WebFluxSecurity 不会向 SecurityContext 添加身份验证

Vos*_*yan 6 java spring spring-security jwt spring-boot

我在 Spring Cloud Security 和反应式堆栈上遇到了这个奇怪的问题。我设置了 Spring Cloud Gateway,同时,我将其设置为 RsourceServer,因此在这种情况下,所有传入请求都将从 Firebase 授予 JWT。这是我的配置的一些快照。

application.yml 设置 JWK 和 Issuer,告诉 Spring Security 如何验证 JWT。

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          jwk-set-uri: https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com
          issuer-uri: https://securetoken.google.com/${project_name}
Run Code Online (Sandbox Code Playgroud)

SecurityConfig

    @EnableWebFluxSecurity
    public class SecurityConfig {

      @Bean
      public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        // @formatter:off
        http
            .csrf().disable()
            .authorizeExchange()
            .pathMatchers("/public").permitAll()
            .anyExchange().authenticated().and()
            .oauth2ResourceServer()
            .jwt();
        return http.build();
        // @formatter:on
      }
    }
Run Code Online (Sandbox Code Playgroud)

最后是控制器

TestController 仅出于测试目的,我创建了 Controller 来检查是否设置了安全上下文。

@RestController
@Slf4j
public class TestController {

  @GetMapping("/public")
  public String getPublic() {
    if (SecurityContextHolder.getContext().getAuthentication() != null) {
      throw new IllegalStateException("Public API should not have any AuthContext");
    }

    return "All shiny you got your PUBLIC data!";
  }

  @GetMapping("/private")
  public String getPrivate(@AuthenticationPrincipal Jwt jwt) {
    log.info(jwt.getTokenValue());    //in here jwt present as should be
    if (SecurityContextHolder.getContext().getAuthentication() == null) {
      throw new IllegalStateException("Oops.... Private API should have AuthContext");
    }

    return "All shiny you got your PRIVATE data!";
  }

}
Run Code Online (Sandbox Code Playgroud)

所以我非常沮丧,希望有人能在这里帮助我。根据所有 Spring Security 文档,在我看来,我应该在 JWT 有效时保存我的安全上下文。

主要目的是能够使用ServletBearerExchangeFilterFunctionwhich 尝试从中获取身份验证和令牌,并将其向下游传递给 WebClient 中的其他服务。但是,它是NULL。

Bearer Token Propagation在这里清楚地写到 SecurityContext 应该在那时已经有效。

任何建议将不胜感激。

小智 0

您必须使用 ReactiveSecurityContextHolder 并将其链接到 Rest 控制器的响应。

您的 RestController 也需要为此返回 Mono 或 Flux。

例如

return ReactiveSecurityContextHolder.getContext()
    .map { securityContext -> securityContext.authentication }
    .map { authentication -> authentication.principal }
Run Code Online (Sandbox Code Playgroud)