session与cookie

考虑一个问题:

如何抓取一个访问受限的网页?如校内好友的主页,个人新鲜事页面等。

显然,通过浏览器,我们可以手动输入用户名密码来访问目标页面,所谓“抓取”,只不过需要使用程序来模拟完成同样的工作,因此需要了解“登陆”过程中到底发生了什么。

对未登录用户,服务器强制用户跳转到登陆页面,用户键入用户名密码并提交,服务器将用户POST的信息与数据库中信息比对,如通过则跳转至landing page。那么在我们访问其他页面的时候,服务端如何判断我们的身份呢?由于HTTP协议是无状态的,显然,服务器不可能直接知道我们在上一秒刚刚登录成功。

最简单的思路,就是用户每个POST请求中,都需要带上用户名与密码来标识自己的身份;这样虽然可行,但大大加重了服务器的负担(对于每个request都需要到数据库验证),也大大降低了用户体验(每个页面都需要重新输入用户名密码,每个页面都带有登录表单)。

因此,诞生了一个解决方案:cookie。cookie,简而言之就是在本地计算机保存一些用户操作的历史信息(当然包括登录信息),并在用户再次访问该站点时浏览器通过HTTP协议将本地cookie内容发送给服务器,从而完成验证,或继续上一步操作。

进一步的,诞生了另外一种解决方案:session,简而言之就是在服务器上保存用户操作的历史信息。但该方式下,仍然需要将发送请求的客户端与session对象进行对应,所以可以借助cookie机制来获取客户端的标识(即session id),也可以通过GET方式将id提交给服务器。session id,即服务器上session对象文件的名称,由服务器负责产生,保证随机性与唯一性,相当于一个随机密钥,避免在握手或传输中暴露用户真实密码,类似的设计思想在SSO与OpenID中也经常用到。

再插入一个问题:为什么对于一些网站,关闭浏览器之后,session就失效了?

从上文可以知道,session一般通过cookie来保存session id,如果cookie设置为关闭浏览器就删除(expire),那么无论如何设置session的超时机制,由于浏览器重新启动时再也找不到原来的cookie了,因此服务器只能重新为其分配session id。

问题3:cookie和session的区别?

如上文所述,session和cookie的目的相同,都是为了克服http协议无状态的缺陷,但完成的方法不同。session通过cookie,在客户端保存session id,而将用户的其他会话消息保存在服务端的session对象中,与此相对的,cookie需要将所有信息都保存在客户端。因此cookie存在着一定的安全隐患,例如本地cookie中保存的用户名密码被破译,或cookie被其他网站收集(例如:1. appA主动设置域B cookie,让域B cookie获取;2. XSS,在appA上通过javascript获取document.cookie,并传递给自己的appB)。

在当初写php App时,知道通过SSO可以从Session中获取userid,但不知其所以然,于是遇到一个奇怪的问题:浏览器A标签脚本执行过程中,打开B标签访问同一个脚本,会被pending,直到A执行完毕。原因该脚本执行了session_start(),而php session_start()后对该session的写入是排他的,只有当脚本执行结束或显式执行session_destroy()才能释放session文件锁。因为不知道session的工作原理,被困扰了整整一个工作日!类似的问题还有因为不了解Lamp中字符编码的转换规则,导致某些在gbk和gb2312差集中的文字无法入库。

所以,知其然,还需要知其所以然。磨刀不误砍柴工,授人以渔,做web开发之前,有必要将一些必要知识了解清楚,才不会在用到时候捉襟见肘,或是在调bug时候如无头苍蝇乱转。做好自身建设,永远比case by case地被动满足来得高明。

posted on 2012-01-18 20:46  魏梦  阅读(3075)  评论(3编辑  收藏  举报

导航