【问题标题】:How to use @PreAuthorize in Spring WebFlux?如何在 Spring WebFlux 中使用 @PreAuthorize?
【发布时间】:2019-03-03 01:08:58
【问题描述】:

在 Spring Web 中,我使用 @PreAuthorize 和 SpEl 来检查当前用户的权限。类似的东西:

@Component
public class CustomSecurity {
    public boolean checkPermission(){
        Authentication authentication = SecurityContextHolder.getContext()
                .getAuthentication();
        CurrentAccount currentAccount = (CurrentAccount)authentication.getPrincipal();
        return currentAccount.getUsername().equals("admin");
    }
}

在 RestController 中:

@PreAuthorize("@customSecurity.checkPermission()")
@GetMapping("/")
public Object getWidgetValues() {
    return "Hello admin";
}

现在我尝试使用 WebFlux。 写了 reactiveCheckPermission。

public boolean checkPermission2() {
    return ReactiveSecurityContextHolder.getContext()
            .map(SecurityContext::getAuthentication)
            .map(Authentication::getPrincipal)
            .map(o -> (CurrentAccount) o)
            .map(currentAccount -> currentAccount.getUsername().equals("admin"))
            .block();
}

但是会抛出 IllegalStateException("block()/blockFirst()/blockLast() 是阻塞的,线程并行不支持这种情况

将布尔值更改为 Mono,但 @PreAuthroze 只需要布尔值,而不需要 Mono。

如何在 WebFlux 中使用 @PreAuthorize 对吗?

【问题讨论】:

    标签: spring-security spring-webflux


    【解决方案1】:

    我找到了一种解决方案。

    @PreAuthorize("@customSecurity.checkPermission(#account)")
    @GetMapping("/")
    public Object getWidgetValues(@AuthenticationPrincipal(expression = "account") Account account) {
        return "Hello admin";
    }
    

    在 ReactiveUserDetailsS​​ervice 中使用 CurrentAccount 的位置

    public class CurrentAccount extends User {
    private Account account;
    
    public CurrentAccount(Account account) {
        super(account.getLogin(), account.getPassword(), true, true,
                true, !account.isLocked(),
                AuthorityUtils.createAuthorityList(account.getRole().name()));
        this.account = account;
    }
    

    【讨论】:

      【解决方案2】:

      如果您想更手动地执行此操作,您可以:

      @GetMapping("/resources")
      public Flux<Object> getResources() {
       return ReactiveSecurityContextHolder.getContext()
              .map(SecurityContext::getAuthentication)
              .map(Authentication::getPrincipal)
              .map(o -> (CurrentAccount) o)
              .filter(currentAccount -> 
                  currentAccount.getUsername().equals("admin"))
              .switchIfEmpty(Mono.error(new ResponseStatusException(FORBIDDEN)))
              .then(<here further processing>);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-30
        • 2012-11-25
        • 1970-01-01
        • 2018-03-26
        • 2018-01-26
        • 2019-07-11
        • 2019-01-15
        相关资源
        最近更新 更多