java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > RestTemplate发送请求Cookie影响及注意事项

RestTemplate发送请求时Cookie的影响及注意事项说明

作者:毕小宝

这篇文章主要介绍了RestTemplate发送请求时Cookie的影响及注意事项说明,具有很好的参考价值,希望对大家有所帮助。

背景

一个基于 SpringCloud 的多服务项目中,服务间调用通过 Spring 的 RestTemplate 实现,后台模块 A 有一个定期清理无效业务数据的任务,它调用 Web 服务 B 的 API 时,竟然一直出现 Token 已过期问题。

技术背景

对于 Web 服务模块 B 来说,请求来源有用户浏览器和内部服务 A ,Token 校验通过后会刷新并设置响应对象的 Cookie 中,而 Cookie 又会在下次请求时发送给服务器。

各服务稳定运行后,定时任务 A 调用服务 B 的 API,从来都没有成功过。

后台服务调用时 Cookie 失效问题

问题描述

后台服务 A 在调用 B 的 某API 时,虽然会生成新 Token 信息并设置到头域,但是除了应用启动时成功调用了一次,其他周期的调用都出现了 Token 已过期问题。

问题分析

分析整个认证过程,发现在 Web 的拦截器中,如果检测到了内部服务调用,会刷新 Token 信息并返回给 RestTemplate 对象,而且拦截器提取 Token 的顺序是:请求参数、Cookie、Header。

// 请求参数
String token = request.getParameter("t");
// Cookie
if (StringUtils.isEmpty(token)) {
    Cookie[] cs = request.getCookies();
    if (cs != null) {
        for (Cookie c : cs) {
            if ("t".equals(c.getName())) {
                token = c.getValue();
                break;
            }
        }
    }
}
 //Header
if (StringUtils.isEmpty(token)) {
    token = request.getHeader("t");
}

问题症结

后台模块 A 一小时执行一次,每次调用使用 Spring 托管的 RestTemplate 单例对象发送请求给 B 时,它包含了上次请求收到的 Cookie 信息。

虽然同时生成了 Token 的头域信息,但是在 Web 端优先校验了 Cookie ,因此认证结果始终是无效 Token ,请求被拒绝。

启示录

我从互联网上得到的最好的经验之一,就是永远不要复制和粘贴不是自己编写的代码。

如果你一定要复制,那就照着它逐字输入,逼着自己思考,这些代码实际上是什么意思。

这是昨天看科技周刊印象深刻的一句话,本文的问题虽然不是复制粘贴导致的,但它别人的代码、别人的思想,我没有深刻分析过。

当我临时救火被分派解决这个问题时,简单看了下代码分析如下:

想当然地以为,只要加上从 Header 中获取就好了,而且阴差阳错的加在了 Cookie 获取的后面,所以问题还是没有解决。

反复加日志,打印各个信息的 Token ,发现解析时用的 Token 跟头域不一样, Token 失效时间也很规律,就是上次定时任务的调用时间。突然意识到了,Web 服务用的 Token 跟我想的不一样,谁把 Token 给改了?

答案是 Cookie,RestTemplate 竟然在发送请求时把上次的 Cookie 给带上了。30分钟的有效期,下一轮定时任务执行时,早就是失效了啊。

RestTemplate 注意事项

用 RestTemplate 进行服务调用时,最好清掉 Cookie 信息,

一来避免本文出现的情况;

二来,它作为Spring 托管的单例,如果访问的是不同系统的 API ,势必会出现 Cookie 混淆、失效的问题!

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文