Spring实战(第四版) 第十四章 保护方法应用
1、使用注解保护方法
使用@Secured注解限制方法调用
能够基于用户所授予的权限限制对方法的访问。@PreAuthorize、@PostAuthorize、@PreFilter、@PostFilter
@Configuration
@EnableGlobalMethodSecurity(securedEnabled=true)
public class SecuredConfig extends GlobalMethodSecurityConfiguration {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
@Bean
public SpittleService spitterService() {
return new SecuredSpittleService();
}
}
@Secured("RPLE_SPITTER")
public void addSpittle(Spittle spittle) {}
2、表达式实现方法级别的安全性
- @PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问。
- @PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常。
- @PostFilter 按照表达式过滤方法结果
- @PreFilter 必须在进入方法之前过滤输入值
表述方法访问规则
- 在方法调用之前校验
@PreAuthorize("hasRole('ROLE_SPITTER')")
public void addSpittle(Spittle spittle) {
}
@PreAuthorize("hasRole('ROLE_SPITTER') and #spittle.text.length() <= 140")
public void addSpittle(Spittle spittle) {
}
- 在方法调用之后校验
- 为了方便访问受保护的对象,Spring Security在SpEL中提供了名为returObject的变量。principle也是内置名称,代表当前认证用户的主要信息。
@PostAuthorize("returnObject.spitter.username == principal.username")
public Spittle getSpittleById(long id) {}
过滤方法的输入和输出
- 事后对方法返回值过滤
@PostFilter("hasRole('ROLE_ADMIN') || filterObject.spitter.username == principal.name")
public List<Spittle> getOffensiveSpittles() {}
- 事先对方法的参数进行过滤
@PreFilter("hasRole('ROLE_ADMIN') || targetObject.spitter.username == principal.name")
public void deleteSpittles(List<Spittle> spittles) {}
- 许可计算器
hasPermisssion()函数是Spring Security为SpEL提供的扩展,能够在执行计算的时候插入任意的逻辑。
@PreFilter("hasPermission(targetObject, 'delete')")
public void deleteSpittles(List<Spittle> spittles) {}
- 有两种hasPermission实现,一种可输入参数,一种需要得到目标多项的id
public calss SpittlePermissionEvaluator implements PermissionEvaluator {
private static final GrantedAuthority ADMIN_AUTHORITY = new GrantedAuthorityImpl("ROLE_ADMIN");
public class SpittlePermission(Authentication authentication, Object target, Object permission) {
if (target instanceof Spittle) {
Spittle spittle = (Spittle) target;
String username = spittle.getSpitter().getUsername();
if ('delete'.equals(permission)) return isAdmin(authentication) || username.equals(authentication.getName());
}
}
public boolean hashPermission(AUthentication authentication, Serializable targetId, String targetType, Object permission) {
throw new UnsupportedOperationException();
}
private boolean isAdmin(Authentication authentication) {
return authentication.getAuthorities().contains(ADMIN_AUTHORITY);
}
}
浙公网安备 33010602011771号