JWT

在正式介绍 JWT 之前,先来讲讲什么是认证、授权、Cookie、Session、Token ...

认证与授权

认证是指验证当前用户的身份,常见的有使用账号密码登录、手机号验证码等方式认证身份

授权是指用户拥有的操作权限,比如非常核心的功能只有超级管理员可以操作,而一般核心的功能管理员可以操作,而普通用户只能操作一般的功能

一般数据库中会存储用户的认证和授权信息,比如账号密码、用户拥有的权限等信息

Cookie、Session、Token

HTTP 是无状态的,但大多数场景都需要保存用户的登录状态,就出现了三种不同的方式:Cookie、Session、Token

Cookie:服务器响应中包含会话状态,浏览器需要在本地保存这些状态信息,后续的请求需要将这些状态添加到请求头中一起发送给服务器,服务器便可进行会话跟踪

Session:基于 Cookie 实现,不同在于会话状态保存在服务器,仅仅响应 SessionID 给浏览器,后续的请求只需要将 SessionID 添加到请求头的 Cookie 中即可

Token:访问资源的凭证,用户认证成功后服务器会签发一个 Token,包含用户认证和授权信息,服务器不需要记录状态

问题一:禁用 Cookie 后,怎么使用 Session?

在 HTTP 请求头中有一个 Cookie 字段,Session 基于 Cookie 实现,只需要将 SessionID 添加到请求头中即可,如:Cookie: SessionID

所以 Cookie 对于 Session 来说只是一个传递 SessionID 的媒介,当 Cookie 被禁用后,可以将 SessionID 添加到 URL 中,如:https://xxx.com?SessionID=xxx

问题二:Session 和 Token 的异同?

首先,Session 和 Token 都是保存用户登录信息的机制,可以让用户在多个页面切换时服务器依旧可以自动获取登录信息,无需重新登录

然后,Session 和 Token 不同之处有:

分布式会话

基于 Session 机制的认证过程如下:

因为 Session 保存在服务器中,这种方式在单机中毫无问题,但如果是服务器集群,那么就可能出现同一个用户两次请求发送到不同服务器,导致无法获取会话状态信息的情况

针对这种情况,主要有两种解决方案:

JWT

前面介绍了这么多,下面正式开始介绍 JWT (JSON Web Token)。当提到 Token 时,一般都是指 JWT,虽然 Token 不同的实现方式,但 JWT 已经成为事实上的标准

JWT 原理:服务器认证成功后,生成一个 JSON 对象,发回给用户,如下:

此后,用户与服务器通信时,都需要发回这个 JSON 对象,服务器依靠该对象认证用户身份。为了防止数据被篡改,服务器在生成该对象时会加上数字签名

有了 JWT 之后,服务器就不需要存储任何 Session 信息,也就变成无状态,也方便扩展

JWT 数据结构

在介绍 JWT 原理时,只是简单的说了一下 JWT 是一个 JSON 对象,但这并不严谨~~

从结果上来看,JWT 是一个很长的字符串,中间用.将其分割成三个部分,可以在网站 jwt.io 上对字符串进行解码。下面给出一个 JWT 例子:

JWT 的三个部分分别为:

Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常如下:

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据,JWT 规定了 7 个官方字段,供选用:

除了官方规定的字段外,还可以定义私有字段,如下所示:

注意:JWT 默认不加密,任何人都可以读到,所以不要把秘密信息放在这个部分

Signature 部分是对前两个部分的签名,防止数据被篡改。首先需要一个签名密钥,该密钥只有服务器知道,不能泄漏给其它人。按照下面公式生成签名:

JWT 使用方式

客户端收到服务器返回的 JWT 后,可以存储在 Cookie 中,也可以存储在 localStorage 中。如果存储在 Cookie 中,每次请求都会自动发送,但这样不能跨域

更好的做法是将 JWT 放在 HTTP 请求头的Authorization字段中:

JWT 特点

JWT Demo

下面给出一个自己实现的 JWT Demo,虽然它只是一个小 Demo,但里面涉及到的内容还挺多的,先给出项目仓库链接 JWT Demo

总结一下这个 Demo 中包含的内容:

参考文章