一、什么是Jwt Refresh Token
Json Web Token(JWT)是一种在网络间传输信息的方式,常用于身份验证和授权。使用JWT需要在客户端使用密钥对数据进行签名,然后将令牌发回服务器以进行验证。但是,如果需要长时间访问某些内容,许多身份验证和授权令牌将过期。JWT Refresh Token允许客户端在过期的JWT之前提供一个新的JWT令牌。 JWT Refresh Token是一种标准的身份验证令牌,它允许客户端在过期之前自动重新生成新的令牌,而不需要进行用户重新登录或者授权。
二、Jwt Refresh Token 的工作原理
JWT是一种声明式的身份验证/授权机制,它由三部分组成:头部、载荷和签名。第一部分是头部,用于指定JWT类型和使用的签名算法。第二部分是载荷,包含有关用户的信息和其他元数据。第三部分是签名,用于验证JWT的完整性。这三个部分都是使用Base64进行编码的。 现在,假设在JWT令牌中有一个称为设置Refresh Token的字段,值为true。当该令牌在过期之前发现时,可以使用令牌中包含的“Refresh Token”生成新的JWT令牌并发送给客户端。 以下是JWT和Refresh Token工作的简要流程:
- 使用服务器端密钥和其他信息为JWT生成令牌。
- 返回JWT令牌和Refresh Token
- 客户端记录令牌和Refresh Token,并在每个之间进行快速切换。
- 当JWT令牌过期时,客户端使用Refresh Token请求新的JWT令牌。
- 刷新新的JWT令牌并继续使用。
三、Jwt Refresh Token 的优势
使用JWT Refresh Token有几个优点:
- 颁发长期有效的访问令牌。使用Refresh Token可以将访问令牌的有效期延长到较长的时间。
- 降低服务器负载。使用Refresh Token可以减少对服务器的访问,因为客户端可以在一段时间内自行处理验证和更新令牌。
- 提高安全性。使用Refresh Token可以减少发生中间人攻击的机会,因为JWT令牌有效期非常短,而Refresh Token有效期长。
四、如何实现Jwt Refresh Token
实现JWT Refresh Token需要进行以下步骤:
1. 创建初始JWT令牌
const jwt = require('jsonwebtoken');
const jwtKey = 'your_jwt_secret';//jwt密钥
const jwtExpirySeconds = 300; //JWT Token的有效期为5分钟
const userName = 'your_username';//用户名称
const token = jwt.sign({ userName }, jwtKey, {
algorithm: 'HS256',
expiresIn: jwtExpirySeconds
});
2. 生成Refresh Token
为每个JWT令牌生成一个Refresh Token,用于在令牌到期之前获取新的令牌。
const RefreshToken = require('../models/refresh-token.model');//引入 RefreshToken 模型
const generateRefreshToken = async (userName) => {
const refreshToken = new RefreshToken({
userName: userName,
token: crypto.randomBytes(40).toString('hex'), //生成一个40位的随机Refresh Token
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) //Refresh Token有效期7天
});
await refreshToken.save();
return refreshToken;
}
3. 验证JWT令牌并生成新的JWT令牌
const verify = require('./verify');//引入 JWT 验证方法
const refreshToken = async (oldToken) => {
const oldDecodedToken = jwt.decode(oldToken);
const refreshToken = await RefreshToken.findOne({ userName: oldDecodedToken.userName });
if (!refreshToken) return;//传递的旧Token的refreshToken不存在
//验证RefreshToken是否过期
if (refreshToken.expires.valueOf() < Date.now()) {
await refreshToken.remove();//删除RefreshToken
return;//refreshToken已过期
}
//验证JWT令牌的签名,以确保它没有被改变
const { algorithm } = jwt.decode(oldToken, { complete: true }).header;
await verify(oldToken, jwtKey, algorithm);
const newToken = jwt.sign({ userName: oldDecodedToken.userName }, jwtKey, {
algorithm: algorithm,//使用相同的算法
expiresIn: jwtExpirySeconds
});
return newToken;
}
4. 使用Refresh Token获取新的JWT令牌
const express = require('express');
const router = express.Router();
const RefreshToken = require('../models/refresh-token.model');
const jwtRefreshToken = require('../middleware/jwt-refreshtoken.middleware');
const jwt = require('jsonwebtoken');
const jwtKey = 'your_jwt_secret';//jwt密钥
router.post('/', jwtRefreshToken, async (req, res) => {
try {
const oldToken = req.token;//传递的旧的JWT令牌
const newToken = await refreshToken(oldToken);//生成新的JWT令牌
if (!newToken) {
res.status(401).send("Unauthorized");//新的JWT令牌被拒绝
return;
}
res.json({ token: newToken });//发送新的JWT令牌
} catch (err) {
res.status(500).send(err);//服务器错误
}
});
module.exports = router;
五、总结
Jwt Refresh Token 是一种长期有效的身份验证令牌,可以提高客户端的使用体验,降低服务器负载和提高安全性。实现 JWT Refresh Token 具有重要的意义,需要根据具体的业务需求进行定制化开发。