前言
本文描述了在PC端Web页面登录最常见的表单登录Cookie方式。
对其他登录方式,比如表单登录Token方式、SSO单点登录、手机端登录和第三方授权登录方式,将在以后用专门文章介绍。
表单登录Cookie方式
![c7b37931354d10353aaf754a8cc5ba8d.png](https://i-blog.csdnimg.cn/blog_migrate/81b4306c87b5e4840b67b67121fe3316.png)
以登录用户Web邮箱为例:
- 用户在客户端(浏览器)上打开Web邮箱页面。
- 输入用户名和密码(统称为Credentials),提交表单HTTP request。
- 服务端验证Credentials通过,则创建Session,并存储Session数据。
- 服务端返回HTTP response,其中HTTP response header中的
Set-Cookie
字段用来存放服务器返回的Cookies,包括Session ID和其他Cookies。 - 浏览器将
Set-Cookie
中的Cookies存储在浏览器中的特定区域。 - 用户登录后,在后续浏览器发起HTTP request时都在HTTP request header的
Cookie
字段中附上Session ID和其他Cookies。 - 服务端验证HTTP请求中的Session ID有效性通过,则正常响应请求,并可根据该Session ID获取Session数据。
- 用户退出后,客户端(浏览器)将销毁该Session相关的Cookies,服务端将销毁Session数据。
因为用Session ID来标识用户登录状态,这种登录方式也被称为Session登录方式。
什么是Cookie
参见:
Using HTTP cookies
HTTP cookie(Web cookie,浏览器cookie)是服务器发送到用户Web浏览器的一小段数据。浏览器可以存储它,并将其与以后的请求一起发送回同一服务器。
谁生成Cookie?
服务端,一般是是Web server,也可以是应用程序。
谁存储Cookie?
服务端和客户端(浏览器)都存储。
服务端存储Session。
客户端(浏览器)存储Session ID和其他Cookies。
谁验证Cookie?
客户端在后续的HTTP请求中附上Session ID和其他Cookies,由服务端进行验证。
Cookie与Session的关系
因为HTTP连接是无状态的,但是在真正的Web页面操作时,需要维持用户登录状态(Session),所以在服务端需要为每个登录的用户创建Session数据。
Session ID是Session数据的唯一标识。
SessionID由服务端通过HTTP response header的Set-Cookie
字段返回给客户端(浏览器),客户端(浏览器)将Set-Cookie
字段作为Cookies来存储。
客户端(浏览器)在后续发起的HTTP request header中的Cookie
字段附上Session ID用于服务端作用户身份认证。
小结:
- Session ID是Session数据的唯一标识,用来唯一表示一次用户登录状态。
- Session ID是Cookies中的一个字段。
在浏览器中查看Cookies
参见:
- View, Edit, And Delete Cookies with Chrome DevTools
通过在Chrome浏览器查看Cookies,来了解Cookies的属性。
按F12
打开Chrome Dev Tools,打开 Application / Storage / Cookies。
Cookies下会按HTTP headers Origin 列出有Cookies。
Cookies列表的字段包括:
Name
: Cookie名称。Value
:Cookie值。Domain
:Cookie的域名,限制浏览器只能将该Cookie发送到哪个域名。Path
:Cookie的路径,限制浏览器只能将该Cookie发送到域名的哪个URL。值为/
时,表示可以发送给域名下的所有URL。Expires / Max-Age
:Cookie的有效时间或最大年龄。Permanent cookies在有效期后被浏览器删除;Session cookies的该值为Session
,在当前会话结束后被删除。Size
:Cookie的大小(bytes),包括Cookie名称和Cookie值。HttpOnly
:为true(打勾)时表示,只能用于发送HTTP请求,不允许JavaScript读取。用来防止含有敏感数据(比如Session ID)的Cookie被恶意JavaScript盗取后发起跨站脚本攻击(cross-site scripting (XSS))。Secure
:为true(打勾)时,表示该Cookie只能通过HTTPS连接来发送。SameSite
:该特性用来防止跨站请求伪造攻击(cross-site request forgery attacks (CSRF))。值为Strict
时,来限制只能发送给和Origin一样的站点。值为Lax
时,限制只能发送给和Origin一样的域名,或用户从外部站点导航到该URL。值为None
时,不作该限制。该特性为实验特性。Priority
:Cookie优先级,默认为Medium
。该特性已作废。
在Chrome Dev Tools中,打开Network,选择XHR,打开某个连接,打开Headers,查看Request Headers的Cookie
字段,就可以看到浏览器发起HTTP请求时附上的Cookie的值。
Cookies的安全性
Cookies的安全性包括:
- Cookie内容的安全
- Cookie传输的安全
- 防止非法的访问Cookie
- 防止Cookie的泄漏
Cookie内容的安全
以Session ID为例。
一个安全的Session ID应该满足:
- Session ID是全局唯一的,用来唯一表示一次用户登录状态。
- Session ID是有时效性的,在Session结束后被自动销毁。参见上面的
Expires / Max-Age
。 - Session ID是无法猜测的。
关于如何生成Session ID,参见:
Generating Sessions Ids
Cookie的传输的安全
参见上面的Secure
。
强烈建议使用HTTPS连接,因为使用HTTP时,所有的HTTP request和response报文都是明文传输的。
使用HTTPS连接时,即使报文被窃听,黑客也无法解密出报文,也就无法盗取Cookie。
防止非法的访问Cookie
参见上面的HttpOnly
和SameSite
来防止跨站脚本攻击(cross-site scripting (XSS))和跨站请求伪造攻击(cross-site request forgery attacks (CSRF))。
防止Cookie的泄漏
服务器除了在HTTP reponse header的Set-Cookie
中返回Cookies外,不要在其他地方返回。
客户端(浏览器)除了浏览器自动在HTTP request header的Cookie
中附上Cookies外,不要在其他地方读取、提供、显示和打印Cookies。
另外,不要使用来路不明的浏览器。
Cookies的隐私性
Cookies除了用来记录Session ID维持用户登录状态外,还可以用来记录购物车、用户偏好和用户行为数据。
因为Cookies可用来记录用户隐私数据,因此国外一些网站会很明显地提示网站将会收集你的隐私数据用于改进用户体验。
Cookies的使用限制
因为客户端(浏览器)每次发起HTTP连接时都要带着Cookies,因此Cookies数据条目不能太多,数据量也不能太大,不然就会降低Web页面的访问性能。
另外只有Chrome才会自动存储和处理Cookies,所以在手机App或小程序访问页面时,通常不会使用Cookies方式,而是使用Token方式,这将在以后单独进行介绍。
会话保持
在有多台Web服务器时,需要通过负载均衡对外提供服务。这时就需要注意会话保持的问题。
如果使用了云供应商提供的负载均衡实例,可以开启会话保持功能,在HTTP负载均衡时通过Cookies来将请求总是转发给同一台Web服务器,在TCP负载均衡时通过客户端IP将请求总是转发给同一台Web服务器。
这种做法有一个问题,在Web服务器更新应用版本时,会导致连接到该服务器上的所有用户会话都会中断。
比较好的做法是,通过Redis分布式缓存实例来在服务端统一存储用户会话,此时Web服务器相当于无状态的,即使更Web服务器上的应用版本,用户会话也不会受影响。
参考文档
- Using HTTP cookies
- HTTP headers Origin
- A practical, Complete Tutorial on HTTP cookies
- https://www.valentinog.com/blog/cookies/#session-based-authentication
- View, Edit, And Delete Cookies with Chrome DevTools
- Learn how HTTP Cookies work
- Generating Sessions Ids
- Cookies vs. Tokens: The Definitive Guide