前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Spring安全表达式控制系统功能访问权限

使用Spring安全表达式控制系统功能访问权限

作者头像
Java_老男孩
发布2019-12-26 17:38:15
9680
发布2019-12-26 17:38:15
举报

一、SPEL表达式权限控制

spring security 3.0开始已经可以使用spring Expression表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。Spring Security可用表达式对象的基类是SecurityExpressionRoot。

表达式函数

描述

hasRole([role])

用户拥有指定的角色时返回true (Spring security默认会带有ROLE_前缀),去除前缀

hasAnyRole([role1,role2])

用户拥有任意一个指定的角色时返回true

hasAuthority([authority])

拥有某资源的访问权限时返回true

hasAnyAuthority([auth1,auth2])

拥有某些资源其中部分资源的访问权限时返回true

permitAll

永远返回true

denyAll

永远返回false

anonymous

当前用户是anonymous时返回true

rememberMe

当前用户是rememberMe用户返回true

authentication

当前登录用户的authentication对象

fullAuthenticated

当前用户既不是anonymous也不是rememberMe用户时返回true

hasIpAddress('192.168.1.0/24'))

请求发送的IP匹配时返回true

部分朋友可能会对Authority和Role有些混淆。Authority作为资源访问权限可大可小,可以是某按钮的访问权限(如资源ID:biz1),也可以是某类用户角色的访问权限(如资源ID:ADMIN)。当Authority作为角色资源权限时,hasAuthority('ROLE_ADMIN')与hasRole('ADMIN')是一样的效果。

二、SPEL在全局配置中的使用

我们可以通过继承WebSecurityConfigurerAdapter,实现相关的配置方法,进行全局的安全配置(之前的章节已经讲过) 。下面就为大家介绍一些如何在全局配置中使用SPEL表达式。

2.1.URL安全表达式

代码语言:javascript
复制
config.antMatchers("/system/*").access("hasAuthority('ADMIN') or hasAuthority('USER')")
      .anyRequest().authenticated();

这里我们定义了应用/person/*URL的范围,只有拥有ADMIN或者USER权限的用户才能访问这些person资源。

2.2.安全表达式中引用bean

这种方式,比较适合有复杂权限验证逻辑的情况,当Spring Security提供的默认表达式方法无法满足我们的需求的时候。首先我们定义一个权限验证的RbacService。

代码语言:javascript
复制
@Component("rbacService")
@Slf4j
public class RbacService {
    //返回true表示验证通过
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        //验证逻辑代码
        return true;
    }
    public boolean checkUserId(Authentication authentication, int id) {
        //验证逻辑代码
        return true;
    }
}

对于"/person/{id}"对应的资源的访问,调用rbacService的bean的方法checkUserId进行权限验证,传递参数为authentication对象和person的id。该id为PathVariable,以#开头表示。

代码语言:javascript
复制
config.antMatchers("/person/{id}").access("@rbacService.checkUserId(authentication,#id)")
      .anyRequest().access("@rbacService.hasPermission(request,authentication)");

三、 Method表达式安全控制

如果我们想实现方法级别的安全配置,Spring Security提供了四种注解,分别是@PreAuthorize , @PreFilter , @PostAuthorize@PostFilter

3.1.开启方法级别注解的配置

在Spring安全配置代码中,加上EnableGlobalMethodSecurity注解,开启方法级别安全配置功能。

代码语言:javascript
复制
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

3.2 使用PreAuthorize注解

@PreAuthorize 注解适合进入方法前的权限验证。只有拥有ADMIN角色才能访问findAll方法。

代码语言:javascript
复制
@PreAuthorize("hasRole('ADMIN')")
List<Person> findAll();

3.3 使用PostAuthorize注解

@PostAuthorize 在方法执行后再进行权限验证,适合根据返回值结果进行权限验证。Spring EL 提供返回对象能够在表达式语言中获取返回的对象returnObject。下文代码只有返回值的name等于authentication对象的name才能正确返回,否则抛出异常。

代码语言:javascript
复制
@PostAuthorize("returnObject.name == authentication.name")
Person findOne(Integer id);

3.4 使用PreFilter注解

PreFilter 针对参数进行过滤,下文代码表示针对ids参数进行过滤,只有id为偶数才能访问delete方法。

代码语言:javascript
复制
//当有多个对象是使用filterTarget进行标注
@PreFilter(filterTarget="ids", value="filterObject%2==0")
public void delete(List<Integer> ids, List<String> usernames) {

3.5 使用PostFilter 注解

PostFilter 针对返回结果进行过滤,特别适用于集合类返回值,过滤集合中不符合表达式的对象。

代码语言:javascript
复制
@PostFilter("filterObject.name == authentication.name")
List<Person> findAll();

欢迎关注公众号:老男孩的成长之路,精选干货每周定期奉上!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、SPEL表达式权限控制
  • 二、SPEL在全局配置中的使用
    • 2.1.URL安全表达式
      • 2.2.安全表达式中引用bean
      • 三、 Method表达式安全控制
        • 3.1.开启方法级别注解的配置
          • 3.2 使用PreAuthorize注解
            • 3.3 使用PostAuthorize注解
              • 3.4 使用PreFilter注解
                • 3.5 使用PostFilter 注解
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档