RestTemplate调用REST接口返回401 提示Authorization头未找到JWT
开发REST API客户端时,代码逻辑看似可正常运行,但请求接口始终返回401错误,服务端提示JWT未在HTTP请求的Authorization头中找到。
关联代码
服务层实现
@Service public class RestTemplateService { private static final String GET_RELATION_BY_ID = "https://cuco-query-sbg-cuco-dev.apps.scg01.scg.dev.bo2.paas.cloudcenter.corp/getRelationByCucoId/{cucoId}"; private static final String JWT = "Bearer xxxx"; RestTemplate restTemplate = new RestTemplate(); public ResponseEntity<CuCoPerson> getRelationById(Integer cucoId) { HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); headers.add("Authorization", JWT); HttpEntity<String> entity = new HttpEntity<String>("parameters", headers); Map<String, Integer> param = new HashMap<String, Integer>(); param.put("cucoId", cucoId); return restTemplate.exchange(GET_RELATION_BY_ID, HttpMethod.GET, entity, CuCoPerson.class, param); } }
控制器层实现
@GetMapping("/getRelationById/{cucoId}") public ResponseEntity<CuCoPerson> getRelationByCucoId(@PathVariable Integer cucoId, @AuthenticationPrincipal Principal principal) { return restTemplateService.getRelationById(cucoId); }
根因分析
两个核心问题会导致该故障:
- GET请求违规携带无效请求体
HTTP规范中GET请求语义为资源查询,不应该携带请求体。代码构造HttpEntity时传入了无意义的字符串"parameters"作为请求体,RestTemplate默认使用JDK原生HttpURLConnection发送请求,该实现对GET请求携带请求体的场景存在兼容缺陷,部分版本会出现请求头丢失、请求方法被自动修改为POST的异常。 - JDK原生HTTP客户端的重定向安全限制
JDK自带的HttpURLConnection默认开启自动重定向跟随,当请求被重定向到不同域名、不同协议的地址时,会主动移除Authorization类敏感请求头,防止凭证泄露到非目标站点。目标接口部署在企业PaaS平台,这类平台的路由层普遍存在隐式重定向逻辑(路径补全、协议跳转、默认域名映射等),极易触发该安全限制,导致最终到达业务服务的请求丢失JWT头。
修复方案
按以下步骤修改即可解决问题:
- 移除GET请求的无效请求体,构造请求实体时仅传入请求头,同时将头的
add方法改为set,避免多值头导致解析失败:// 错误写法 // HttpEntity<String> entity = new HttpEntity<String>("parameters", headers); // 正确写法 headers.set("Authorization", JWT); HttpEntity<Void> entity = new HttpEntity<>(headers); - 替换RestTemplate默认的请求工厂,使用Apache HttpClient实现替代JDK原生客户端,从根本上解决重定向丢头、HTTP协议兼容性差的问题:
- 引入Apache HttpClient依赖(Spring Boot Web模块默认自带该依赖,无需额外引入可直接使用)
- 初始化RestTemplate时指定请求工厂:
RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
- 可选优化:可先用curl/Postman直接调用目标接口,确认是否存在隐式重定向,拿到最终真实接口地址后直接配置到代码中,跳过不必要的重定向跳转。
内容的提问来源于stack exchange,提问作者DiegoMG
相关产品推荐
相关产品推荐

