我真的不会把它放在这里,但我真的很困惑, 我想实现以下目标。
我正在运行
- Java 14
Spring Cloud Gateway
版本:Hoxton.SR3
Spring Boot
版本:2.2.5.RELEASE
现在我想将安全性集成到我的网关和所有下游微服务中。最终,我决定使用 Firebase 作为身份提供商 (IDP)。我的 Angular 应用程序将从 Firebase 获取 JWT token ,并将其在每个请求中发送到云网关。因此,网关将开始仅充当资源服务器,仅此而已。
这是我如何尝试的。 同时设置 Spring Cloud Gateway 充当资源服务器。 这里解释得很好Spring Security Docs .
这是我的配置
@EnableWebFluxSecurity
public class ResourceServerSecurityConfiguration {
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
// @formatter:off
http
.authorizeExchange()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
// @formatter:on
}
}
和application.yml
spring:
security:
oauth2:
resourceserver:
jwt:
jwk-set-uri: https://www.googleapis.com/service_accounts/v1/jwk/<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6c1f090f191e0918030709022c1f151f180901420b1f091e1a050f090d0f0f03190218420f0301" rel="noreferrer noopener nofollow">[email protected]</a>
issuer-uri: https://securetoken.google.com/{$app.name}
正如您在此 YAML 中看到的,我提供了 jwk-set-uri 和颁发者来验证传入的 token 。
至此,所有工作都已被接受。所有请求都必须在身份验证 header 中包含有效的 JWT。
下一步,
我希望我的网关使用 WebClient
并调用多个服务来聚合前端数据。
这是我尝试配置我的客户端的方法。
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder()
.filter(new ServletBearerExchangeFilterFunction());
}
如您所见,它使用 ServletBearerExchangeFilterFunction
这是我真正的问题所在。
我已经检查过,当 Spring 配置 oauth2ResourceServer 时,它使用 NoOpServerSecurityContextRepository
。据我所知,到目前为止,这正是一个用于注册每个请求上下文的存储库。另外,我知道使用 NoOp 是有意义的,因为我们想要无状态。但是我不明白如何使 ServletBearerExchangeFilterFunction 正常工作并向下游传递我的 token 。
我现在花了很多时间试图找出正确的方法。
Github:https://github.com/spring-projects/spring-security/issues/7771
即使根据这一点,我尝试做的事情也应该是合法且可能的。不知道我哪里错了。
最佳答案
我想到了这一点,问题是 ReactiveSecurityContext 仅当您处于 react 流中且 ServletBearerExchangeFilterFunction 用于 Servlet 调用时才可用。
最终,我刚刚编写了自己的过滤器函数,该函数监听 ReactiveSecurity 上下文并设置 Authorization header 。在这里。
public class BearerExchangeFilterFunction implements ExchangeFilterFunction {
@Override
@NonNull
public Mono<ClientResponse> filter(@NonNull ClientRequest request, ExchangeFunction next) {
return ReactiveSecurityContextHolder.getContext()
.map(c -> (c.getAuthentication().getCredentials()))
.cast(AbstractOAuth2Token.class)
.checkpoint()
.map(token -> bearer(request, token))
.defaultIfEmpty(request)
.flatMap(next::exchange);
}
private ClientRequest bearer(ClientRequest request, AbstractOAuth2Token token) {
return ClientRequest.from(request)
.headers(headers -> headers.setBearerAuth(token.getTokenValue()))
.build();
}
}
关于java - Spring Cloud Gateway + Spring安全资源服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61511710/