版权声明
- 原创作者:Sᴀғᴇᴛʏ 007
- 博客地址:https://blog.csdn.net/weixin_44437620?spm=1000.2115.3001.5343
JWT(JSON Web Token)是目前最流行的跨域认证解决方案
1. 跨域认证流程
2. JWT原理
3. JWT数据结构
实际的JWT是一个很长的字符串,中间用点(.)分隔成三个部分。
JWT的三个部分:Header(头部) Payload(负载).Signature(签名)
写成一行,就是这个样子:
Header.Payload.Signature
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Header
Header部分是一个JSON对象,描述JWT的元数据,通常是下面的样子。
{
"alg":"123456",
"typ":"JWT"
}
上面的代码中,alg属性表示签名的算法(algorithm),默认是HMAC SHA256(写成HS256);typ属性表示这个令牌(token)的类型(type),JWT令牌统一写为JWT。
最后,将上面的JSON对象使用Base64URL算法转成字符串。
Payload
Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT规定了7个官方字段
- iss(issuer): 签发人
- exp(expiration time):过期时间
- sub(subject):主题
- aud(audience): 受众
- nbf(Not Before): 生效时间
- iat(Issued At): 签发时间
- iti(JWT ID):编号
除了官方字段,也可以自定义私有字段。
{
"sub":"1234567890",
"name":"John Doe",
"admin":true
}
注意:JWT默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。
这个JSON对象也要使用Base64URL算法转成字符串。
Signature
Signature部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret),这个密钥只有服务器才知道,不能泄露给用户。然后,使用Header里面指定的签名算法(默认是HMAC SHA256),按照下面的公式产生签名。
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),secret
)
算出签名以后,把Header、Payload、Signature三个部分拼成一个字符串,每个部分之间用“点”(.)分隔,就可以返回给用户。
在JWT中,消息体是透明的,使用签名可以保证消息不被篡改。但不能实现数据加密功能。
Base64URL
前面提到,Header和Payload串型化的算法是Base64URL。这个算法跟Base64算法基本类似,但有一些小的不同。
JWT作为令牌(token),有些场合可能会放到URL(比如api.example.com/?token = xxx)。Base64有三个字符+、/和=,在URL里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_。这就是Base64URL的=算法。
4. JWT的使用方式
客户端收到服务器返回的JWT,可以存储在Cookie里面,也可以存储在localStorage。
此后,客户端每次与服务器通信,都要带上这个JWT。你可以把它放在Cookie里面自动发送,但是这样不能跨域,所以更好的做法是放在HTTP请求的头信息Authorization字段里面。
Authorization:Bearer <token>
另一种做法是,跨域的时候,JWT就放在POST请求的数据体里面。
5. JWT的几个特点
(1)JWT默认是不加密,但也可以是加密的。生成原始Token以后,可以使用密钥再次加密。
(2)JWT不加密的情况下,不能将秘密数据写入JWT。
(3)JWT不仅可以用于认证,也可以用于交换信息。有效使用JWT,可以降低服务器查询数据库的次数。
(4)JWT的最大缺点是,由于服务器不保存session状态,因此无法在使用过程中废止某个token,或者更改token的权限。也就是说,一旦JWT签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
(5)JWT本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT的有效期应该设置的比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
(6)为了减少盗用,JWT不应该使用HTTP协议明码传输,要使用HTTPS协议传输。
JWT的解决方案
在Node.js中使用JWT
推荐:https://github.com/auth0/node-jsonwebtoken
详细使用方法
//引入 jwt
const jwt = require('jsonwebtoken')
//生成 jwt (建议使用异步方法)
// const token = jwt.sign({
// foo:'bar'
// },'shhhhh')
// 异步生成token
jwt.sign({
foo:'bar'
},'shhhhh',(err,token) => {
// 失败
if(err){
return console.log('生成token失败')
}
// 成功
console.log(token)
})
//验证 jwt
jwt.verify('生成的token',
'生成token的唯一识别码(这里使用的是:shhhhh)',
(err,ret) => {
// 失败
if(err){
console.log('token认证失败')
}
// 成功
console.log(ret)
})