Spring Security(4)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~
前面的方法中,除了login()方法能成功,另外两个都失败,并不是因为代码问题,而是Spring Security默认是通过Web页面来实现页面逻辑跳转的。但在前后端分离的开发模式中,页面跳转的逻辑后端已经无法直接控制了,而是通过返回状态码由前端来执行跳转。因此,需要对应用进行改造。
首先自定义认证成功处理器,也就是实现AuthenticationSuccessHandler接口:
/**
* 自定义认证成功处理器
*
* @author 湘王
*/
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
System.out.println("登录成功"); // 前后端分离的调用方式
response.setStatus(HttpStatus.OK.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("OK");
}
}
接着来实现之前没有的认证失败处理器AuthenticationFailureHandler:
/**
* 自定义认证失败处理器
*
* @author 湘王
*/
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
System.out.println("user or password error"); // 前后端分离的调用方式
response.setStatus(HttpStatus.OK.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("user or password error");
}
}
再实现登出处理器LogoutSuccessHandler:
/**
* 自定义登出处理器
*
* @author 湘王
*/
@Component
public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
System.out.println("登出成功"); // 前后端分离的调用方式
response.setStatus(HttpStatus.OK.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("OK");
}
}
然后修改之前的修改WebSecurityConfiguration,让过滤器中增加对这几个处理器的支持:
// 控制逻辑
@Override
protected void configure(HttpSecurity http) throws Exception {
// 执行UsernamePasswordAuthenticationFilter之前添加拦截过滤
http.addFilterBefore(new CustomInterceptorFilter(), UsernamePasswordAuthenticationFilter.class); http.authorizeRequests()
.anyRequest().authenticated()
// 设置自定义认证成功、失败及登出处理器
.and().formLogin().loginPage("/login")
.successHandler(successHandler).failureHandler(failureHandler).permitAll()
.and().logout().logoutUrl("/logout").deleteCookies("JSESSIONID")
.logoutSuccessHandler(logoutSuccessHandler).permitAll()
// 跨域访问
.and().cors()
.and().csrf().disable();
}
现在再次测试LoginController中的登录和登出操作,可以看到它们都能成功执行。目前权限已经做到了与Controller中的业务逻辑无关了。
但是仅仅做到登录、登出操作肯定是不行的,这连Demo都不如。所以接下里,来看看一个比较核心的问题:用户角色是否有效(不然建角色表干嘛)。
先在LoginController类中加入下面两个方法:
@GetMapping("/admin")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String admin() {
return "admin有ROLE_ADMIN角色";
}
@GetMapping("/manager")
@PreAuthorize("hasRole('ROLE_MANAGER')")
public String manager() {
return "manager有ROLE_MANAGER角色";
}
启动应用,运行postman时会发现:
1、用admin登录,访问localhost:8080/admin正常,但访问localhost:8080/manager就出现Forbidden错误;
2、用manager登录,访问localhost:8080/manager正常,而访问localhost:8080/admin也出现Forbidden错误。
这说明用户角色权限已经起作用了,但显示Forbidden的方式不够友好。所以再来增加一个自定义处理器,也就是实现AccessDeniedHandler接口,让访问拒绝友好一些:
/**
* 自定义访问被拒绝
*
* @author 湘王
*/
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException exception) throws IOException, ServletException {
System.out.println("permission denied"); // 前后端分离的调用方式
response.setStatus(HttpStatus.OK.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("permission denied");
}
}
然后同样地,要在WebSecurityConfiguration过滤器链中增加这个新增的过滤器:
// 控制逻辑
@Override
protected void configure(HttpSecurity http) throws Exception {
// 执行UsernamePasswordAuthenticationFilter之前添加拦截过滤
http.addFilterBefore(new CustomInterceptorFilter(), UsernamePasswordAuthenticationFilter.class); http.authorizeRequests()
.anyRequest().authenticated()
// 设置自定义认证成功、失败及登出处理器
.and().formLogin().loginPage("/login")
.successHandler(successHandler).failureHandler(failureHandler).permitAll()
.and().logout().logoutUrl("/logout").deleteCookies("JSESSIONID")
.logoutSuccessHandler(logoutSuccessHandler).permitAll()
// 配置无权访问的自定义处理器
.and().exceptionHandling().accessDeniedHandler(accessDeniedHandler)
.and().cors()
.and().csrf().disable();
}
再用postman进行测试的时候就能看到,现在的提示现在已经比刚才要友好了。
感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~
Spring Security(4)的更多相关文章
- Spring Security(08)——intercept-url配置
http://elim.iteye.com/blog/2161056 Spring Security(08)--intercept-url配置 博客分类: spring Security Spring ...
- Spring Security(三)
Spring Security(三) 个性化用户认证流程 自定义登录页面 在配置类中指定登录页面和接收登录的 url @Configuration public class BrowserSecuri ...
- Spring Security(二)
Spring Security(二) 注:凡是源码部分,我已经把英文注释去掉了,有兴趣的同学可以在自己项目里进去看看.:-) 定义用户认证逻辑 用户登录成功后,用户的信息会被 Security 封装在 ...
- Spring Security(一)
Spring Security(一) 基本原理 前言 Spring Security核心功能 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) Srping Security基本原理 项目 ...
- 【权限管理系统】Spring security(三)---认证过程(原理解析,demo)
在前面两节Spring security (一)架构框架-Component.Service.Filter分析和Spring Security(二)--WebSecurityConfigurer配 ...
- SpringBoot集成Spring Security(7)——认证流程
文章目录 一.认证流程 二.多个请求共享认证信息 三.获取用户认证信息 在前面的六章中,介绍了 Spring Security 的基础使用,在继续深入向下的学习前,有必要理解清楚 Spring Sec ...
- SpringBoot集成Spring Security(6)——登录管理
文章目录 一.自定义认证成功.失败处理 1.1 CustomAuthenticationSuccessHandler 1.2 CustomAuthenticationFailureHandler 1. ...
- SpringBoot集成Spring Security(5)——权限控制
在第一篇中,我们说过,用户<–>角色<–>权限三层中,暂时不考虑权限,在这一篇,是时候把它完成了. 为了方便演示,这里的权限只是对角色赋予权限,也就是说同一个角色的用户,权限是 ...
- SpringBoot集成Spring Security(4)——自定义表单登录
通过前面三篇文章,你应该大致了解了 Spring Security 的流程.你应该发现了,真正的 login 请求是由 Spring Security 帮我们处理的,那么我们如何实现自定义表单登录呢, ...
- SpringBoot集成Spring Security(2)——自动登录
在上一章:SpringBoot集成Spring Security(1)——入门程序中,我们实现了入门程序,本篇为该程序加上自动登录的功能. 文章目录 一.修改login.html二.两种实现方式 2. ...
随机推荐
- IO_对象流
对象流 对象的本质是用来组织和存储数据的,对象本身也是数据.那么,能不能将对象存储到硬盘上的文件中呢?能不能将对象通过网络传输到另一个电脑呢?我们可以通过序列化和反序列化实现. java对象的序列化和 ...
- C# 脚本与Unity Visual Scripting 交互,第一步(使用C# 脚本触发Script Graph的事件)(Custom Scripting Event)
写在前面 感谢Unity 川哥的帮助,解决了单独调用GameObject的需求 首先 需要在Unity 中创建一个自定义事件脚本(注释非常重要) using System.Collections; u ...
- CVE-2022-39197(CobaltStrike XSS <=4.7)漏洞复现
最新文章更新见个人博客 漏洞说明 根据9.20日CobaltStrike官方发布的最新4.7.1版本的更新日志中介绍,<=4.7的teamserver版本存在XSS漏洞,从而可以造成RCE远程代 ...
- (二)JPA 连接工厂、主键生成策略、DDL自动更新
(一)JPA的快速入门 2.JPA连接工厂 通过之前的 代码 实现已经清楚的发现了整个的JPA实现步骤,但是这个步骤似乎有一些繁琐了,毕竟最终所关心的一定是EntityManager对象实例,而要想获 ...
- 第四章:Django表单 - 1:使用表单
假设你想从表单接收用户名数据,一般情况下,你需要在HTML中手动编写一个如下的表单元素: <form action="/your-name/" method="po ...
- Security Context
概述 Security Context(安全上下文)用来限制容器对宿主节点的可访问范围,以避免容器非法操作宿主节点的系统级别的内容,使得节点的系统或者节点上其他容器组受到影响. Security Co ...
- Elasticsearch部署清单---前期准备工作
1.了解ES集群拓扑结构 当我们启动Elasticsearch的实例,就会启动至少一个节点.相同集群名的多个节点的连接组成一个集群, 在默认情况下,集群中的每个节点都可以处理Http请求和集群节点的数 ...
- 【机器学习】利用 Python 进行数据分析的环境配置 Windows(Jupyter,Matplotlib,Pandas)
环境配置 安装 python 博主使用的版本是 3.10.6 在 Windows 系统上使用 Virtualenv 搭建虚拟环境 安装 Virtualenv 打开 cmd 输入并执行 pip inst ...
- 小白转行入门STM32----手机蓝牙控制STM32单片机点亮LED
@ 目录 引言导读 一.通信基础知识 1.1 通信到底传输的是什么? 1.2 比特率和波特率 习题 1.1 双工和单工 习题 1.2 串行和并行 1.3 异同通信和同步通信 习题 二.连接STM32单 ...
- MFC-创建MFC图形界面dll
创建MFC图形界面dll 概述: 利用MFC的DLL框架,制作带有图形界面的dll,可以实现很多功能. 流程: 选择静态链接MFC DLL:以免有的库没有. 采用该框架创建的MFC,会自动生产一个MF ...