【问题标题】:spring webclient sign a body requestspring webclient签署一个body请求
【发布时间】:2020-07-11 20:06:24
【问题描述】:

我需要在 Spring 中使用 WebClient 签署正文请求。

现在,问题在于我无法以“原始”方式获取正文(发送到远程服务器的确切正文)并从该正文计算签名。

我有两种情况,一个对象的发布和一个 FormData 的发布。 第一次我可能可以使用 ObjectMapper 来模仿 WebClient 所做的事情(直到 WebClient 改变它,一切都坏了),但是对于 FormData,模仿它会很棘手。

如果我发送 a = b, e = x 我必须处理编码和参数的顺序(从http的角度来看)它不是强制性的,所以a = b,e = x它与e = x,a = b相同,但对于sha1(字符串)改变

使用过滤器我得到了 body() 但它是一个 BodyInserter 并且它似乎不能转换成一个字符串或字节[]

【问题讨论】:

标签: java spring webclient reactive


【解决方案1】:

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

假设您以 JSON 格式发送数据,您可以通过创建自己的 JsonEncoder(例如,包装现有的 Jackson2JsonEncoder)并在构建 WebClient 时将其作为 ExchangeStrategies 传递来实现这一点。截取序列化数据后,可以注入headers。但是编码器没有对ClientHttpRequest 的引用,因此您需要在HttpConnector 中捕获此对象并将其传递给SubscriberContext

BodyInserters 自动选择消息编写者来编写消息,并且在编码/序列化(如 Json)的情况下,这会像我建议的包装编码器一样交给编解码器。
(如果您不发送 JSON,请告诉我们什么格式,因为其他内容类型的解决方案会有所不同,例如 url 编码的表单等。)

这篇博文解释了这个过程: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();

【讨论】:

    猜你喜欢
    • 2020-05-04
    • 2019-09-19
    • 2020-01-30
    • 1970-01-01
    • 2019-06-24
    • 2021-10-26
    • 2022-01-18
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多