霜天部落 | 关注LAMP高性能、高并发架构的设计与研究

浅谈对session和cookie的理解

本文是关于 cookie 机制和 session 机制的基础知识,部分文字来自网络。

一、 cookie 机制和 session 机制的区别

具体来说 cookie 机制采用的是在客户端保持状态的方案,而 session 机制采用的是在服务器端保持状态的方案。由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以 session 机制可能需要借助于 cookie 机制来达到保存标识的目的,但实际上还有其他选择,比如说重写 URL和隐藏表单域。

二、会话 cookie 和持久 cookie 的区别

如果不设置过期时间,则表示这个 cookie 生命周期为浏览器会话期间,只要关闭浏览器窗口, cookie 就消失了。这种生命期为浏览会话期的 cookie 被称为会话 cookie 。会话 cookie 一般不保存在硬盘上而是保存在内存里。

如果设置了过期时间(setMaxAge(60*60*24)), 浏览器就会把 cookie 保存到硬盘上,关闭后再次打开浏览器,这些 cookie 依然有效直到超过设定的过期时间。存储在硬盘上的 cookie 可以在不同 的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的 cookie ,不同的浏览器有不同的处理方式。

三、如何利用实现自动登录

当用户在某个网站注册后,就会收到一个惟一用户ID的 cookie 。客户后来重新连接时,这个用户ID会自动返回,服务器对它进行检查,确定它是否为注册用户且选择了自动登录,从而使用户不需要给出明确的用户名和密码,就可以访问服务器上的资源。

四、如何根据用户的爱好定制站点

网站可以使用 cookie 记录用户的意愿。对于简单的设置,网站可以直接将页面的设置存储在 cookie 中完成定制。然而对于更复杂的定制,网站只需仅将一个惟一的标识符发送给用户,由服务器端的数据库存储每个标识符对应的页面设置。

五、 cookie 的发送

1.创建 cookie 对象
2.设置最大时效
3.将 cookie 放入到HTTP响应报头

如果你创建了一个 cookie ,并将他发送到浏览器,默认情况下它是一个会话级别的 cookie :存储在浏览器的内存中(服务器自动创建一个 cookie 并将 session Id作为key, session Id的值作为value发送到客户端浏览器内存中),用户退出浏览器之后被删除。如果你希望浏览器将该 cookie 存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该 cookie 。 发送 cookie 需要将 cookie 插入到一个Set-cookie HTTP请求报头中。由于这个方法并不修改任何之前指定的 Set-cookie 报头,而是创建新的报头,因此我们将这个方法称为是addcookie ,而非 setcookie 。同样要记住响应报头必须在任何文档内容发送到客户端之前设置。

六、 cookie 的读取

不同的动态语言有不同的调用方法,在此不再举例。

七、如何使用 cookie 检测初访者

A.使用动态语言获取 cookie 数组
B.在循环中检索指定名字的 cookie 是否存在以及对应的值是否正确
C.如果是则退出循环并设置区别标识
D.根据区别标识判断用户是否为初访者从而进行不同的操作

八、使用 cookie 检测初访者的常见错误

不能仅仅因为 cookie 数组中不存在在特定的数据项就认为用户是个初访者。如果 cookie 数组为null,客户可能是一个初访者,也可能是由于用户将 cookie 删除或禁用造成的结果。但是,如果数组非null,也不过是显示客户曾经到过你的网站或域,并不能说明他们曾经访问过你的服务。依据路径的设置,其中的任何 cookie 都有可能返回给用户的浏览器。

正确的做法是判断 cookie 数组是否为空且是否存在指定的 cookie 对象且值正确。

九、如何使用 cookie 记录各个用户的访问计数

1.获取 cookie 数组中专门用于统计用户访问次数的 cookie 的值
2.将值转换成int型
3.将值加1并用原来的名称重新创建一个 cookie 对象
4.重新设置最大时效
5.将新的 cookie 输出

十、 session 在不同环境下的不同含义

session ,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个 session 。然而当 session 一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含义。

session 在Web开发环境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候 session 也用来指这种解决方案的存储结构。

十一、 session 机制

session 机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存息。

当程序需要为某个客户端的请求创建一个 session 的时候,服务器首先检查这个客户端的请求里是否包含了一个 session 标识-称为 session id,如果已经包含一个 session id则说明以前已经为此客户创建过 session ,服务器就按照 session id把这个 session 检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的 session 对象,但用户人为地在请求的URL后面附加上一个 session 的参数)。如果客户请求不包含 session id,则为此客户创建一个 session 并且同时生成一个与此 session 相关联的 session id,这个 session id将在本次响应中返回给客户端保存。

十二、保存 session id的几种方式

A.保存 session id的方式可以采用 cookie ,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。

B. 由于 cookie 可以被人为的禁止,必须有其它的机制以便在 cookie 被禁止时仍然能够把 session id传递回服务器,经常采用的一种技术叫做URL重写,就是把 session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个 session id。

C.另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把 session id传递回服务器。

十三、 session 什么时候被创建

一个常见的误解是以为 session 在有客户端访问时就被创建,然而事实是直到某server端程序启用 session 时才被创建。
由于 session 会消耗内存资源,因此,如果不打算使用 session ,应该在所有的程序中关闭它。

十四、 session 何时被删除

session 在下列情况下被删除:
A.程序释放 session
B.距离上一次收到客户端发送的 session id时间间隔超过了 session 的最大有效时间
C.服务器进程被停止

再次注意:关闭浏览器只会使存储在客户端浏览器内存中的 session cookie 失效,不会使服务器端的 session 对象失效,除非此时服务器端刚好 session 失效时间到了。

十五、URL重写有什么缺点

对所有的URL使用URL重写,包括超链接,form的action,和重定向的URL。每个引用你的站点的URL,以及那些返回给用户的URL(即使通过间接手段,比如服务器重定向中的Location字段)都要添加额外的信息。

这意味着在你的站点上不能有任何静态的HTML页面(至少静态页面中不能有任何链接到站点动态页面的链接)。因此,每个页面都必须动态生成。如果用户离开了会话并通过书签或链接再次回来,会话的信息都会丢失,因为存储下来的链接含有错误的标识信息 – 该URL后面的 session ID已经过期了。

十六、使用隐藏的表单域有什么缺点

仅当每个页面都是有表单提交而动态生成时,才能使用这种方法。单击常规的超文本链接并不产生表单提交,因此隐藏的表单域不能支持通常的会话跟踪,只能用于一系列特定的操作中,比如在线商店的结账过程。

十七、会话跟踪的基本步骤

1.访问与当前请求相关的会话对象
2.查找与会话相关的信息
3.存储会话信息
4.废弃会话数据

十八、 cookie 的过期和 session 的超时有什么区别

会话的超时由服务器来维护,它不同于 cookie 的失效日期。
首先,会话一般基于驻留内存的 cookie ,不是持续性的 cookie ,因而也就没有截至日期。

十九、 session cookie 和 session 对象的生命周期是一样的吗

当用户关闭了浏览器虽然 session cookie 已经消失,但 session 对象仍然保存在服务器端,直到其失效时间。

二十、是否只要关闭浏览器, session 就消失了

程序一般都是在用户做log off的时候发个指令去删除 session ,然而浏览器从来不会主动在关闭之前通知服务器它将要被关闭,因此服务器根本不会有机会知道浏览器已经关闭。服务器会一直保留这个会话对象直到它处于非活动状态超过设定的间隔为止。

之所以会有这种错误的认识,是因为大部分 session 机制都使用会话 cookie 来保存 session id,而关闭浏览器后这个 session id就消失了,再次连接到服务器时也就无法找到原来的 session 。如果服务器设置的 cookie 被保存到硬盘上,或者使用某种手段改写浏览器发出的 HTTP请求报头,把原来的 session id发送到服务器,则再次打开浏览器仍然能够找到原来的 session 。恰恰是由于关闭浏览器不会导致 session 被删除,迫使服务器为 session 设置了一个失效时间,当距离客户上一次使用 session 的时间超过了这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把 session 删除 以节省存储空间。

由此我们可以得出如下结论:
关闭浏览器,只会是浏览器端内存里的 session cookie 消失,但不会使保存在服务器端的 session 对象消失,同样也不会使已经保存到硬盘上的持久化 cookie 消失。

补充:那如何做到在浏览器关闭时删除 session 呢 ?

严格的讲,做不到这一点。可以做一点努力的办法是在所有的客户端页面里使用 javascript 代码 window.oncolose 来监视浏览器的关闭动作,然后向服务器发送一个请求来删除 session 。但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。