Appearance
在 Web 发展史中,我们知道浏览器与服务器间采用的是 http 协议,而这种协议是无状态的,所以这就导致了服务器无法知道是谁在浏览网页,但很明显,一些网页需要知道用户的状态,例如登陆,购物车等。
所以为了解决这一问题,先后出现了四种技术,分别是隐藏表单域,URL重写,cookie,session,而用的最多也是比较重要的就是 cookie 和 session 了。
Cookie
是什么
Cookie 是浏览器保存在用户电脑上的一小段文本,通俗的来讲就是当一个用户通过 http 访问到服务器时,服务器会将一些 Key/Value 键值对返回给客户端浏览器,并给这些数据加上一些限制条件,在条件符合时这个用户下次访问服务器时,数据通过请求头又被完整地给带回服务器,服务器根据这些信息来判断不同的用户。
TIP
也就是说,Cookie 是服务器传给客户端并保存在客户端的一段信息,这个 Cookie 是有大小,数量限制的!!
Cookie 的创建
可通过两种方式来创建 Cookie:
- 服务器通过发送一个
Set-Cookie响应头部来创建 CookiehttpSet-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,来维持状态。
