Cookie 和 Session

  1. Cookie机制

Cookie 是客户端保存用户信息的一种机制,用来记录用户的一些信息。Cookie 是小型文本文件,内容为一系列键值对。Cookie 是由 HTTP 服务器设置的,保存在浏览器中。

实现机制:

  • 浏览器向某个 URL 发起 HTTP 请求(可以是任何请求,比如 GET 一个页面,或者 POST 一个登录表单)
  • 对应的服务器收到该 HTTP 请求,并计算应当返回给浏览器的 HTTP 响应。在 HTTP 响应报文的响应头中添加 Set-Cookie 的字段,值为要设置的 Cookie(UA 至少要支持 300 项 Cookie,每一项 Cookie 至少要支持到 4096 字节,每个域名至少支持 20 项 Cookie)
  • 浏览器收到对应服务器的 HTTP 响应,在响应头中发现 Set-Cookie 字段,将该字段的值保存在内存或者硬盘中。(Set-Cookie 字段的值可以是很多项的 Cookie,每一项都可以指定过期时间 Expires,默认是用户关闭浏览器时。)
  • 浏览器下一次再给该服务器发送 HTTP 请求时,会将 Cookie 附加在 HTTP 的请求头字段 Cookie 中。(浏览器可以存储多个域名下的Cookie,但只发送当前请求的域名曾经指定的Cookie, 这个域名也可以在Set-Cookie字段中指定)
  • 服务器收到这个 HTTP 请求,发现请求头中有 Cookie 字段,和他自己那块的信息做匹配,就可以知道之前是不是和这个用户对话过。
  • 过期的 Cookie 会被浏览器自动删除。

总之,服务器是通过 Set-Cookie 这个响应头字段来指示浏览器保存 Cookie,浏览器通过 Cookie 这个请求头字段来告诉服务器之前的状态的。

  1. Cookie的不可跨域性

根据 Cookie 规范,域名不一样,二者不能互相操作彼此的 Cookie,只能在同源的 HTTP 请求中携带。比如说:www.tmall.comwww.taobao.com 的域名不同,就不能互相操作,将文章开头的问题抛出来,那么阿里是怎么做到两个域之间共享 Cookie 的?

  1. Cookie的防篡改机制

服务器可以为每个 Cookie 生成签名,由于用户篡改 Cookie 后无法生成对应的签名,服务器就可以得知用户对 Cookie 进行了篡改。校验过程如下:

  • 服务器配置一个字符串,叫Secret,签名通过 Hash(‘xxxxxxxx’ + ‘false’)生成,就是要设置的值和 Secret 相加再取哈希。
  • 在设置 Cookie 的时候,不仅设置 author 的值为 false,在值的后面设置一个签名,最终设置的 Cookie 是 author=false|xxxxxxxx。
  • 服务器发送给浏览器的响应报文中将 Cookie 放在 Set-Cookie: author=false|xxxxxxxx
  • 用户加入要篡改 Cookie ,设置 Cookie 字段为 Cookie: author=true|???????。
  • 服务器收到该 HTTP 请求,发现 Cookie: author=true|???????。服务器开始校验:Hash(‘true’ + ‘????????’),就会发现用户提供的签名不正确,不会发送 HTTP 响应了。

Cookie 是明文传输的,只要服务器设置过一次 author=true|xxxx 就可以知道 true 的签名为 xxxx,以后就可以用这个签名来欺骗服务器。所以,Cookie 中最好不要存放敏感数据。一般来讲,Cookie 中只会放一个 SessionId,而 Session 存储在服务端。

Session

  1. Session机制

Session 是服务端的保持状态的解决方案,存储在服务端,避免了在客户端 Cookie 中存储敏感数据。Session 可以存储在 HTTP 服务器的内存中,也可以存储在内存数据库中。以存储在数据库中的 Session 为例

  • 用户提交包含用户名和密码的表单,发送 HTTP 请求
  • 服务端验证用户名和密码的正确性,正确则把当前用户名(通常是用户对象)存储在数据库中,同时生成他在数据库中的唯一 ID(SessionId,通过SessionId 可以从数据库中取出对应的用户对象,敏感数据[比如author=true]都存储在这个用户对象中)
  • 服务端设置 Cookie 为 sessionId=xxxxxx|checksum 发送 HTTP 响应
  • 用户收到 HTTP 响应后,看不到任何敏感数据,在此后的请求中发送该 Cookie 给服务器
  • 服务器收到 HTTP 请求后,发现 Cookie 中有 SessionId,进行防篡改验证,通过验证,则根据此 ID 从数据库中取出对应的用户对象,查看该用户的状态并继续执行业务逻辑。
  1. Session的生命周期

为了获得更高的存取速度,服务器一般会把 Session 存放在内存中。Session 在用户第一次访问服务器的时候自动创建,Session 生成之后,只要用户继续访问,服务器就会更新 Session 的最后访问时间,并维护该 Session。用户每访问服务器一次,无论是否读写 Session,服务器都认为用户的 Session active 了一次。

  1. Session的有效期

为了防止内存溢出,服务器会把长时间内没有 active 的 Session 从内存删除。这个时间就是 Session 的超时时间,如果过了超时时间没有访问过服务器,Session 就自动失效了。