场景:通过feign调第三方接口传数据,第三方接口有在header中添加认证信息,认证信息中内容包含特殊字符
备注:可以通过本地起另一个接口来模拟调第三方接口,这样看header信息很方便
问题1:添加了header,第三方接收header内容为空
@FeignClient(name = "account-client", url = "${feign.api.url.center}", path = "${feign.api.url.path.center}"
public interface Sock5AccountClient {
/**
* 新增账号同步认证中心
* @param accountDTO账号信息
* @return 响应结果
*/
@PostMapping("/muxadduser")
@Headers("Authorization: {token}")
Result<Void> syncAccount(@RequestParam("token") String token, @RequestBody AccountDTO accountDTO);
}
解决办法
@FeignClient(name = "account-client", url = "${feign.api.url.center}", path = "${feign.api.url.path.center}"
public interface AccountClient {
/**
* 新增账号同步认证中心
* @param accountDTO账号信息
* @return 响应结果
*/
@RequestMapping( value = "/muxadduser",method = RequestMethod.POST,headers = {"Content-Type=application/json"})
JSONObject syncAccount(@RequestHeader(name = "Authorization") String token, @RequestBody AccountDTO accountDTO);
}
问题2:token中传Authorization被转成小写
第三方接收的header里的key是authorization,导致拿不到数据
解决办法:
添加拦截器,删除原key(authorization),新增key(Authorization)
@Configuration
@Slf4j
public class FeignConfiguration implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return;
}
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
Enumeration<String> values = request.getHeaders(name);
while (values.hasMoreElements()) {
String value = values.nextElement();
template.header(name, value);
}
}
}
Collection<String> values = headers.get("authorization");
template.removeHeader("authorization");
template.header("Authorization",values );
}
}
注意这里不能直接添加,直接添加数据会被覆盖,测试发现Content-Type这种带其他字符的能够转化成功,不会被覆盖
问题3:token是一串被加密的数据,存在特殊字符,传到第三方+都被空格取代
解决办法:拦截器获取header内容,替换空格为+
@Override
public void apply(RequestTemplate template) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return;
}
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
Enumeration<String> values = request.getHeaders(name);
while (values.hasMoreElements()) {
String value = values.nextElement();
template.header(name, value);
}
}
}
Map<String, Collection<String>> headers = template.headers();
Collection<String> values = headers.get("authorization");
Collection<String> encodeValues = new ArrayList<>();
for (String str : values) {
str = str.replaceAll(" ", "+");
encodeValues.add(str);
}
template.removeHeader("authorization");
template.header("Authorization",encodeValues);
}
最后给接口添加拦截器即可
@FeignClient(name = "account-client", url = "${feign.api.url.center}", path = "${feign.api.url.path.center}",configuration = FeignConfiguration.class)
public interface AccountClient {
。。。。
}
其他特殊字符目前在数据中未看到丢失情况,稍后如果测试出现在做补充。
网友评论