java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring Security其它权限校验&自定义权限校验

Spring Security其它权限校验方式&自定义权限校验方式

作者:Maiko Star

这篇文章主要介绍了Spring Security其它权限校验方式&自定义权限校验方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

一、其它权限校验方法(了解)

我们前面都是使用@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攻击也就不用担心了。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文