首页 > 解决方案 > Spring Security 5.x、WebFlux、Reactive、如何在 ReactiveSecurityContextHolder 中存储身份验证

问题描述

我正在使用 Spring Boot 2.3.1 和 WebFlux 构建 OAuth2 授权服务器。我遇到了一个问题。成功验证后,Authorization对象中缺少该ReactiveSecurityContextHolder对象。

我有一个实现,ServerSecurityContextRepository它实现了load如下方法。

@Override public Mono load(ServerWebExchange swe) {

return swe.getSession().map(WebSession::getAttributes).flatMap((attrs) -> {
  ServerHttpRequest request = swe.getRequest();
  String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);

  if (authHeader != null && authHeader.startsWith("Bearer ") && authHeader.contains(" ")) {
    // Split the auth header at space and the second token is the authToken.
    String authToken = authHeader.split(" ")[1];

    try {

// Some code removed here.
      Authentication auth = new UsernamePasswordAuthenticationToken(principal, authToken);
      SecurityContext sc = (SecurityContext)attrs.get(VarahamihirConstants.SECURITY_CONTEXT_ATTRIBUTE);
      if (sc == null) {
        sc = new SecurityContextImpl(auth);
        save(swe, sc);
      }
      final SecurityContext context = sc;
      return this.authenticationManager.authenticate(auth).map((authentication) -> {
        context.setAuthentication(authentication);
        return context;
      });
    } catch (ParseException|JOSEException|BadJOSEException e) {
      return Mono.error(new UnauthorizedException("The auth token is invalid."));
    }
  } else {
    return Mono.empty();
  }
});

}

我还有一个实现ReactiveAuthenticationManagerwhich implementsauthenticate方法。

public Mono<Authentication> authenticate(Authentication authentication) {
String authToken = authentication.getCredentials().toString();
try {
  Principal principal = authentication.getPrincipal();
  if (!jwtUtil.validateToken(principal.getAuthToken())) {
    return Mono.empty();
  }
// Some code removed.
                Authentication auth = new UsernamePasswordAuthenticationToken(principal,
                        authToken,
                        actualAuthorities);
                return Mono.just(auth);
              })
      return Mono.just(auth);
  }
  //SecurityContextHolder.getContext().setAuthentication(auth);
} catch (Exception e) {
  e.printStackTrace();
  return Mono.error(e);
}
return Mono.error(new UnauthorizedException("Unreachable place."));

}

在此之后,代码在处理身份验证流程方面工作正常,但ReactiveSecurityContextHolder不包含任何上下文。也正因为如此,任何PrePost注释都不能使用。

我直观地理解,我必须在某个地方将上下文保存到上下文持有者中,但是在哪里?

标签: javaspring-securityspring-webfluxreactive

解决方案


推荐阅读