一、请求参数名设置

之前的表单信息有一些要求:

1、action属性发送的地址是Security设置的URL

2、发送的请求方式是POST

3、请求的账户信息,也就是表单发送的参数,必须对应的是username & password

原因是因为这个过滤器类:

org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

和下面的方法:

如果要改变默认的请求参数,可以设置:

package cn.zeal4j.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password"
).
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求 httpSecurity.authorizeRequests().
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable();
}
}

二、前后端分离登陆成功页的跳转:

问题的产生:

使用默认successForwardUrl并不能用来跳转到外部地址,也就是跨域访问

例如这样设置成功登陆页进行跳转:

successForwardUrl("http://www.baidu.com")

方法分析:

successForwardUrl方法的实现:

public FormLoginConfigurer<H> successForwardUrl(String forwardUrl) {
this.successHandler(new ForwardAuthenticationSuccessHandler(forwardUrl));
return this;
}

内部是调用了一个成功处理器方法,并且注入了一个跳转授权成功处理器对象,构造参数又是这个要登录的页面URL

跳转授权成功处理器类:

package org.springframework.security.web.authentication;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert; public class ForwardAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private final String forwardUrl; public ForwardAuthenticationSuccessHandler(String forwardUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> {
return "'" + forwardUrl + "' is not a valid forward URL";
});
this.forwardUrl = forwardUrl;
} public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
request.getRequestDispatcher(this.forwardUrl).forward(request, response);
}
}

可以看到下面的这个方法是将URL进行转发处理的,所以像跨域处理的是没有办法解决的

这个处理器类是实现了一个接口:

org.springframework.security.web.authentication.AuthenticationSuccessHandler 

接口的方法:

package org.springframework.security.web.authentication;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication; public interface AuthenticationSuccessHandler {
default void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
this.onAuthenticationSuccess(request, response, authentication);
chain.doFilter(request, response);
} void onAuthenticationSuccess(HttpServletRequest var1, HttpServletResponse var2, Authentication var3) throws IOException, ServletException;
}

也就是说,我们可以通过自己写一个类实现这个接口,单独处理前后端分离的重定向登陆URL

package cn.zeal4j.handler;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 23:48
* 前后端分离url登陆处理 Front and rear separation (FARS)
*/
public class FarsAuthenticationSuccessHandler implements AuthenticationSuccessHandler { private String url; public FarsAuthenticationSuccessHandler(String url) {
this.url = url;
} @Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.sendRedirect(url);
}
// @Override
// public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
//
// }
}

改写登陆成功页面URL的方法:

package cn.zeal4j.configuration;

import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password").
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
// successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆

failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求 httpSecurity.authorizeRequests().
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable();
}
}

参数Authentication可以获取登陆账户的信息:

package cn.zeal4j.handler;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 23:48
* 前后端分离url登陆处理 Front and rear separation (FARS)
*/
public class FarsAuthenticationSuccessHandler implements AuthenticationSuccessHandler { private String url; public FarsAuthenticationSuccessHandler(String url) {
this.url = url;
} @Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { Object principal = authentication.getPrincipal();
User user = (User) principal;
Collection<GrantedAuthority> authorities = user.getAuthorities();
System.out.println(user.getUsername());
System.out.println(user.getPassword());
for
(GrantedAuthority authority : authorities) {
System.out.println(authority.getAuthority());
}
httpServletResponse.sendRedirect(url);
} // @Override
// public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
//
// }
}

打印结果:

admin
null
admin
normal

密码输出NULL是因为Security的保护限制?

三、前后端分离登陆失败页的跳转:

有成功页面的跳转,对应的就有失败页面的跳转

public FormLoginConfigurer<H> failureForwardUrl(String forwardUrl) {
this.failureHandler(new ForwardAuthenticationFailureHandler(forwardUrl));
return this;
}

也是同样的方法和类似的对象和相同的注入方式

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
// package org.springframework.security.web.authentication; import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert; public class ForwardAuthenticationFailureHandler implements AuthenticationFailureHandler {
private final String forwardUrl; public ForwardAuthenticationFailureHandler(String forwardUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> {
return "'" + forwardUrl + "' is not a valid forward URL";
});
this.forwardUrl = forwardUrl;
} public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
request.setAttribute("SPRING_SECURITY_LAST_EXCEPTION", exception);
request.getRequestDispatcher(this.forwardUrl).forward(request, response);
}
}

所以要实现跨域跳转,一样是实现上面的接口,除了跳转,该方法还要求携带异常对象

自定义实现类

package cn.zeal4j.handler;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 28 3:44
*/
public class FarsAuthenticationFailureHandler implements AuthenticationFailureHandler { private String url; public FarsAuthenticationFailureHandler(String url) {
this.url = url;
} @Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
// 因为跨域,无法携带异常对象
httpServletResponse.sendRedirect(url);
}
}

更改Security跳转配置:

package cn.zeal4j.configuration;

import cn.zeal4j.handler.FarsAuthenticationFailureHandler;
import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password").
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
// successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆
// failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求
failureHandler(new FarsAuthenticationFailureHandler("/error.html")); // 跨域处理,不需要跳转了
httpSecurity.authorizeRequests().
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable();
}
}

登陆控制器的跳转方法就不需要了

package cn.zeal4j.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 22:35
*/ @Controller
public class LoginController { @RequestMapping("main.page")
public String toMainPage() {
return "main"; // 模版内的页面不允许重定向,忘了忘了
} @PostMapping("error.page") // 控制器不支持POST请求跳转解析, 需要控制器跳转 Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
public String redirectToErrorPage() {
return "redirect:/error.html"; // 重定向要写/标识 区分模版解析
}
}

【Spring-Security】Re03 认证参数修改与跨域跳转处理的更多相关文章

  1. Spring Security 接口认证鉴权入门实践指南

    目录 前言 SpringBoot 示例 SpringBoot pom.xml SpringBoot application.yml SpringBoot IndexController SpringB ...

  2. 最简单易懂的Spring Security 身份认证流程讲解

    最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...

  3. Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理

    本文完整代码下载点击 一. 前言 相信了解过我或者看过我之前的系列文章应该多少知道点我写这些文章包括创建 有来商城youlai-mall 这个项目的目的,想给那些真的想提升自己或者迷茫的人(包括自己- ...

  4. Spring Security 自定义认证逻辑

    Spring Security 自定义认证逻辑 这篇文章的内容基于对Spring Security 认证流程的理解,如果你不了解,可以读一下这篇文章:Spring Security 认证流程 . 分析 ...

  5. 170222、使用Spring Session和Redis解决分布式Session跨域共享问题

    使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...

  6. 使用Spring Session和Redis解决分布式Session跨域共享问题

    http://blog.csdn.net/xlgen157387/article/details/57406162 使用Spring Session和Redis解决分布式Session跨域共享问题

  7. 【基础】Html跨域跳转问题整理

    今天遇到一个问题,是有关 跨域跳转问题,涉及到知识比较基础. 具体问题是:  A站点的 PageA (Post数据)到 B站点的 PageB,PageB接受到后Redirect到B站的 PageC:  ...

  8. 学习Spring Boot:(二十八)Spring Security 权限认证

    前言 主要实现 Spring Security 的安全认证,结合 RESTful API 的风格,使用无状态的环境. 主要实现是通过请求的 URL ,通过过滤器来做不同的授权策略操作,为该请求提供某个 ...

  9. Spring Security 安全认证

    Spring Boot 使用 Mybatis 依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> ...

  10. Spring Security 入门(1-5)Spring Security - 匿名认证

    匿名认证 对于匿名访问的用户,Spring Security 支持为其建立一个匿名的 AnonymousAuthenticationToken 存放在 SecurityContextHolder 中, ...

随机推荐

  1. react移动端组件antd-mobile

    使用react移动端组件antd-mobile完成底部导航功能实现. 官网:https://mobile.ant.design/docs/react/introduce-cn antd-mobile ...

  2. 开发视频会议系统:使用GPU解码渲染视频

    现在,使用视频会议系统远程协同办公.沟通交流,已经非常普遍了.如果我们要开发自己的视频会议系统,那么,GPU解码渲染技术是不可缺少的. 在视频会议系统中,经常需要同时观看会议中多个参会人员的视频图像, ...

  3. LeetCode 409. Longest Palindrome 最长回文串(C++/Java)

    题目: Given a string which consists of lowercase or uppercase letters, find the length of the longest ...

  4. P7322

    P7322 好神仙! \(\color{#5bc9}\text{提醒,本文有大量没有推到过程的式子,所以读者可以自己遮住先推一下}\) Inscription: 有一个长度为 \(k\) 的窗口,在一 ...

  5. .net core .net6 webapi 连接mysql 8

    1.表结构: CREATE TABLE `table2` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `myname` varchar(255) NOT NULL, ...

  6. Scrapy框架(六)--图片数据抓取

    基于文件下载的管道类 在scrapy中我们之前爬取的都是基于字符串类型的数据,那么要是基于图片数据的爬取,那又该如何呢? 其实在scrapy中已经为我们封装好了一个专门基于图片请求和持久化存储的管道类 ...

  7. Selenium模块的使用(一)

    简介 selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器, 完全模拟浏览器的操作,比 ...

  8. 《Android开发卷——开卷》

    打算在自己在工作中遇到的问题,技术难点都记录下来,让其他人可以借鉴或者指点,这样既可以成长自己也可以成长别人.因为自己已经在工作了,所以遇到的问题非常具有代表性,所以不能简单简单的像网上一些小学生一样 ...

  9. 解决 Xshell 无法使用 zsh 的 prompt style

    为了更好的阅读体验,请点击这里 先学习一下 zsh 的配置吧~ 参考资料 从 0 开始:教你如何配置 zsh powerlevel10k 如何给 Xshell 配置呢 当我安装完 oh-my-zsh. ...

  10. BST-splay板子 - 维护一个分裂和合并的序列

    splay 均摊复杂度 \(O(\log n)\) 证明: https://www.cnblogs.com/Mr-Spade/p/9715203.html 我这个 splay 有两个哨兵节点,分别是1 ...