Cookie 与 Session
在 Web 发展史中,我们知道浏览器与服务器间采用的是 http
协议,而这种协议是无状态的,所以这就导致了服务器无法知道是谁在浏览网页,但很明显,一些网页需要知道用户的状态,例如登陆,购物车等。
所以为了解决这一问题,先后出现了四种技术,分别是隐藏表单域,URL重写,cookie,session,而用的最多也是比较重要的就是 cookie 和 session 了。
# Cookie
# 是什么
Cookie
是浏览器保存在用户电脑上的一小段文本,通俗的来讲就是当一个用户通过 http
访问到服务器时,服务器会将一些 Key/Value
键值对返回给客户端浏览器,并给这些数据加上一些限制条件,在条件符合时这个用户下次访问服务器时,数据通过请求头又被完整地给带回服务器,服务器根据这些信息来判断不同的用户。
也就是说,Cookie
是服务器传给客户端并保存在客户端的一段信息,这个 Cookie
是有大小,数量限制的!!
# Cookie 的创建
可通过两种方式来创建 Cookie:
- 服务器通过发送一个
Set-Cookie
响应头部来创建 CookieSet-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
- 浏览器通过
document.cookie
可以读写 Cookie
Cookie 的属性值包括:
属性 | 作用 |
---|---|
name | Cookie 名称 |
value | 如果用于保存用户登录态,应该将该值加密,不能使用明文的用户标识 |
path | 允许访问此 Cookie 的页面路径 |
domain | 允许访问此 Cookie 的域名 |
expires/max-age | 指定 Cookie 的生存期 |
http-only | 不能通过 JS 访问 Cookie,减少 XSS 攻击 |
secure | 只能在协议为 HTTPS 的请求中携带 |
same-site | 规定浏览器不能在跨域请求中携带 Cookie,减少 CSRF 攻击 |
如果不设置 expires/max-age 这个 cookie 默认是 Session 的,也就是关闭浏览器该 cookie 就消失了
其中 sameSite
可以设置 3 类值:
Strict
: 严格模式,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 CookieLax
: 宽松模式,大多数情况不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外None
: Chrome 计划将Lax
变为默认设置。这时,网站可以选择显式关闭 SameSite 属性,将其设为 None。不过,前提是必须同时设置 Secure 属性(Cookie 只能通过 HTTPS 协议发送),否则无效
服务端通过 Set-Cookie
创建 Cookie 后,根据过期时间的不同,可区分为会话级别 Cookie 和 持久级别 Cookie:
- 会话级别 Cookie:未指定过期时间,在浏览器关闭之后 Cookie 就会失效
- 持久级别 Cookie:设置了过期时间,保存在硬盘的 Cookie,在过期时间之后失效
现在 Cookie 保存在了客户端,当我们去请求一个 URL 时,浏览器会根据这个 URL 路径,将符合条件的 Cookie 放在请求头中传给服务器。
# Session
Cookie 是有大小限制和数量限制的,并且越来越多的 Cookie 代表客户端和服务器的传输量增加,可不可以每次传的时候不传所有 Cookie 值,而只传一个唯一 ID,通过这个 ID 直接在服务器查找用户信息呢?答案是有的,这就是我们的 Session。
Session 是基于 Cookie 来工作的,同一个客户端每次访问服务器时,只要当浏览器在第一次访问服务器时,服务器设置一个 ID 并保存一些信息(例如登陆就保存用户信息,视具体情况),并把这个 ID 通过 Cookie 存到客户端,客户端每次和服务器交互时只传这个 ID,就可以实现维持浏览器和服务器的状态,而这个 ID 通常是 NAME
为 JSESSION
的一个 Cookie。
实际上,有四种方式让 Session 正常工作:
- 通过 URL 传递 SessionID
- 通过 Cookie 传递 SessionID
- 通过 SSL 传递 SessionID
- 通过隐藏表单传递 SessionID
第一种情况:
当浏览器不支持 Cookie 功能时,浏览器会将用户的 SessionCookieName (默认为 JSESSIONID)重写到用户请求的 URL 参数中。格式:/path/Servlet;name=value;name2=value2?Name3=value3
第三种情况:
会根据 javax.servlet.request.ssl_session
属性值设置 SessionID。
注:如果客户端支持 Cookie,又通过 URL 重写,Tomcat 仍然会解析 Cookie 中的 SessionID 并覆盖 URL 中的 SessionID。
# 小结
# 二者的异同
相同点(有关系的地方):
- Session 和 Cookie 都是为了让 http 协议有状态而存在
- Session 通过 Cookie 工作,Cookie 传输的 SessionID 让 Session 知道这个客户端到底是谁
不同点:
- Session 将信息保存到服务器,Cookie 将信息保存在客户端
# 工作流程
当浏览器第一次访问服务器时,服务器创建 Session 并将 SessionID 通过 Cookie 带给浏览器保存在客户端,同时服务器根据业务逻辑保存相应的客户端信息保存在 session 中;客户端再访问时上传 Cookie,服务器得到 Cookie 后获取里面的 SessionID,来维持状态。