Spring保护方法
Spring保护方法
一、使用注解保护方法
1.@Secured
由Spring Security提供,首先需要启用基于注解的方法安全性:
@EnableGlobalMethodSecurity(securedEnabled = true) @Configuration public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{\ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("tang").password("123").roles("USER"); } }
如果securedEnabled设置为true,将会创建一个切点,这样Spring Security切面就会包装带有@Secured注解的方法。
@Secured("ROLE_ROOT") //使用String数组作为参数,每个String值是一个权限 public String addUser() { return "add"; }
如果方法被没有认证的用户或没有所需权限的用户调用,保护这个方法的切面将抛出一个Spring Security异常。
2.JSR-250的@RolesAllowed注解
该注解与@Security注解基本一致,它们的区别在于@RolesAllowed注解是JSR-250定义的标准注解。
如果使用该注解需要将@EnableGlobalMethodSecurity的jsr250Enable属性设置为true。
二、使用表达式实现方法级别的安全性
使用SpEL能够在方法调用上实现更有意思的安全性约束。如果表达式结果为true,那么安全规则通过,否则就会失败。
首先,先要设置prePostEnable属性设置为true。
@EnableGlobalMethodSecurity(prePostEnabled = true) @Configuration public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration{ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("tang").password("123").roles("USER"); } }
@PreAuthorize和@PostAuthorize,它们能够基于表达式的计算结果来限制方法的访问。
@PreAuthorize:在方法调用之前执行,如果表达式的计算结果不为true,将会阻止方法
的执行。
@PostAuthorize:直到方法返回才执行,然后决定是否抛出安全异常。
@PreAuthorize("(hasRole('ROLE_ROOT') and #content.text.length() <= 180)") public String addUser() { return "add"; }
@PostAuthorize("returnObject.root.username = root.username") public String addUser() { return "add"; }
有时需要保护的不是方法调用,而是传入方法的数据和方法返回的数据。
事后对方法的返回值进行过滤
@PostAuthorize("returnObject.root.username == root.username") //使用表达式计算该方法返回集合的每个成员,将计算结果为false的成员移除掉 //filterObject对象引用的是这个方法所返回List中的某一个元素 @PostFilter("hasRole('ROLE_ADMIN') || " + "filterObject.admin.username == principal.username") public String addUser() { return "add"; }
事先对方法的参数进行过滤
@PreAuthorize("hasRole({'ROLE_ADMIN', 'ROLE_USER'})") @PreFilter("hasRole('ROLE_ADMIN') || " + "targetObject.user.username == user.name") public void deleteSth(List<User> userList) {}
应该避免编写复杂的安全表达式,或者在表达式中嵌入太多与安全无关的业务逻辑。而且,表达式
最终只是一个设置给注解的String值,难以测试和调试。
Simple is important!