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 指定过滤对象。

浙公网安备 33010602011771号