Spring WebClient:自动计算正文的HMAC签名并将其作为标头传递



在我的Spring Boot应用程序中,我使用RestTemplate来调用一个WS,其中的HMAC签名应该作为HTTP标头提供。为此,我使用了ClientHttpRequestInterceptor.基本上,我做到了:

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
try {
String hmac = Hmac.calculateRFC2104HMAC(body, key);
request.getHeaders().add("X-Hub-Signature", "sha1=" + hmac);
return execution.execute(request, body);
}
catch (NoSuchAlgorithmException | InvalidKeyException e) {
throw new IOException(e);
}
}

现在我想使用WebClient更好地集成到我的反应式应用程序中。但是我迷失在这个新的反应式 API 中。如何使用ExchangeFilterFunctionBodyInserter来实现这一点?困难在于检索正文,执行签名计算并因此更新请求。

感谢您的支持。

对正文进行签名需要以序列化形式进行签名,但序列化发生在发送数据之前,因此需要对其进行拦截。

您可以通过创建自己的编码器(例如包装现有Jackson2JsonEncoder(并在构建WebClient时将其作为ExchangeStrategies传递来执行此操作。截获序列化数据后,可以注入标头。但是编码器没有对ClientHttpRequest的引用,因此您需要在HttpConnector中捕获此对象并将其传递到SubscriberContext中。

这篇博文解释了这个过程: https://andrew-flower.com/blog/Custom-HMAC-Auth-with-Spring-WebClient#s-post-data-signing

例如,WebClient创建步骤可能如下所示,其中MessageCapturingHttpConnector是捕获ClientHttpRequestBodyCapturingJsonEncoder的连接器

Signer signer = new Signer(clientId, secret);
MessageSigningHttpConnector httpConnector = new MessageSigningHttpConnector();
BodyCapturingJsonEncoder bodyCapturingJsonEncoder
= new BodyCapturingJsonEncoder(signer);
WebClient client
= WebClient.builder()
.exchangeFunction(ExchangeFunctions.create(
httpConnector,
ExchangeStrategies
.builder()
.codecs(clientDefaultCodecsConfigurer -> {
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(bodyCapturingJsonEncoder);
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
})
.build()
))
.baseUrl(String.format("%s://%s/%s", environment.getProtocol(), environment.getHost(), environment.getPath()))
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();

最新更新