也谈Http Session和Cookie

环境部署:
在一台服务器上部署了两个服务:
服务A:通过80/443端口对外提供xxx服务,前后台通过HeartBeat维持session
服务B:通过5900端口对外提供yyy服务

问题描述:
一旦使用yyy服务xxx服务就会出现HTTP Session expired的问题

问题分析:
在浏览器中跟踪xxx服务的交互过程发现,打开yyy服务之后发往xxx服务的sessionId发生了改变,变成了yyy服务返回的sessionId。由于是通过cookie来在前后台之间传递sessionId,看来是两个服务的cookie产生了冲突。

解决方案:
为每个服务的sessionId定义特殊的名称避免冲突覆盖,比如xxx服务的sessionId名称定义为xxx.JSESSIONID,yyy服务的sessionId名称定义为yyy.JSESSIONID。修改后问题解决。

问题虽然解决了,但还是有疑问,问题为什么会产生?有没有其他的解决方案?

  • Session是怎样保存的,是否必须用Cookie,用其他方式是否就没有类似的问题?
  • 浏览器中Cookie是怎样维护的,两个服务端口不同,为什么会冲突覆盖?

带着这样的问题梳理了HTTP Session和Cookie的原理。

为什么要有Session和Cookie

根因在于HTTP协议是无状态协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。

Cookie

http头部中的Set-Cookie和Cookie分别是专门负责设置和发送cookie的。当服务器返回给客户端http响应信息时,其中如果包含Set-Cookie这个头部时,意思就是指示客户端建立一个cookie,并且在后续的http请求中自动发送这个cookie到服务器端,直到这个cookie过期。如果cookie的生存时间是整个会话期间的话,那么浏览器会将cookie保存在内存中,浏览器关闭时就会自动清除这个cookie。另外一种情况就是保存在客户端的硬盘中,浏览器关闭的话,该cookie也不会被清除,下次打开浏览器访问对应网站时,这个cookie就会自动再次发送到服务器端。

Cookie的不可跨域名性

很多网站都会使用Cookie。例如,Google会向客户端颁发Cookie,Baidu也会向客户端颁发Cookie。那浏览器访问Google会不会也携带上Baidu颁发的Cookie呢?或者Google能不能修改Baidu颁发的Cookie呢?

答案是否定的。Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。

Cookie在客户端是由浏览器来管理的。浏览器能够保证Google只会操作Google的Cookie而不会操作Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名。Google与Baidu的域名不一样,因此Google不能操作Baidu的Cookie。
需要明确的是:Cookie是按照域名管理的,这里的域名是不包括端口号的。即同一IP(主机名)的不同端口认为是同一域名。
例如Chrome浏览器的Cookie可以通过:chrome://settings/siteData查看:
在这里插入图片描述
Cookie是按照IP(主机名/域名)分别保存的,不区分端口号

HTTP Session

除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,跟Cookie的区别在于Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了,这就是Session。

Session和Cookie

Session和Cookie都是用来记录客户端状态的技术,那么为什么要开发出这样两种技术?

Session一般依赖于Cookie:前面提到了Session信息保存在服务器上,客户端浏览器再次访问时只需要从保存的Session中查找该客户的状态就可以了。那么问题就来了,要查找某个客户的信息,首先需要这个客户的标识,这个客户的标识一般来说就是SessionID。需要客户端请求时携带这个SessionID,往往把SessionID保存在名为JSESSIONID的Cookie中实现。

是不是说禁用了Cookie Session就无法实现了?当然不是,只是说Cookie是实现SessionID传递的比较简单的方式,除此之外还有其他的替代方案,比如URL中携带。

那么Session的优势在哪?一般来说,Session信息保存在服务器端,信息更安全可靠,不像Cookie通过抓包工具可以一览无余,有些客户比较敏感的信息还是保存在Session中更好,更安全。

问题回顾

再回到问题上,SessionID是通过JSESSIONID这个Cookie传递的,而两个服务虽然端口号不同,但IP(主机名/域名)相同,因此产生了两个服务的JSESSIONID互相覆盖的情况,过程如下:

首先,访问了服务A,没有SessionID,服务A产生了SESSIONID#1通过名为JSESSIONID的Cookie给客户端,同时在服务A中保存的Session列表中保存了SESSIONID#1的信息;

再访问服务B,如果不携带SessionID,服务B要产生新的SESSIONID,携带SessionID#1,由于该SessionID在服务B的Session列表中查找不到,还是要产生新的SessionID。因此服务B产生了SESSIONID#2,同样通过名为JSESSIONID的Cookie给客户端,由于服务A、B都使用名为JSESSIONID的Cookie传递SessionID,导致发给服务A的请求携带了SESSIONID#2,服务A在自己保存的Sessionlieb中找不到该Session,认为Session过期。

参考

  1. 理解Cookie和Session机制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值