SpringSecurity(二十四):基于方法的权限管理

基于方法的权限管理主要是通过AOP实现的 Spring Security中通过MethodSecurityInterceptor来提供相关的实现,不同在于FilterSecurityInterceptor只是在请求之前进行前置处理,MethodSecurityInterceptor除了前置处理之外还可以进行后置处理,前置处理就是在前请之前判断是否具有相应的权限,后置处理就是对方法的执行结果进行二次过滤,前置处理和后置处理分别对应了不同的实现类,我们分别来看

注解介绍

目前在Spring Boot中基于方法的权限管理主要是通过注解来实现,我们需要通过@EnableGlobalMethodSecurity注解开启权限注解的使用,方法如下:

@EnableGlobalMethodSecurity(prePostEnabled=true,securedEnabled=true,jsr250Enabled=true)

这个注解中我们设置了三个属性:
prePostEnabled:开启Spring Security提供的四个权限注解,@PostAuthorize ,@PostFilter,@PreAuthorize,@PreFilter,这四个注解支持权限表达式,功能比较丰富
securedEnabled:开启Spring Security提供的@Secured注解,该注解不支持权限表达式
jsr250Enabled:开启JSR-250提供的注解,主要包括@DenyAll,@PermitAll 以及@RolesAllowed三个注解,这些注解也不支持权限表达式

这些注解的含义如下:

@PostAuthorize:在目标方法执行之后进行权限校验

@PostFilter:在目标方法执行之后对方法的返回结果进行过滤

@PreAuthorize:在目标方法执行之前进行权限校验

@PreFilter:在目标方法执行之前对方法参数进行过滤

@Secured:访问目标方法必须具备相应的角色

@DenyAll:拒绝所有访问

@PermitAll:允许所有访问

@RolesAllowed:访问目标方法必须具备相应的角色

一般来说,这要设置prePostEnabled=true就足够了

示例

@Service
public class HelloService {
    @PreAuthorize("principal.username.equals('javaboy')")
    public String hello() {
        return "hello";
    }

    @PreAuthorize("hasRole('admin')")
    public String admin() {
        return "admin";
    }

    @Secured({"ROLE_user"})
    public String user() {
        return "user";
    }

    @PreAuthorize("#age>98")
    public String getAge(Integer age) {
        return String.valueOf(age);
    }
}

第一个 hello 方法,注解的约束是,只有当前登录用户名为 javaboy 的用户才可以访问该方法。
第二个 admin 方法,表示访问该方法的用户必须具备 admin 角色。
第三个 user 方法,表示方法该方法的用户必须具备 user 角色,但是注意 user 角色需要加上 ROLE_ 前缀。
第四个 getAge 方法,表示访问该方法的 age 参数必须大于 98,否则请求不予通过。

可以看到,这里的表达式还是非常丰富,如果想引用方法的参数,前面加上一个 # 即可,既可以引用基本类型的参数,也可以引用对象参数。
缺省对象除了 principal ,还有 authentication(参考之前的权限管理部分)。

Spring Security 中还有两个过滤函数 @PreFilter 和 @PostFilter,可以根据给出的条件,自动移除集合中的元素。

@PostFilter("filterObject.lastIndexOf('2')!=-1")
public List<String> getAllUser() {
    List<String> users = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        users.add("javaboy:" + i);
    }
    return users;
}
@PreFilter(filterTarget = "ages",value = "filterObject%2==0")
public void getAllAge(List<Integer> ages,List<String> users) {
    System.out.println("ages = " + ages);
    System.out.println("users = " + users);
}

在 getAllUser 方法中,对集合进行过滤,只返回后缀为 2 的元素,filterObject 表示要过滤的元素对象。
在 getAllAge 方法中,由于有两个集合,因此使用 filterTarget 指定过滤对象。

posted @ 2021-05-30 22:11  刚刚好。  阅读(366)  评论(0)    收藏  举报