您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来~
前面的方法中,除了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进行测试的时候就能看到,现在的提示现在已经比刚才要友好了。
感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~
本篇博文目录:一.SpringSecurity简介1.SpringSecurity2.SpringSecurity相关概念二.认证和授权1.认证(1)使用SpringSecurity进行简单的认证(SpringBoot项目中)(2)SpringSecurity的原理(3)SpringSecurity核心类(4)认证登入案例(JWT+SpringSecurity实现登入案例)2.授权(1)加入权限到Authentication中(2)SecurityConfig配置文件中开启注解权限配置(3)给接口中的方法添加访问权限(4)用户权限表的建立3.自定义失败处理(1)创建异常处理类(2)配置移除处理
目录springSecurity授权权限管理策略基于url的权限管理基于方法的权限管理将url权限管理设为动态会话管理会话并发管理会话失效处理禁止再次登录会话共享源码分析CSRF跨站请求伪造开启CSRF防御传统web开发前后端分离开启CSRF防护csrf防御过程CORS跨域问题springBoot解决跨域的三种方式springSecurity解决跨域springSecurity授权认证与授权解耦授权:据系统提前设置好的规则,给用户分配可以访问某一个资源的权限,用户根据自己所具有权限,去执行相应操作。GrantedAuthority应该如何理解呢?是角色还是权限?权限是具体一些操作,角色是一些权
问题描述在做项目的时候,使用SpringSecurity配置完系统的访问权限时,进行测试的时候,发现明明携带了访问该路径需要的权限标志,会一直提示说我们权限不足。这里我配置了AccessDeniedHandler,当SpringSecurity判断我们权限不足时,会抛出AccessDeniedException异常,然后执行AccessDeniedHandler中我们重写的的handle方法。解决实在想不出原因的时候,我开始着手从源码去探究报错的原因,于是我从网上找来了这张图,授权测试流程:如图所示,首页请求先会进入FilterSecurityInterceptor过滤器,将它作为断点的入口。
SpringBoot集成SpringSecurity+MySQL+JWT附源码,废话不多直接盘SpringBoot已经为用户采用默认配置,只需要引入pom依赖就能快速启动SpringSecurity。目的:验证请求用户的身份,提供安全访问优势:基于Spring,配置方便,减少大量代码内置访问控制方法permitAll()表示所匹配的URL任何人都允许访问。authenticated()表示所匹配的URL都需要被认证才能访问。anonymous()表示可以匿名访问匹配的URL。和permitAll()效果类似,只是设置为anonymous()的url会执行filter链中denyAll()表示所
说明SpringSecurityOAuth2单点登录昨天我发了一个单点登录版本的验证博客,到今天早上我再研究了一下,发现了一些问题:昨天那个单点登录是在每个模块的基础上做的,也就是说如果你想让每个模块都如认证中心认证,就要在每个模块里进行相关配置,这还不是最紧要的,你要想想,因为我们是通过注解的方式在对应的方法鉴权,这样的话就会导致我们每次访问这个方法的时候就要去认证中心请求一次,也就是鉴权一次,那么整个系统模块又多,路径又多,认证中心肯定是吃不消的啊.所以在这个基础上,就需要去将认证中心在第一次认证产生的token,交给前端,然后在GateWay里进行一个token的验证,这样子就避免我们每
特别注意:以下内容如果访问失败或有其他疑问,可先学习:SpringSecurity+oauth2+JWT实现统一授权和认证及项目搭建(一)1获取当前用户的信息代码为:Objectprincipal=SecurityContextHolder.getContext().getAuthentication().getPrincipal();但是,通过运行会发现principal的值只是用户名,没有用户信息,通过去看源码,才发现问题所在,以下是源码:源码类:DefaultUserAuthenticationConverter.java通过源码分析,发现这里的map只存储用户名,对此,如果要获取用户,
文章目录前言一、SpringSecurity简介二、Shiro和Security的对比2.1Shiro的特点2.2Security的特点2.3二者的相同点三、Security实现权限四、用户认证流程4.1认证接口分析前言Web应用的开发,安全是至关重要的,选择使用SpringSecurity是目前来说较为正确的选择。SpringSecurity框架起源于2003年年底acegi系统,起因是Spring开发者邮件列表中的一个问题,有人提问是否考虑提供一个基于Spring的安全实现。基于SpringBoot+MP+Redis+Vue实现的前后端分离的权限管理系统:https://gitee.com
一、SpringSecurity的功能简单介绍(1)简介SpringSecurity是针对Spring项目的安全框架,也是SpringBoot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理! 主要的几个类:webSecurityConfigurerAdapter:自定义Security策略AuthenticationManagerBuilder:自定义的认证策略@EnableWebSecurity:开启WebSecurity模式 Spring
SpringSecurity安全框架学习——@PreAuthorize的实现原理@PreAuthorize@EnableMethodSecurityMethodSecuritySelectorPrePostMethodSecurityConfiguration@PreAuthorize首先我们打开@PreAuthorize注解的源码,然后按住Ctrl并单击PreAuthorize,可以看到在EnableMethodSecurity注解中有引用(本文使用IDEA,后续不再复述)@EnableMethodSecurity查看EnableMethodSecurity源码,可以到,其引用了Method
springboot整合springsecurity+oauth2.0本文采用的springboot去整合springsecurity,采用oauth2.0授权认证,使用jwt对token增强。本文仅为学习记录,如有不足多谢提出。OAuth2简介OAuth2.0是用于授权的行业标准协议。OAuth2.0为简化客户端开发提供了特定的授权流,包括Web应用、桌面应用、移动端应用等。OAuth2相关名词解释Resourceowner(资源拥有者):拥有该资源的最终用户,他有访问资源的账号密码;Resourceserver(资源服务器):拥有受保护资源的服务器,如果请求包含正确的访问令牌,可以访问资源