温故而知新 关于SESSION和COOKIE

    之前就有一篇COOKIE的类似温故文章了(http://blog.csdn.net/banmuhuangci/archive/2008/11/05/3229297.aspx),此文中重点叙述了COOKIE的Expires属性的不可读取问题,以至于重新发回COOKIE时需要再次设置Expires属性。

    今天写这篇文章主要阐述一下SESSION的一些细节问题以及SESSION和COOKIE的关系

 

     首先,论坛上经常会遇到的一个问题是,SESSION安全吗?答案是:安全,SESSION是保存在服务器上的,客户端无法擅自修改值,因此是安全的,但是如果作为登录状态的判断,SESSION是否安全就要看你是如何通过SESSION判断登录状态了,这个问题不是SESSION的问题,而是开发者的思路问题。

 

    另外就是,COOKIE在不设置Expires属性时 关闭浏览器及过期,SESSION也是这样吗?答案:当然不是。

    SESSION的生存周期只与其过期时间有关,也就是说,在ASP.NET 或ASP中如果不调用 Session.Clear()或Session.Abandon()方法,那么SESSION只会在预设的Session.TimeOut所设置的时间后消亡。因此,SESSION消亡的条件就只有两个A、过期,B、调用销毁方法主动销毁。

     可是很多人会问,既然如此为什么我关闭浏览器后立刻打开页面,依然没有SESSION的回话状态呢?

     这种情况就要仔细的关心下SESSION和COOKIE的关系了。

     

     在ASP.NET中,SESSION是需要COOKIE支持的,如果在用户客户端禁用了COOKIE或在配置文件中设置SESSION为无COOKIE的情况下,客户端浏览器的地址栏会以明文方式显示SESSION标识出来以用来在服务器与客户端之间传递保持状态。因此,当我们正常情况下使用SESSION的时候,实际上打开浏览器访问网站,服务器分配一个会话给客户端后也就同时创建了一个没有设置Expires属性的COOKIE用来保存该客户端SESSION的标识,这样客户端请求服务器的时候,服务器会先获取并检查这个伴随SESSION一起建立的COOKIE里的值,然后对比服务器上的SESSION.ID,知道是哪个客户端的请求后再将属于这个客户端的SESSION用于程序处理。这就是在默认情况下有COOKIE状态的SESSION工作的基本流程,否则服务器怎么可能知道是哪个客户端发送的请求,大家都知道HTTP是无状态的。

     结合之前关于COOKIE的文章和现在分析SESSION的工作流程,我们就知道,当客户端关闭浏览器之后,实际上消亡的不是SESSION而是伴随SESSION创建的COOKIE,这个COOKIE消亡了之后,客户端对服务器的请求中就不包含标识该客户端的信息,因此,服务器并不知道是哪个客户端因为对于服务器来说他是新来的,所以就会重新创建并分配一个新的SESSION给他。因此在客户端看来似乎SESSION就没了,其实并不是,SESSION还在只是没人来认领了。

 

 

实际上,COOKIE和SESSION关系密切,MS不建议使用COOKIELESS的SESSION,因为SESSION被明文写在了URL里,这样会很容易被篡改并被恶意利用。事实上,我们开发中也绝少使用COOKIELESS的SESSION,所以正常情况下,SESSION是需要依赖COOKIE的,所以COOKIE在没设置EXPRIES属性时候的特征也会蒙蔽不少新开发者。

 

需要注意的是,文中大部分提到的COOKIE是服务器创建SESSION时自动创建的为SESSION服务的COOKIE,而不是开发者手工创建的。

 

有经验的开发者通常会自定义另外的有一定有效期的COOKIE以补充解决SESSION无法长期或在关闭浏览器后“丢失”的问题。

 

最后以一个比喻来再次加深印象。

我们将整个过程想做投币存储服务

SESSION是一个储藏柜,COOKIE是一个号牌,IIS或者说服务器是我们的服务员。

当你投币(请求)的时候,服务员会给你开一个储藏柜,然后发给你一个号牌,你可以多次的拿号牌给服务员存取你对应的储藏柜里的东西,但当有一天,你搞掉了你的号牌(关闭浏览器,COOKIE消失了),这时你将无法存取你之前的储藏柜里的东西,只能重新投币然后服务员重新发给你一个号牌并重新给你开一个空的储藏柜。可是你之前的储藏柜仍然还在,里面也仍然还有你之前存储的东西。存储服务中心当然也有他们自己的规定,就是如果20天内没有人存取的柜将会被清空,里面的东西都销毁(会话过期)。当然也有用户会主动的取消自己的储藏柜(调用清楚或销毁方法)。

我们也知道,存储服务不会因为你丢失了号牌而主动去清空对应柜子的,因为他并不知道你是否真的丢失了号牌,而且他同样不知道你丢失的是哪个号牌,因为他们的号牌是随机生成而且号码是条形码或者磁卡,没有可见的数字。

 

通过这个比喻,同时你就知道为什么不建议COOKIELESS的会话了,要知道,一个明文的号牌是多么的容易伪造,作为存储服务中心的老板,你也不希望你的客户的储藏柜总是因为别人伪造号牌而丢失东西吧。

 

另外说一下 Session.Clear()和Session.Abandon()的区别,CLEAR将SESSION中的所有项都清除,也就是说,所有想都没了,SESSION中的所有项都是NULL,而ABANDON方法是直接将SESSION对象清除了。也有人说,ABANDON会触发SESSION_END事件,是的,因为END时间就是在SESSION被销毁时发生的。

posted @ 2009-09-23 18:08  ZetaChow晓代码  阅读(318)  评论(0编辑  收藏  举报