首先需要理解cookie的概念,cookie是一段不超过4KB的小型文本数据,用于记录用户信息,每次发送http请求时,在请求头上都会携带这个cookie,仅此而已。cookie有一些重要的属性:
- Name
- Value
- Domain
- Path
- Expires/Max-Age:同时存在时,Max-Age优先级更高
- Secure:该cookie只能被https发送
- HttpOnly:防止客户端通过document.cookie来访问
由于HTTP是无状态的协议,所以服务器想要识别是哪个用户发送的HTTP请求,就需要使用session或是token中的一种。
1、session
显然,如果cookie里存了一些敏感信息,例如用户的用户名和密码,是非常不安全的,所以产生了session。在用户登录后,服务器会给每一位用户生成一个独一无二的session id,一份保存在服务器,一份发送给客户端,至于客户端把session id存在cookie里还是存在storage里都可以,每次请求的时候携带session id给服务器识别用户身份就行了。
2、token
session的缺点显而易见,一是增加了服务器负担,二是如果服务器采用分布式系统,其余服务器没有存放session id则会导致无法识别,所以产生了token。以JWT为例,在用户登录时,服务器会生成一串字符串token,由3部分组成Header、Payload和Signature,以.分隔,类似下面这种:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
服务器将token发送给客户端进行保存,而服务器仅需要保存一份密钥,用于对Header和Payload进行加密后与Signature进行对比就行了。
当然,token也是可以存在cookie里或是storage里的:
1)若放在cookie里,每次请求都会自动携带,缺点是不能跨域且容易遭受CSRF攻击
2)若放在storage里,具有更灵活,更大空间,天然免疫 CSRF的特征,缺点是容易受到XSS攻击
通常,我们会放到storage里,每次发起http请求时,放到请求头的Authorization字段中。
JWT 的最大缺点是无法作废已颁布的令牌:由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
所以通常在下发access token的同时会下发一个refresh token。access token的有效期较短,每次请求都会携带,refresh token的有效期较长,仅在获取新access token的时候携带。