# Cookie + Session 登录
HTTP 是一种无状态的协议,客户端每次发送请求时,首先要和服务器端建立一个连接,在请求完成后又会断开这个连接。这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法判断本次请求和上一次请求是否来自同一个用户,进而也就无法判断用户的登录状态。
为了解决 HTTP 无状态的问题,Lou Montulli 在 1994 年的时候,推出了 Cookie。
Cookie 是服务器端发送给客户端的一段特殊信息,这些信息以文本的方式存放在客户端,客户端每次向服务器端发送请求时都会带上这些特殊信息。
有了 Cookie 之后,服务器端就能够获取到客户端传递过来的信息了,如果需要对信息进行验证,还需要通过 Session
客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个便是
Session对象。
有了 Cookie 和 Session 之后,我们就可以进行登录认证了
# Cookie + Session 实现流程
Cookie + Session 的登录方式是最经典的一种登录方式,现在仍然有大量的企业在使用。
用户首次登录时:

- 用户访问
a.com/pageA,并输入密码登录。 - 服务器验证密码无误后,会创建
SessionId,并将它保存起来。 - 服务器端响应这个 HTTP 请求,并通过
Set-Cookie头信息,将SessionId写入Cookie中
服务器端的
SessionId可能存放在很多地方,例如:内存、文件、数据库等。
第一次登录完成之后,后续的访问就可以直接使用 Cookie 进行身份验证了:

- 用户访问
a.com/pageB页面时,会自动带上第一次登录时写入的Cookie。 - 服务器端比对
Cookie中的SessionId和保存在服务器端的SessionId是否一致。 - 如果一致,则身份验证成功
Cookie + Session 存在的问题
虽然我们使用
Cookie + Session的方式完成了登录验证,但仍然存在一些问题:
- 由于服务器端需要对接大量的客户端,也就需要存放大量的
SessionId,这样会导致服务器压力过大。 - 如果服务器端是一个集群,为了同步登录态,需要将
SessionId同步到每一台机器上,无形中增加了服务器端维护成本。 - 由于
SessionId存放在Cookie中,所以无法避免CSRF攻击
# Token 登录
为了解决 Session + Cookie 机制暴露出的诸多问题,我们可以使用 Token 的登录方式。
Token 是服务端生成的一串字符串,以作为客户端请求的一个令牌。当第一次登录后,服务器会生成一个 Token 并返回给客户端,客户端后续访问时,只需带上这个 Token 即可完成身份认证。
# Token 机制实现流程
用户首次登录时:

- 用户输入账号密码,并点击登录。
- 服务器端验证账号密码无误,创建 Token。
- 服务器端将 Token 返回给客户端,由客户端自由保存
后续页面访问时:

- 用户访问
a.com/pageB时,带上第一次登录时获取的Token。 - 服务器端验证
Token,有效则身份验证成功
# Token 机制的特点
- 服务器端不需要存放 Token,所以不会对服务器端造成压力,即使是服务器集群,也不需要增加维护成本。
- Token 可以存放在前端任何地方,可以不用保存在 Cookie 中,提升了页面的安全性。
- Token 下发之后,只要在生效时间之内,就一直有效,如果服务器端想收回此 Token 的权限,并不容易。
# Token 的生成方式
最常见的 Token 生成方式是使用 JWT(Json Web Token),它是一种简洁的,自包含的方法用于通信双方之间以 JSON 对象的形式安全的传递信息。
上文中我们说到,使用 Token 后,服务器端并不会存储 Token,那怎么判断客户端发过来的 Token 是合法有效的呢?
答案其实就在 Token 字符串中,其实 Token 并不是一串杂乱无章的字符串,而是通过多种算法拼接组合而成的字符串,我们来具体分析一下。
JWT 算法主要分为 3 个部分:header(头信息),playload(消息体),signature(签名)。
header 部分指定了该 JWT 使用的签名算法:
header = '{"alg":"HS256","typ":"JWT"}' //
`HS256` 表示使用了 HMAC-SHA256 来生成签名。
playload 部分表明了 JWT 的意图:
