【问题标题】:Spring TestRestTemplate not encoding "+" characterSpring TestRestTemplate 未编码“+”字符
【发布时间】:2017-11-20 06:08:45
【问题描述】:

我正在执行一个 SAML 请求,该请求具有一个名为“SAMLRequest”的 base64 编码参数。问题是“+”字符没有得到 URL 编码(它适用于其他字符,例如“=”)。当服务器收到请求时,它被视为无效文档,因为所有“+”字符现在都是空格“”字符。

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_XML);
    String base64SamlRequest = Base64.encode(... some payload ...);
    HttpEntity<Object> httpEntity = new HttpEntity<>(base64SamlRequest, headers);
    restTemplate.exchange(endpoint+"&SAMLRequest="+base64SamlRequest, method, httpEntity, String.class);

我也尝试过使用 SAMLRequest={base64SamlRequest} 作为 URL 的一部分进行模板化。

restTemplate.exchange(endpoint, method, httpEntity, String.class, base64SamlRequest);

启用日志记录 logging.level.org.apache.http=DEBUG 我可以看到 + 字符是 url 参数中的纯文本(未编码)。

如何强制对这些进行编码?或者我可以在上面的代码中改变什么来正确编码?

【问题讨论】:

  • @AmolRaje 我试过headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);,但还是不行。
  • ok.. 编码成字符串后将加字符改成 %2B 然后传递给 url
  • base64SamlRequest = base64SamlRequest .replaceAll("+", "%2B") 然后传给url

标签: spring spring-boot


【解决方案1】:

对于进入 URL 的 Base64 编码字符串操作,Spring 的最佳实践是使用 Spring 的 Base64Utils

String base64SamlRequest = Base64Utils.encodeToUrlSafeString(... some byte-wise payload ...);

这可确保所有字符在编码过程中正确转义。

请参阅 Spring-Boot 管理控制台代码中的 this example

有关详细信息,请参阅Base64Utils source,它在幕后使用Base64#getUrlEncoder 对字符串进行编码。

【讨论】:

  • 这从客户端的角度工作,但服务器不能再解析字符串(可能是因为 OpenSAML 它没有使用 decodeToUrlSafeString)。使用Base64Utils.decodeFromUrlSafeString 解码可以工作,但Base64Utils.decodeFromString 会失败。我无法更改服务器正在使用的 Base64 库,因为它是他们的代码。
【解决方案2】:

我现在已经解决了这个问题。结果我需要模拟 SAML 请求的表单提交。 URL编码表单数据的规则不同。

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

    String base64SamlRequest = Base64Utils.encodeToString(authnRequest.getBytes());

    MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
    form.add("username", "user");
    form.add("password", "password");
    form.add("SAMLRequest", base64SamlRequest);

    HttpEntity<Object> httpEntity = new HttpEntity<>(form, headers);

    ResponseEntity<String> response = restTemplate.postForEntity(endpoint, httpEntity, String.class);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-11
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多