Spring Security @ обход предварительной авторизации для определенной роли

#java #spring #spring-security #authorization

#java #spring #spring-безопасность #авторизация

Вопрос:

Я работаю с политикой безопасности 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");
}
 

Но это не работает. У кого-нибудь есть идеи по этому поводу?

Ответ №1:

Для более подробного объяснения посмотрите следующую ссылку (в основном раздел 6). Код, используемый в качестве основы моего ответа, был:

MySecurityExpressionRoot

customMethod Security expressionhandler

Следующий код работает для меня:

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

Любой пользователь с ADMIN SUPER ролями: или сможет получить к нему доступ.