我目前正在开发一个用于开发的 REST“代理”。这个想法是在命令行上启动一个 jar,为其提供“代理”REST API 的基本 URL 和用于身份验证的现有密钥。代理处理身份验证/续订并将所有 REST 调用转发到目标 API。
我认为 Spring Cloud Gateway 可能非常适合此目的,并且使用请求链已经成功地使身份验证方面的工作正常进行:
@Configuration
public class FilterConfiguration {
@Bean
public RouteLocator mock(RouteLocatorBuilder builder, @Value("${gateway.url}") String url, @Value("${secret.key}") String secretKey, MyGatewayFilterFactory filterFactory) {
return builder.routes()
.route("pass-through", predicateSpec -> predicateSpec
.path("/authentication/sign/in/**", "/authentication/renew/**")
.uri(url))
.route("requires-auth", predicateSpec -> predicateSpec
.alwaysTrue()
.filters(gatewayFilterSpec -> gatewayFilterSpec
.filter(filterFactory.apply(new MyGatewayFilterFactory.Config(secretKey)))
)
.uri(url))
.build();
}
}
@Component
@RequiredArgsConstructor
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory .Config> {
private final WebClient webClient;
@Override
public GatewayFilter apply(MyGatewayFilterFactory.Config config) {
return (exchange, chain) -> Optional.of(AccessTokensHolder.tokens)
.map(AtomicReference::get)
.map(Mono::just)
.orElseGet(() -> this.signIn(config.getSecretKey()))
.flatMap(accessTokens -> {
exchange.getRequest()
.mutate()
.header(HttpHeaders.AUTHORIZATION, String.format("%s %s", accessTokens.getType(), accessTokens.getAccessToken()));
return chain.filter(exchange);
})
.onErrorResume(t -> Mono.empty())
.then(Mono.fromRunnable(this.postRequest(exchange)));
}
private Mono<AccessTokens> signIn(String secretKey) {
// uses the webClient to get the access tokens for the secretKey ...
}
private Runnable postRequest(ServerWebExchange exchange) {
return () -> {
ServerHttpResponse response = exchange.getResponse();
if (HttpStatus.PRECONDITION_FAILED.equals(response.getStatusCode())) {
// todo : HELP!
}
};
}
@Data
@RequiredArgsConstructor
public static class Config {
public final String secretKey;
}
private static final class AccessTokensHolder {
private static final AtomicReference<AccessTokens> tokens = new AtomicReference<>();
}
}
我的问题是响应的处理。如果经过身份验证的调用以 412 响应,我需要能够进行 webClient 调用来刷新访问令牌,然后再次执行原始调用(使用修改后的授权标头)。我不知道如何实现这一点(对于 SCG 和 WebFlux 来说相当新)...
(顺便说一句,如果有人知道更好/更简单的方法来实现这一点,我洗耳恭听!)
任何帮助将不胜感激!
干杯!
你能解决这个问题吗?我也遇到同样的问题但是不知道怎么解决!