首页 > 解决方案 > Spring Security @PreAuthorize ByPass 用于特定角色

问题描述

我正在使用 Spring 安全策略,需要全局角色SUPER@PreAuthorize的帮助,当令牌拥有它时,它必须绕过端点上的所有内容。这是一个端点示例:

@GetMapping
@PreAuthorize("(hasAuthority('DOMAIN_FIND_ALL'))")
public ResponseEntity<ResponseDTO<List<DomainDTO>>> findAll() {
    return ResponseEntity.ok().body(domainService.findAll());
}

我为我的全球角色找到的工作方式是这样的

@GetMapping
@PreAuthorize("(hasAuthority('DOMAIN_FIND_ALL') or (hasAuthority('SUPER'))")
public ResponseEntity<ResponseDTO<List<DomainDTO>>> findAll() {
    return ResponseEntity.ok().body(domainService.findAll());
}

但是实现应用程序的每个端点都太长了(hasAuthority('SUPER'),所以我正在寻找一种以全局方式配置它的方法,这样,如果令牌具有该角色,则允许所有端点。

我试过的:

@Override
public void configure(HttpSecurity http) throws Exception {
   http.csrf().disable()
              .authorizeRequests()
              .otherStuffs..
              .antMatchers("/**").authenticated()
              .antMatchers("/**").hasRole("SUPER");
}

但它不起作用。有人对此有任何想法吗?

标签: javaspringspring-securityauthorization

解决方案


有关更详细的说明,请查看以下链接(主要是第 6 节)。用作我回复基础的代码是:

MySecurityExpressionRoot

CustomMethodSecurityExpressionHandler

以下代码适用于我:

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .otherStuffs..
            .antMatchers("/**").authenticated();  // hasRole("SUPER") isn't require
}

覆盖默认MethodSecurityExpressionOperations接口:

public class MySecurityExpressionRoot implements MethodSecurityExpressionOperations {

  // Same properties than provided
  // link for MySecurityExpressionRoot
  ...

  public MySecurityExpressionRoot(Authentication authentication) {
    if (authentication == null) {
        throw new IllegalArgumentException("Authentication object cannot be null");
    }
    this.authentication = authentication;
  }

  // This is the ONLY change, as you can see the "SUPER" was added as allowed
  @Override
  public final boolean hasAuthority(String authority) {
    return this.hasAnyAuthority(authority, "SUPER");
  }

  // Rest of the code is the same than provided
  // link for MySecurityExpressionRoot
  ...
}

现在我们需要将上面的类添加到 Spring 配置中:

@Configuration  // Required although not include in "source CustomMethodSecurityExpressionHandler" class
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
  private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();

  @Override
  protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
    final MySecurityExpressionRoot root = new MySecurityExpressionRoot(authentication);
    root.setPermissionEvaluator(getPermissionEvaluator());
    root.setTrustResolver(this.trustResolver);
    root.setRoleHierarchy(getRoleHierarchy());
    return root;
  }
}

现在您可以使用以下虚拟GET端点对其进行验证:

@GetMapping("/add-new-user")
@PreAuthorize("hasAuthority('ADMIN')")
public ResponseEntity<String> addNewUser() {
    return new ResponseEntity("[add-new-user] Testing purpose", OK);
}

任何具有:ADMINSUPER角色的用户都可以访问它。


推荐阅读