使用Spring RestTemplate发送加密JSON请求时出现乱码问题
解决Spring RestTemplate发送加密JSON请求乱码问题
嘿,我看你遇到了RestTemplate发送加密JSON时的乱码问题,导致服务端解密失败抛出异常。这个问题大多是因为加密后的二进制数据处理不当,或者RestTemplate的默认编码配置干扰了数据传输。下面是我整理的具体解决方案:
1. 先搞对加密后的数据处理方式
加密后的内容本质是二进制字节流,如果你直接用new String(encryptedBytes)把它转成普通字符串,大概率会因为默认编码(比如UTF-8)无法解析二进制内容而产生乱码。正确的做法是用Base64把加密后的字节编码成安全的可传输字符串,这样不会丢失任何信息:
// 假设encryptJson是你的加密方法,返回加密后的字节数组 byte[] encryptedBytes = encryptJson(yourOriginalJson); // 转成Base64编码的字符串,确保传输过程中数据完整 String encryptedBase64 = Base64.getEncoder().encodeToString(encryptedBytes);
2. 配置RestTemplate避免自动编码干扰
默认的RestTemplate会对字符串请求体做额外的编码处理,这很可能破坏你已经处理好的加密内容。我们需要调整它的消息转换器:
RestTemplate restTemplate = new RestTemplate(); // 移除默认的StringHttpMessageConverter,它会自动对字符串做编码转换 restTemplate.getMessageConverters().removeIf(converter -> converter instanceof StringHttpMessageConverter); // 添加自定义的String转换器,指定UTF-8编码,并且禁止自动添加Accept-Charset头 StringHttpMessageConverter customConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8); customConverter.setWriteAcceptCharset(false); restTemplate.getMessageConverters().add(customConverter);
发送请求时,记得设置正确的请求头,告诉服务端你发送的是Base64编码的内容:
HttpHeaders headers = new HttpHeaders(); // 可以用text/plain,或者自定义媒体类型比如application/encrypted-json headers.setContentType(MediaType.TEXT_PLAIN); HttpEntity<String> requestEntity = new HttpEntity<>(encryptedBase64, headers); // 发送请求并接收响应 ResponseEntity<String> response = restTemplate.postForEntity( "http://你的WebService地址", requestEntity, String.class );
3. 服务端要对应做解码处理
别忘了服务端这边也要配合,先把接收到的Base64字符串解码回字节数组,再进行解密:
// 服务端获取请求体(这里假设用Spring MVC接收) @PostMapping("/your-endpoint") public String handleEncryptedRequest(@RequestBody String encryptedBase64) { // 解码Base64字符串到字节数组 byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBase64); // 执行解密操作 String decryptedJson = decryptBytes(encryptedBytes); // 后续业务处理... return yourResponse(); }
4. 其他排查小技巧
- 检查原始JSON的编码:确保你生成原始JSON时用的是UTF-8编码;
- 开启RestTemplate日志:查看实际发送的请求体和你本地生成的Base64字符串是否一致,排查中间是否有修改:
<!-- 如果你用logback,添加这个日志配置 --> <logger name="org.springframework.web.client.RestTemplate" level="DEBUG"/> - 直接发送二进制字节流:如果你的加密方案允许,也可以直接发送字节数组,避免Base64转换。此时Content-Type设为
application/octet-stream:HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); HttpEntity<byte[]> requestEntity = new HttpEntity<>(encryptedBytes, headers); ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
内容的提问来源于stack exchange,提问作者Chitra
相关产品推荐
相关产品推荐

