【Spring-Security】Re03 认证参数修改与跨域跳转处理
一、请求参数名设置
之前的表单信息有一些要求:
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 认证参数修改与跨域跳转处理的更多相关文章
- Spring Security 接口认证鉴权入门实践指南
目录 前言 SpringBoot 示例 SpringBoot pom.xml SpringBoot application.yml SpringBoot IndexController SpringB ...
- 最简单易懂的Spring Security 身份认证流程讲解
最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...
- Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理
本文完整代码下载点击 一. 前言 相信了解过我或者看过我之前的系列文章应该多少知道点我写这些文章包括创建 有来商城youlai-mall 这个项目的目的,想给那些真的想提升自己或者迷茫的人(包括自己- ...
- Spring Security 自定义认证逻辑
Spring Security 自定义认证逻辑 这篇文章的内容基于对Spring Security 认证流程的理解,如果你不了解,可以读一下这篇文章:Spring Security 认证流程 . 分析 ...
- 170222、使用Spring Session和Redis解决分布式Session跨域共享问题
使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...
- 使用Spring Session和Redis解决分布式Session跨域共享问题
http://blog.csdn.net/xlgen157387/article/details/57406162 使用Spring Session和Redis解决分布式Session跨域共享问题
- 【基础】Html跨域跳转问题整理
今天遇到一个问题,是有关 跨域跳转问题,涉及到知识比较基础. 具体问题是: A站点的 PageA (Post数据)到 B站点的 PageB,PageB接受到后Redirect到B站的 PageC: ...
- 学习Spring Boot:(二十八)Spring Security 权限认证
前言 主要实现 Spring Security 的安全认证,结合 RESTful API 的风格,使用无状态的环境. 主要实现是通过请求的 URL ,通过过滤器来做不同的授权策略操作,为该请求提供某个 ...
- Spring Security 安全认证
Spring Boot 使用 Mybatis 依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> ...
- Spring Security 入门(1-5)Spring Security - 匿名认证
匿名认证 对于匿名访问的用户,Spring Security 支持为其建立一个匿名的 AnonymousAuthenticationToken 存放在 SecurityContextHolder 中, ...
随机推荐
- mysql 查询差集方法
第一种是通过not in的方式去处理: select id from table_a where id not in (select id from table_b); 第二种则是通过左连接(left ...
- 盘点 Spring Boot 解决跨域请求的几种办法
熟悉 web 系统开发的同学,对下面这样的错误应该不会太陌生. 之所以会出现这个错误,是因为浏览器出于安全的考虑,采用同源策略的控制,防止当前站点恶意攻击 web 服务器盗取数据. 01.什么是跨域请 ...
- Python遥感影像叠加分析:基于一景数据提取另一数据
本文介绍基于Python中GDAL模块,实现基于一景栅格影像,对另一景栅格影像的像元数值加以叠加提取的方法. 本文期望实现的需求为:现有一景表示6种不同植被类型的.tif格式栅格数据,以及另一 ...
- 制作Jdk镜像
本文介绍用Dockerfile的方式构建Jdk镜像,请保证安装了Docker环境. 首先创建/opt/jdk目录,后续步骤都在该目录下进行操作. 准备好Jdk安装文件,放到/opt/jdk目录下. 编 ...
- FFmpeg frei0r插件使用学习
背景 ffmpeg做基本的音视频编辑还是比较简单的,但要做一些滤镜及特效就比较麻烦了.接下来看看借用frei0r插件怎么做: 简介 你可以将frei0r看作是一个"视频特效工具箱" ...
- Python中使用MySQL模糊查询的方法
1.方法一:使用pymysql库的方法 当在Python中使用MySQL进行模糊查询时,我们通常会使用pymysql或mysql-connector-python这样的库来连接MySQL数据库并执行查 ...
- QT学习:03 信号与槽
--- title: framework-cpp-qt-03-信号与槽 EntryName: framework-cpp-qt-03-signal-slot date: 2020-04-09 13:5 ...
- 解决BitBucket仓库较大拉取失败,使用SSH拉取
HTTPS 拉取 如果使用的是https拉取,可使用以下命令尝试,如果还是失败,可使用 ssh 拉取 git clone --depth=1 xxxx.git --depth=1:拉取最近1次提交记录 ...
- .NET 6 Entity Framework Core Db First(2) 增删改查
基础代码 在Program.cs注入DemoContext 新建HomeController,继承ControllerBase 添加Controller特性,[ApiController] [Rout ...
- html2canvas 页面截屏
$(document).ready(function () { $(".example1").on("click", function (event) { va ...