RestTemplate调用接口报Unauthorized异常但Postman正常如何解决?
问题排查方案
核心问题1:GET请求携带请求体不符合规范,RestTemplate默认不会发送GET请求的body
- HTTP规范本身没有禁止GET请求带body,但大多数服务端框架、HTTP客户端对GET请求body的处理逻辑不一致:Postman会正常发送GET请求的body,但RestTemplate的默认实现
SimpleClientHttpRequestFactory会忽略GET请求的body,导致你提交的参数根本没有发送到服务端,自然校验不通过返回401。 - 解决办法:
- 优先和接口提供方确认,是否支持把请求参数放在URL query参数里,或者把请求方法改成POST(POST带body是标准规范)
- 如果必须用GET带body,需要替换RestTemplate的请求工厂为
HttpComponentsClientHttpRequestFactory,这个实现支持GET请求携带body,示例代码:
// 替换RestTemplate的请求工厂 RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
需额外引入httpclient依赖(以Maven为例):
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency>
问题2:时间格式可能存在错误
- 你代码里定义的时间格式是
DateTimeFormatter.ofPattern("dd.MM.yyyy hh:mm:ss"),其中hh是12小时制,凌晨和中午的12点都会显示为00,和你Postman示例里的24小时制格式不符,可能导致服务端校验参数失败。 - 解决办法:把格式改成24小时制的
HH,即:
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");
问题3:配置值读取错误校验
你最早手动拼接Basic认证头的代码存在逻辑错误:propertiesService.getValue(authLogin+":"+authPassword)是把拼接后的账号密码作为key去配置中心取值,而不是直接对账号密码拼接后做base64编码,虽然你后续改用setBasicAuth方法规避了这个问题,但仍建议你打印日志确认读取到的authLogin、authPassword、apiKey和Postman里的配置完全一致,避免配置值读取错误、前后有空格等问题。
问题4:请求信息对比排查
如果以上方法都没有解决问题,可以给RestTemplate添加请求拦截器,打印完整的请求url、请求头、请求体内容,和Postman发送的请求做逐字对比,即可定位差异点。示例拦截器代码:
restTemplate.setInterceptors(Collections.singletonList((request, body, execution) -> { log.info("请求方法:{}", request.getMethod()); log.info("请求URL:{}", request.getURI()); log.info("请求头:{}", request.getHeaders()); log.info("请求体:{}", new String(body, StandardCharsets.UTF_8)); return execution.execute(request, body); }));
内容的提问来源于stack exchange,提问作者Shoxrux Sindarov
相关产品推荐
相关产品推荐

