问题
项目中需要对数据进行同步,在代码中通过配置url,然后使用RestTemplate发起http请求,其中url携带了用户名与密码,如下:
http://cluster:cluster@192.168.61.30:18011/kettle/executeTrans/?rep=resource&trans=drug
原代码如下:
if (hospitalSyncEnabled) {
String url = hospitalSyncUrl + hospitalBizResponse.getId();
String response = restTemplate.getForObject(url, String.class);
log.info("Call Kettle Response : {}", response);
}
结果:请求报错:“401 Unauthorized…”
分析
根据报错结果可以推测请求失败是因为该http请求在目的主机鉴权失败。因此问题出在:把账号:密码
直接拼接在url中,然后通过restTemplate.getForObject进行请求导致的。
接下来尝试将账号:密码
信息设置在http的headers中:
if (hospitalSyncEnabled) {
String url = hospitalSyncUrl + hospitalBizResponse.getId();
HttpHeaders headers = new HttpHeaders();
String encodeAuthString = Base64.getEncoder().encodeToString(authString.getBytes());
headers.set("Authorization", "Basic " + encodeAuthString);
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(null,headers);
String response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class).getBody();
log.info("Call Kettle Response : {}", response);
}
结果
在对代码修改后,再次调用接口,访问成功。
原因探索
通过debug,可以发现,restTemplate.getForObject进行请求时,携带的账号:密码
信息直接拼接在url中,但是由于安全性问题,现在很多系统已经不支持该方式,因此导致鉴权失败;
然而,当我们将账号:密码
信息设置在header后,并通过exchange方法进行http请求,最终在创建连接时,其携带了账号:密码
信息,因此鉴权成功。