HTTP是一种无状态协议。所以当某个用户发出多个请求时,服务器根本无法确定是同一用户。比如在淘宝的某个页面中,你进行了登陆操作。当你跳转到商品页时,服务端如何知道你是已经登陆的状态?如何能把一个用户的状态数据关联起来呢?所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户。
cookie
cookie是首先产生的解决办法。cookie机制采用的是在客户端保持状态的方案。
cookie 是HTTP协议的一部分, 且必须包含这部分。它的处理分为如下几步:
- 服务器向客户端发送 cookie,使用 HTTP 协议规定的 set-cookie 头操作产生一个<key,value>格式的数据元素。
- 浏览器将 cookie 保存。
- 每次浏览器发出请求都会将 cookie 发向服务器。
与cookie相关的一些参数:
- path:表示 cookie 影响到的路径,匹配该路径才发送这个 cookie。
- expires 和 maxAge:告诉浏览器这个 cookie 什么时候过期,expires 是 UTC 格式时间,maxAge 是 cookie 多久后过期的相对时间。当不设置这两个选项时,会产生 session cookie,session cookie 是 transient 的,当用户关闭浏览器时,就被清除。一般用来保存 session 的 session_id。
- secure:当 secure 值为 true 时,cookie 在 HTTP 中是无效,在 HTTPS 中才有效。
- httpOnly:浏览器不允许脚本操作 document.cookie 去更改 cookie。一般情况下都应该设置这个为 true,这样可以避免被 xss 攻击拿到 cookie。
cookie可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。
cookie 虽然很方便,但是使用 cookie 有一个很大的弊端,cookie 中的所有数据在客户端就可以被修改,数据非常容易被伪造,那么一些重要的数据就不能存放在 cookie 中了,而且如果 cookie 中数据字段太多会影响传输效率。为了解决这些问题,就产生了 session。
session
session机制采用的是在服务器端保持状态的方案,其数据是保留在服务器端的,可以放在 文件、数据库、或内存中。session 的运作通过一个 session_id,同时在客户端保存session_id 来进行。在客户端保存session_id的机制有:
- cookie
- URL重写
- 表单隐藏域
- cookie
当请求到来时,服务器首先检查这个客户端的请求里是否已包含了一个session_id,如果已包含则说明以前已经为此客户端创建过session,服务器就按照session_id把这个session检索出来使用,进行数据的保存和修改;若检索不到,会新建一个session。如果客户端请求不包含session_id,则为此客户端创建一个session并且生成一个与此session相关联的session id,这个session_id将被在本次响应中返回给客户端保存。
但cookie可以被人为的禁止,则必须有其他机制以便在cookie被禁止时
仍然能够把session_id传递回服务器。经常被使用的一种技术叫做URL重写,表单隐藏域。
- URL重写
就是把session_id直接附加在URL路径的后面。我们就可以在地址栏看到这样的字符串。
sessionid=KWJHUG6JJM65HS2K6
- 表单隐藏域
就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session_id传递回服务器。比如:
<form name="testform" action="/xxx">
<input type="hidden" name="session_id" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzW">
<input type="text">
</form>
所以,总结一下:
Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。