首页 > 解决方案 > 如何在 Spring WebFlux 中使用 @PreAuthorize?

问题描述

在 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。写了反应检查权限。

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() are blocking,线程并行不支持

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

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

标签: spring-securityspring-webflux

解决方案


我找到了一种解决方案。

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

推荐阅读