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);
  }
}

posted on 2021-12-26 18:00  kaiker  阅读(11)  评论(0)    收藏  举报