会话跟踪机制是Web开发中常见的名词,用得也是相当的频繁,但是它到底是什么一个概念,可能对于刚刚接触这一个知识点的人来说会有比较大的疑惑。那么本文就是通过一些基本而有趣的案例(最后有涉及到ITeye和人人网的一个比较)结合笔者局限的知识来进行说明的。
首先我们提几个问题:
1、会话跟踪机制的作用是什么?
2、什么是Session?
3、什么是Cookie?
4、Session和Cookie之间的关系是什么?
(如果您对这四个概念了如指掌的话,可以直接忽略本文了)
下面让我们来看第一个演示:
一、演示1:
1、首先我们打开浏览器(笔者所用的是IE浏览器),进入ITeye首页并且登录
2、我们打开一个新的选项卡,并且再次进入ITeye的首页,大家可以想一个问题,进入之后是处于登录状态还是未登录的状态呢?结果如下:
依然处于登录状态,那么我们继续。
3、在浏览器的菜单栏上点击文件—>新建窗口,在新的浏览器窗口中我们再进入ITeye的首页,再看结果:
依然在登录,并且在打开新的窗口时,是直接进入ITeye的首页的。
4、再刺激一点,在菜单栏上点击文件—>新建会话,在新的浏览器窗口中我们进入ITeye的首页(此时你可能有点不耐烦了,不过见证“奇迹”的时刻就要来临了):
结果是“您未登录”(并且我们可以发现,在新的窗口中,我们并没有直接进入ITeye的首页,而是进入你自己设定的首页)。
从繁琐的演示1中我们来归纳一下:当在一个网页中登录进入了ITeye之后,无论是在同一窗口的不容选项卡中或者是在新建窗口的网页中进入该网站,都处于登录状态,而在新建会话的窗口中进入该网站,则处于原始状态。
或许有人会说,这是与打开网页的方式有关,但是其中深层次的原因是什么呢?我们便引入了会话跟踪机制。
二、什么是会话跟踪?
首先我们来看看会话话跟踪的作用:
在同一个银行的不同ATM机前,三个客户进行不同的操作,当客户1输入密码,点击确认之后,银行的服务器如何知道这个请求是来取款的,它会不会接到确认响应之后将钱转到另外一个账户(因为与此同时还有客户3在进行转账操作)。
通过这个问题我们会自然地相当,必定存在某种可能,是服务器知道那些请求是客户1发来的,那些请求是另外的用户发来的,这就是体现会话跟踪机制作用的一个简答的例子。
我们其实可以这样定义会话:一系列具有某个相同属性的的请求所组成的一个集合。
那么会话跟踪就是在一系列的请求中找到具有某种相同属性的请求,并将它们组成一组会话。上述的例子中这种属性就是表现在客户的身份上。
三、什么是Session?
会话跟踪在Web开发中得体现是通过一个叫Session的机制来完成的。在用户第一次请求网页的时候,服务器在返回一个请求的时候会在自己的存储空间内开辟一块空间来保存该请求的一些属性,比如用户状态、用户名、密码之类的。并且将这块空间的标识也同时返回给用户,这个标识就是在Session中经常提到了SessionID。那么之后后续的请求在发送时,会将这个SessionID一起发送过来。这样服务器通过客户端返回的SessionID找到相应的Session区域,这样便可以甄别出不同的请求了。
Session的作用其实就是存储请求的属性以区分不同的请求,通常在服务器端Session都收以散列表的形式存储的,我们所熟知的Tomcat的Session就是通过HashMap来进行存储的。
那么,服务器发送出得SessionID在客户端到底是如何存储的呢,这这就要引出Cookie概念了。
四、什么是Cookie?
上面所说的SessionID在客户端实际上是存储在Cookie中的,Cookie实际上是存储在客户端内存或硬盘的一个信息片段。它的格式如下
服务器所发送的SessionID就是作为name存放在Cookie中的。
当客户再次发送请求给Web服务器的时候,会将Cookie连同请求内容一起发送,服务器通过寻找name标识来取得其中的value值,这个value值便是相应Session的标识了。
注:在Session规范中,用于会话的的Cookie的名字必须是JSESSIONID。(也就是说,name必须是JSESSIONID)。
以下是自行创建的一个Cookie的内容:
![](http://dl.iteye.com/upload/attachment/569418/36f86507-2d4b-3f65-896c-cbb6c2b48f65.jpg)
有人或许会问,想domain、path、version这些是什么,我想说的是百度可以解决,我就不再赘述。唯一要注意的一点是max-age这个属性:我们说过Cookie是保存在客户端硬盘或者内存中的信息片段,保存在内存中就不会持久,那么除了强行删除Cookie之外还有什么控制它存储长短的方法呢?那就是所说的这个max-age了,该属性的值以秒为单位,当一个请求之后超过该时间后再没有请求发出后,这个Cookie就会自动清除。这个可以表现为你登陆一个网站之后很久没有再进行操作,当再次操作网页时它会提示您已经断开,请重新登陆。
五、Cookie的深入分析:Cookie的存储方式
图5.1
通过上述的分析,我们接下来可以解释演示1中的现象了,基于Session机制下的Cookie存放在客户端的内存中,我们知道不同进程之间不能共享同一内存的数据,因此这个Cookie只能是被一个浏览器窗口进程所占有。
大家可以回忆一下,我们除了第一个登陆后的网页之后,陆续打开了同一个窗口下的另一选项卡,通过新建窗口的一个新的窗口,通过新建会话的一个新的窗口。其实我们在打开网页的同时同时,再打开资源管理器中的进程管理可以看到:
1、打开新的选项卡及新建窗口前:
有三个iexplore.exe。
2、打开新的选项卡及新建窗口之后:
还是三个iexplore.exe,进程数没有变化。
3、但是当新建会话之后:
五个iexplore.exe进程了,进程数增加。
所以说,前两种方法打开的网页实际上是与原始网页在一个进程之内,他们共享内存数据,当然也就是共享存放的Cookie片段,当打开网页发送请求时,会将这个Cookie片段一起发送给服务器,服务器此时将已经登录的状态返回,于是便有了两者都出现直接登录的状态。
而新建会话实际上是新建了一个进程,它并没有记录已经登录状态的Cookie片段,因此当它想ITeye发送请求的时候,得到的返回只是一个未登录的页面,因为之前ITeye的服务器上还并未存储的有这个进程请求的相关信息。
六、思考:ITeye VS. 人人网
通过Session和Cookie的分析,我们貌似比较好的解释了演示1出现的现象,但是演示2随即而来:
1、同时在两个窗口中登录ITeye(另一个窗口通过菜单栏中文件—>新建会话,保证两个窗口属于不同进程):从一个窗口中退出,并且刷新另一窗口的页面之后的结果:
第一个窗口:已经退出了
第二个窗口:还未退出
这个可以通过我们之前的分析进行解释,两个窗口是两个不同的进程。存放着两个不同的Cookie,当一个进程退出时,不影响另一进程在服务器存放的Session中的登录状态。不过别高兴得太早,看下面的。
2、将登录ITeye改成登录人人网,其他操作相同,结果是:
第一个窗口:已经退出
第二个窗口:也已经退出
从演示2我们可以总结一下,在两个不同进程的页面上同时登录ITeye,当从其中一个页面退出时,另一个页面还保持登录状态;如果是人人网的话,从任何一个页面退出后,另外的页面也将退出。
ITeye和人人网的在这个演示中这个不同点是在我分析Session时偶然发现的一个问题,到现在还未能解决。有些问题未必有我们想得那么简单,但是个人觉得也不能因为问题复杂而不去想。本文设计的知识点是比较浅的,希望能给需要的朋友起到一个抛砖引玉的作用。为大家分析会话跟踪带来一点兴趣。分析中或许会有不对的地方,也请发现的人指正出来。大家共同进步!