使用Openfeign进行远程调用时,cookie如何返回呢?
有同学问我这个问题,写篇文章供参考一下吧。
有这么一些情况,我们跨服务远程调用时,需要携带cookie,而返回时有可以有也写了新的cookie
比如说我们在其他模块向用户中心模块检查是否有登录,当前请求是否有登录。
那么我们向用户中心请求时,就要携带cookie,用户中心检查cookie中的tooken来判断是否有登录,然后返回结果。
服务远程调用携带cookie
这里面涉及到客户端----请求---->A服务,再由A服务----请求--->用户中心
所以从A服务到用户中主服务这个过程中需要携带cookie。
@Slf4j
public class FeignConfiguration implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
if (attributes == null) {
return;
}
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
template.header(name, values);
}
}
}
}
这个一搜一大把的呢,所以这个对于同学们来说,肯定不是问题,也理解怎么回事的。
处理返回的cookie
假如我们使用双token的模式,当前token过期了,生成新的返回给客户端,通过写cookie的方式,直接写回去,A端是收不到的,客户端也不会有。
大概就是这样的过程:
用户中心服务----写cookie--->A端服务----响应---->客户端
写cookie这个过程无效
那怎么办呢?
我们可以拦截response,然后写到A端的response上,响应给客户端
具体代码如下,略加修改成自己适用的既可
@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;
@Bean
public Decoder feignDecoder() {
return new ResultStatusDecoder(new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters))));
}
static class ResultStatusDecoder implements Decoder {
final Decoder delegate;
public ResultStatusDecoder(Decoder delegate) {
Objects.requireNonNull(delegate, "Decoder must not be null. ");
this.delegate = delegate;
}
@Override
public Object decode(Response response, Type type) throws IOException {
InputStream inputStream = response.body().asInputStream();
String resultStr = IOUtils.toString(inputStream, "UTF-8");
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
if (attributes != null) {
HttpServletResponse targetResponse = attributes.getResponse();
//把cookies给到返回的response
Map<String, Collection<String>> headers = response.headers();
Set<Map.Entry<String, Collection<String>>> entries = headers.entrySet();
for (Map.Entry<String, Collection<String>> next : entries) {
if (next.getKey().equals("set-cookie")) {
Collection<String> value = next.getValue();
Iterator<String> iterator = value.iterator();
if (iterator.hasNext() && targetResponse != null) {
String tokenKey = iterator.next();
targetResponse.setHeader("Set-Cookie", tokenKey);
break;
}
}
}
}
return delegate.decode(response.toBuilder().body(resultStr, StandardCharsets.UTF_8).build(), type);
}
}
详情可以去学习摸鱼君这个项目。