【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 中, ...
随机推荐
- boss直聘__zp_stoken__逆向
声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 目标网站 aHR0cHM6 ...
- [SWPUCTF 2021 新生赛]easy_md5
打开靶场可以看到一串代码,进行代码审计我们可以知道这个网页包含了一个叫flag2.php的文件,如果想要得到这个文件就得进行GET传参和POST传参. 并且这里用到一个MD5绕过,传参的值不能相等,但 ...
- java.io.File类中分隔符区别
1.separator File.separator是系统默认的文件分隔符号,在UNIX系统上,这个字段的值是'/';在Microsoft Windows系统上,它是''. 类型:String 2.s ...
- 使用 Filebeat+Easysearch+Console 打造日志管理平台
近年来,日志管理平台越来越流行.使用日志管理平台可以实时地.统一地.方便地管理和查看日志,挖掘日志数据价值,驱动运维.运营,提升服务管理效率. 方案架构 Beats 是轻量级采集器,包括 Filebe ...
- Vue学习:20.综合案例-商品列表
学而时用之,方能融会贯通! 实例:商品列表 实现功能 要求表格组件支持动态数据渲染.自定义表头和主体.标签组件需要双击显示输入框并获得焦点,可以编辑标签信息. 思路 首先是表格组件,动态渲染需要使用组 ...
- OpenCV + sklearnSVM 实现手写数字分割和识别
这学期机器学习考核方式以大作业的形式进行考核,而且只能使用一些传统的机器学习算法. 综合再三,选择了自己比较熟悉的MNIST数据集以及OpenCV来完成手写数字的分割和识别作为大作业. 1. 数据集准 ...
- 使用嵌套的ScriptableObject及ReorderableList创建习题持久化数据
使用嵌套的ScriptableObject及ReorderableList创建习题持久化数据 效果展示 题集持久化数据:存储题目,可以直接在inspector面板上创建对应的问题子项 问题持久化数据 ...
- 05-Python函数
函数定义与调用 函数由以下几个部分组成: 函数名 函数参数 函数体 返回值 定义一个函数: def showMyName(name): #定义函数 print(name) showMyName(&qu ...
- HDD成都站:HMS Core 6.0带来新可能,多元服务驱动产品价值提升
9月10日,由华为开发者联盟主办的HDD(Huawei Developer Day)于成都举行.活动中,华为HMS Core各领域专家重点解读了HMS Core 6.0为开发者带来的多项全新能力,及生 ...
- Linux 内核:设备树(3)把device_node转换成platfrom_device
Linux 内核:设备树(3)把device_node转换成platfrom_device 背景 在上一节中讲到设备树dtb文件中的各个节点转换成device_node的过程(<dtb转换成de ...