在spring security安全管理框架中,主要注解有
- @EnableGlobalMethodSecurity
- @Secured (角色认证)
- @PreAuthorize(访问方法之前进行 权限或角色 认证)
- @PostAuthorize(访问方法之后进行 权限或角色 认证)
- @PreFilter (过滤参数集合)
- @PostFilter (过滤返回值集合)
@EnableGlobalMethodSecurity
当我们需要使用 spring security 中的注解,只需要在启动类(配置类)开启注解@EnableGlobalMethodSecurity 就能达到目的。同时这个注解为我们提供了prePostEnabled 、securedEnabled 和 jsr250Enabled 三种不同的机制来实现同一种功能,其三种机制默认值均为false:
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true,jsr250Enabled = true)
- 机制一:prePostEnabled
prePostEnabled = true 会解锁 @PreAuthorize 和 @PostAuthorize 两个注解 - 机制二:securedEnabled
securedEnabled =true会解锁@Secured注解 - 机制三: jsr250Enabled
jsr250Enabled=true 启用 JSR-250 安全控制注解,这属于 JavaEE 的安全规范(现为 jakarta 项目)。一共有五个安全注解。
如果你在 @EnableGlobalMethodSecurity 设置 jsr250Enabled 为 true ,就开启了 JavaEE 安全注解中的以下三个:
-
@DenyAll: 拒绝所有访问
-
@RolesAllowed({“USER”, “ADMIN”}): 该方法只要具有"USER", "ADMIN"任意一种权限就可以访问。这里可以省略前缀ROLE_,实际的权限可能是ROLE_ADMIN
-
@PermitAll: 允许所有访问
@Secured
@Secured注解的作用:在用户向浏览器发送一个请求时会去访问控制器中的方法,然后在访问此控制器中的方法之前会先去UserDetailsService用户细节实现类的实现方法中return的User对象查看是否具有@Secured注解中指定的角色,如果有指定的角色,那么系统允许用户访问此控制器方法,否则,系统不允许访问此控制器方法;注意在使用@Secured设置角色名字的时候,角色名的前面一定要加上ROLE_前缀;
UserDetailsService用户细节实现类中的情况如下图:
UserDetailsService中的用户具有ROLE_user角色,因此可以访问控制器中的update方法
@PreAuthorize
@PreAuthorize注解会在方法执行前进行验证,而 @PostAuthorize 注解会在方法执行后进行验证
@PreAuthorize注解的作用:在浏览器发送一个请求后,会访问控制器中的对应的方法,@PreAuthorize注解会在访问控制器中的方法之前进行 权限或角色 认证,看看UserDetailsService用户细节实现类中对应的用户有没有相应的 权限或角色,如果有那么该用户发送的请求可以进入控制器中对应的方法,如果没有相应的权限或角色,那么用户发送的请求不能进去控制器中对应的方法
权限认证:
@GetMapping("/update")
// 单个权限认证 hasAuthority()
// @PreAuthorize("hasAuthority('admins')")
// 多个权限认证 hasAnyAuthority()
@PreAuthorize("hasAnyAuthority('admins,person')")
public String update(){
return "update";
}
角色认证:
@GetMapping("/update")
// 单个角色 hasRole()
// @PreAuthorize("hasRole('ROLE_user')")
// 多个角色 hasAnyRole()
@PreAuthorize("hasAnyRole('ROLE_user,Role_admin')")
public String update(){
return "update";
}
@PostAuthorize
@PostAuthorize注解使用不多,在方法执行后再进行权限验证。@PostAuthorize注解的作用:在访问控制器中的相关方法之后(方法的return先不执行),进行权限认证,去看看UserDetailsService用户细节实现类中用户是否有对应的权限,如果有的话,那么控制器方法的最后一句return语句会执行,否则,控制器方法的最后一句return语句不会执行。
实际用法与@PreAuthorize 相似
@PreFilter
@PreFilter注解对集合类型的参数执行过滤,移除结果为false的元素。基于方法入参相关的表达式,对入参进行过滤。分页慎用!该过程发生在接口接收参数之前。 入参必须为 java.util.Collection 且支持 remove(Object) 的参数。如果有多个集合需要通过 filterTarget=<参数名> 来指定过滤的集合。内置保留名称 filterObject 作为集合元素的操作名来进行评估过滤
@GetMapping("/info")
@PreFilter(value = "filterObject.id%2==0")
public List<Users> info(@RequestBody List<Users> list){
list.forEach(t->{
System.out.println(t.getUserid()+"\t"+t.getUsername());
});
return list;
}
@PostFilter
注意@PostFilter注解只有在控制器方法的return返回值是一个集合的时候才可以使用;
@PostFilter注解的作用:如果控制器方法的return返回值是一个集合,此注解可以对return的这个集合进行过滤输出。使用@PostFilte注解可以对集合类型的返回值进行过滤。使用@PostFilter时,Spring Security将移除使对应表达式即的结果为false的元素
@GetMapping("/list")
@PostFilter(value = "filterObject.username=='libai'")
public List<Users> list(){
ArrayList<Users> list = new ArrayList<Users>();
list.add(new Users(1,"libai","666"));
list.add(new Users(2,"dufeng","123"));
return list;
}
访问结果: