30.session
# 无状态的HTTP协议
HTTP无状态:HTTP协议对事务处理是没有记忆能力的, 也就是说服务器不知道客户端是什么状态。当我们向服务器发送请求后,服务器解析此请求,然后返回对应的相应,服务器负责完成整个过程。 这个过程是完全独立的,服务器不会记录前后状态的变化,也就是缺少状态记录。 也就是说如果后续处理需要前面的信息,就必须重传,这导致需要额外传递一些前面的重复请求,才能获取后续响应,然而这种效果显然太浪费资源了。
因为HTTP协议是一个无状态协议,即Web端的应用程序无法区分收到的两个HTTP请求是否是同一个浏览器发出的。为了跟踪用户状态,服务器可以向浏览器分配一个唯一ID,并以Cookie的形式发送到浏览器,浏览器在后续访问时总是附带此Cookie,这样,服务器就可以识别用户身份。
# 为什么有session?
首先大家知道,http协议是无状态的,即你连续访问某个网页100次和访问1次对服务器来说是没有区别对待的,因为它记不住你。
在一些场合,确实需要服务器记住当前用户怎么办?比如用户登录邮箱后,接下来要收邮件、写邮件,总不能每次操作都让用户输入用户名和密码吧,为了解决这个问题,session的方案就被提了出来,事实上它并不是什么新技术,而且也不能脱离http协议以及任何现有的web技术。
原理很简单,假设你访问网页时就像逛澡堂,第一次进去你是没有钥匙的,这个时候你交了钱服务台就分配一把钥匙给你,你走到哪里都要带上,因为这是你身份的唯一标识,接下来你用这把钥匙可以去打开一个专有的储物柜存储你的衣物,游完泳,你再用钥匙去打开柜子拿出衣物,最后离开游泳池时,把钥匙归还,你的这次游泳的过程就是一次session,或者叫做会话,在这个例子中,钥匙就是session的key,而储物柜可以理解为存储用户会话信息的介质。
Session是一种在服务器端存储用户信息的机制,用于跟踪和管理用户在应用程序中的活动。当用户第一次访问应用程序时,服务器会为该用户创建一个唯一的session ID,该ID会被存储在cookie中,然后在用户的每个请求中都将该ID传回服务器。服务器使用该ID来查找存储在服务器上的与该ID相关的session数据,从而维护用户状态。
# 那么在web server中如何实现session呢
想必看了上面的例子你会很容易理解,主要是解决两个问题,一个是钥匙的问题,一个是存储用户信息的问题。对于第一个问题,即什么东西可以让你每次请求都会自动带到服务器呢?如果你比较了解http协议,那么答案一目了然,就是cookie,如果你想为用户建立一次会话,可以在用户授权成功时给他一个cookie,叫做会话id,它当然是唯一的,比如PHP就会为建立会话的用户默认set一个名为phpsessid,值看起来为一个随机字符串的cookie,如果下次发现用户带了这个cookie,服务器就知道,哎呀,刚刚这位顾客来了。
剩下的是解决第二个问题,即如何存储用户的信息,服务器知道会话id为abc的用户来了,那abc想存储自己的私人信息,比如购物车信息,如何处理?这个时候可以用内存、也可以用文件,也可以用数据库了,但有个要求是,数据需要用用户的会话id即可取到,比如php就默认会把会话id为abc的用户会话数据存储到/tmp/phpsess_abc的文件里面,每次读取都要反序列化程序可以理解的数据,写的时候又需要序列化为持久的数据格式。
# 使用场景
- 用户登录状态的维护
- 购物车和订单管理
- 多步骤表单的填写和提交
- 保持用户偏好设置和语言选择
# 区别
- 与cookie相比,session可以存储更多的信息,包括负责的对象和数据结构。而cookie只能存储简单的键值对(cookie设计初衷用于维护HTTP状态,不用于存储数据)
- session数据存储在服务器上,对用户不可见,因此更加安全可靠
- cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。【同时我们也看到,由于在服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上还有其他选择。】
# 误区
在谈论Session机制时,会有这样一种误解:只要关闭浏览器,Session就消失了。 这种理解是错误的。 对于Session来说,除非程序通知服务器删除Session,否则服务器会一直保留。
但是在我们关闭浏览器时,浏览器不会主动在关闭之前通知服务器它将要关闭,所以服务器不会有机会知道浏览器已经关闭。之所以有这种错觉,是因为大部分Session机制使用会话Cookie来保存SessionID信息,而关闭浏览器后,Cookie消失了,再次连接服务器时,就无法找到原来的Session了