【问题标题】:Spring WebClient can't read request body before send with ExchangeFilterFunctionSpring WebClient 在使用 ExchangeFilterFunction 发送之前无法读取请求正文
【发布时间】:2019-09-01 02:54:06
【问题描述】:

我一直使用 RestTemplate 并决定切换到 WebClient。

在发送请求之前,我使用私钥签署请求正文,客户端使用公钥检查请求。

我的拦截器:

private static class SignatureClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {

    private final PrivateKey privateKey;

    private SignatureClientHttpRequestInterceptor(String privateKeyLocation) {
        this.privateKey = PemUtils.getPrivateKey(Paths.get(privateKeyLocation));
    }

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        if (request.getMethod() == HttpMethod.POST) {
            request.getHeaders().add("X-Signature", Base64.getEncoder().encodeToString(PemUtils.signData(privateKey, SignatureAlgorithm.RS256.getJcaName(), body)));
        }
        return execution.execute(request, body);
    }
}

但在 WebClient,我没有在 ExchangeFilterFunction 中找到这样的机会。

有没有办法在 WebClient 中执行此操作,还是我必须在发送之前手动签署请求正文?

【问题讨论】:

  • 嘿,伙计@Peter。面临类似情况。你可以在哪里工作?如果是这样,请分享
  • @Enoobong 不幸的是,我无法解决它

标签: java spring spring-webflux


【解决方案1】:

签署正文需要序列化形式,但序列化发生在发送数据之前,因此需要以某种方式拦截。

对于 JSON 内容,您可以创建自己的编码器(例如,包装现有的 Jackson2JsonEncoder)并在构建 WebClient 时将其作为 ExchangeStrategies 传递。截取序列化数据后,可以注入headers。但是编码器没有对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();

【讨论】:

    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-12
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 2020-03-27
    相关资源
    最近更新 更多