Spring Security其它权限校验方式&自定义权限校验方式
作者:Maiko Star
一、其它权限校验方法(了解)
我们前面都是使用@PreAuthorize注解,然后在在其中使用的是hasAuthority方法进行校验。
SpringSecurity还为我们提供了其它方法例如:hasAnyAuthority,hasRole,hasAnyRole等。
这里我们先不急着去介绍这些方法,我们先去理解hasAuthority的原理,然后再去学习其他方法你就更容易理解,而不是死记硬背区别。并且我们也可以选择定义校验方法,实现我们自己的校验逻辑。
hasAuthority方法实际是执行到了SecurityExpressionRoot的hasAuthority,大家只要断点调试既可知道它内部的校验原理。
它内部其实是调用authentication的getAuthorities方法获取用户的权限列表。然后判断我们在接口上定义的权限是否被包含于用户的权限列表,如果有则返回true放行,反之false拦截。
hasAnyAuthority方法可以传入多个权限,只有用户有其中任意一个权限都可以访问对应资源。
@PreAuthorize("hasAnyAuthority('admin','test','system:dept:list')") public String hello(){ return "hello"; }
hasRole要求有对应的角色才可以访问,但是它内部会把我们传入的参数拼接上 ROLE_ 后再去比较。
所以这种情况下要用用户对应的权限也要有 ROLE_ 这个前缀才可以。
@PreAuthorize("hasRole('system:dept:list')") public String hello(){ return "hello"; }
hasAnyRole 有任意的角色就可以访问。它内部也会把我们传入的参数拼接上 ROLE_ 后再去比较。
所以这种情况下要用用户对应的权限也要有 ROLE_ 这个前缀才可以。
@PreAuthorize("hasAnyRole('admin','system:dept:list')") public String hello(){ return "hello"; }
二、自定义权限校验方法(掌握)
我们也可以定义自己的权限校验方法,在@PreAuthorize注解中使用我们的方法。
@Component("ex") public class SGExpressionRoot { public boolean hasAuthority(String authority) { //获取当前用户的权限 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); LoginUser loginUser = (LoginUser) authentication.getPrincipal(); List<String> permissions = loginUser.getPermissions(); //判断用户权限集合中是否存在authority return permissions.contains(authority); } }
在SPEL表达式中使用 @ex相当于获取容器中bean的名字未ex的对象。然后再调用这个对象的
hasAuthority方法
@RequestMapping("/hello") @PreAuthorize("@ex.hasAuthority('system:dept:list')") public String hello(){ return "hello"; }
三、基于配置的权限控制
我们也可以在配置类中使用使用配置的方式对资源进行权限控制。
eg:
.antMatchers("/testCors").hasAuthority("system:dept:list222")
@Override protected void configure(HttpSecurity http) throws Exception { http //关闭csrf .csrf().disable() //不通过Session获取SecurityContext .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() // 对于登录接口 允许匿名访问 .antMatchers("/user/login").anonymous() .antMatchers("/testCors").hasAuthority("system:dept:list222") // 除上面外的所有请求全部需要鉴权认证 .anyRequest().authenticated(); //添加过滤器 http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); //配置异常处理器 http.exceptionHandling() //配置认证失败处理器 .authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler); //允许跨域 http.cors(); }
四、CSRF
CSRF是指跨站请求伪造(Cross-site request forgery),是web常见的攻击之一。
SpringSecurity去防止CSRF攻击的方式就是通过csrf_token。后端会生成一个csrf_token,前端发起请求的时候需要携带这个csrf_token,后端会有过滤器进行校验,如果没有携带或者是伪造的就不允许访问。
我们可以发现CSRF攻击依靠的是cookie中所携带的认证信息。但是在前后端分离的项目中我们的认证信息其实是token,而token并不是存储中cookie中,并且需要前端代码去把token设置到请求头中才可以,所以CSRF攻击也就不用担心了。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。