jwt鉴权机制
1、摘要
JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本质就是一个字符串书写规范,作用是用来在用户和服务器之间传递安全可靠的信息。
2. JWT是什么
根据维基百科的定义,JSON WEB Token(JWT,读作 [/dʒɒt/]),是一种基于JSON的、用于在网络上声明某种主张的令牌(token)。JWT通常由三部分组成: 头信息(header), 消息体(payload)和签名(signature)。
在目前前后端分离的开发过程中,使用token鉴权机制用于身份验证是最常见的方案,流程如下
- 假设用户要登录一个APP,用户就需要输入用户名和密码,然后发送给APP的服务器
- 服务器验证过用户发来的用户名和密码后,就会生成一个token,
- 服务端返回JWT信息给用户,JWT中
- 用户发送请求的时候一般会在HTTP头部加上这个Token
- 服务器收到Token后,对Token进行核实,Token验证通过,且没有过期
- 用户直接登录,不需要再次输入用户名密码,服务器只需识别头部的Token就可以确认用户身份
这里生成的Token就用的JWT这种数据结构
✒️Token的携带
token可以放在Cookie,Authorization,或者Body里面
什么情况下使用JWT比较适合?
3. JWT 的数据结构
Token,分成了三部分,头部(Header)、载荷(Payload)、签名(Signature),并以.进行拼接。其中头部和载荷都是以JSON格式存放数据,只是进行了base64 编码(secret 部分是否进行 base64 编码是可选的,header 和 payload 则是必须进行 base64 编码),由于编码过程是可逆的,如果得知编码方式后,那么整个 jwt 串便是明文了,所以pyaload中一定不能放密码等重要信息。
header
头部主要是用来指明签名的算法,避免消息被篡改,jwt 中常用的签名算法是 HS256,常见的还有md5,sha 等,签名算法是不可逆的。声明算法的字段名为alg,同时还有一个typ的字段,默认JWT即可。以下示例中算法为HS256,1
{"alg": HS256, "typ": "JWT"}
pyaload
负载主要是用来存放数据,一般可以存放相应用户数据来生成不同的JWT1
2
3
4
5
6
7
8
9 "payload": {
"data": [
{
"tooltt": "https://tooltt.com"
}
],
"iat": 1650451633,
"exp": 1650556799
}
JWT规定了7个官方字段,供选用
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。
1 |
|
由于编码的可逆性,不要把秘密信息放在这个部分。
Signature
签名是对头部和负载两个部分进行签名,防止数据篡改。
签名里面有个核心就是要定义一个密钥,这个密钥只有服务器能知道,然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
公式如下:
1 |
|
一旦前面两部分数据被篡改,只要服务器加密用的密钥没有泄露,得到的签名肯定和之前的签名不一致
4. 鉴权机制时如何实现的
相关代码已上传github https://github.com/blueskyadd/JWT
基础服务器的搭建
首先初始化项目1
npm init -y
第二步 安装 express jsonwebtoken依赖1
npm i express jsonwebtoken -D
第三步,调整配置文件
为了方便我们本地调试代码,安装nodemon
nodemon用来监视node.js应用程序中的任何更改并自动重启服务,非常适合用在开发环境中
1 | npm i nodemon -D |
打开pakage.json文件调整scripts,调试命令
然后创建app.js文件
监听3000端口,运行npm run egg
启动服务
登录生成JWT
借助第三方库jsonwebtoken,通过jsonwebtoken 的 sign 方法生成一个 token
- 第一个参数指的是 Payload
- 第二个是秘钥,服务端特有
- 第三个参数是 option,可以定义 token 过期时间
此处的密钥,使用crypto来生成30位的随机字符串
然后来尝试调用接口,我这里使用的是REST Client
插件,可以直接安装,
然后创建一个以http结尾的文件
然后点击send Request 发送请求,请求成功后,可以看到返回的信息
校验token
使用jwt.verify(token,secretOrPublicKey,[options,callback])来
验证token的合法性;
同理发送get请求,将登录返回的token, 复制到请求头的authorization字段上,拼接Bearer 空格 token
这是遵守OAuth2.0规则的
然后点击发送,返回认证成功的信息
5. JWT的优缺点
优点
- json具有通用性,所以可以跨语言组成简单,
- 字节占用小,便于传输服务端无需保存会话信息,
- 很容易进行水平扩展一处生成,多处使用,
- 可以在分布式系统中,
- 解决单点登录问题可防护CSRF攻击
缺点
- payload部分仅仅是进行简单编码,所以只能用于存储逻辑必需的非敏感信息
- 需要保护好加密密钥,一旦泄露后果不堪设想
- 为避免token被劫持,最好使用https协议
6. 推荐阅读
1.浏览器渲染流程
2.数据包是如何完整的发送到应用程序
3.浏览器的进程和线程
4.重定向与负载均衡
5.JS模块化
6.深入理解URL
7.HTTP报文是什么
8.React SSR 的实现