Token 加密实现
前端 Token 生成、加密与验证的实现方式
问题
介绍如何实现 Token 加密,包括 JWT 的生成、签名和验证。
解答
JWT 结构
JWT(JSON Web Token)由三部分组成,用 . 连接:
Header.Payload.Signature
- Header:算法和类型
- Payload:数据载荷
- Signature:签名验证
Node.js 实现 JWT
const crypto = require('crypto');
// Base64URL 编码
function base64UrlEncode(str) {
return Buffer.from(str)
.toString('base64')
.replace(/=/g, '')
.replace(/\+/g, '-')
.replace(/\//g, '_');
}
// Base64URL 解码
function base64UrlDecode(str) {
str = str.replace(/-/g, '+').replace(/_/g, '/');
// 补齐 padding
while (str.length % 4) {
str += '=';
}
return Buffer.from(str, 'base64').toString();
}
// 生成签名
function createSignature(header, payload, secret) {
const data = `${header}.${payload}`;
return crypto
.createHmac('sha256', secret)
.update(data)
.digest('base64')
.replace(/=/g, '')
.replace(/\+/g, '-')
.replace(/\//g, '_');
}
// 生成 Token
function generateToken(payload, secret, expiresIn = 3600) {
const header = {
alg: 'HS256',
typ: 'JWT'
};
// 添加过期时间
const now = Math.floor(Date.now() / 1000);
payload = {
...payload,
iat: now, // 签发时间
exp: now + expiresIn // 过期时间
};
const encodedHeader = base64UrlEncode(JSON.stringify(header));
const encodedPayload = base64UrlEncode(JSON.stringify(payload));
const signature = createSignature(encodedHeader, encodedPayload, secret);
return `${encodedHeader}.${encodedPayload}.${signature}`;
}
// 验证 Token
function verifyToken(token, secret) {
const parts = token.split('.');
if (parts.length !== 3) {
throw new Error('Invalid token format');
}
const [encodedHeader, encodedPayload, signature] = parts;
// 验证签名
const expectedSignature = createSignature(encodedHeader, encodedPayload, secret);
if (signature !== expectedSignature) {
throw new Error('Invalid signature');
}
// 解析 payload
const payload = JSON.parse(base64UrlDecode(encodedPayload));
// 检查过期时间
if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) {
throw new Error('Token expired');
}
return payload;
}
// 使用示例
const secret = 'my-secret-key';
const token = generateToken({ userId: 123, role: 'admin' }, secret, 7200);
console.log('Token:', token);
const decoded = verifyToken(token, secret);
console.log('Decoded:', decoded);
前端存储与使用
// 存储 Token
function saveToken(token) {
// 推荐使用 httpOnly cookie(需后端配合)
// 前端可用 localStorage,但要注意 XSS 风险
localStorage.setItem('token', token);
}
// 获取 Token
function getToken() {
return localStorage.getItem('token');
}
// 请求拦截器添加 Token
axios.interceptors.request.use(config => {
const token = getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// 响应拦截器处理过期
axios.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
// Token 过期,跳转登录
localStorage.removeItem('token');
window.location.href = '/login';
}
return Promise.reject(error);
}
);
使用 jsonwebtoken 库
const jwt = require('jsonwebtoken');
const secret = 'my-secret-key';
// 生成
const token = jwt.sign(
{ userId: 123 },
secret,
{ expiresIn: '2h' }
);
// 验证
try {
const decoded = jwt.verify(token, secret);
console.log(decoded);
} catch (err) {
console.log('验证失败:', err.message);
}
关键点
- JWT 由 Header、Payload、Signature 三部分组成,使用 Base64URL 编码
- 签名使用 HMAC-SHA256 算法,保证数据不被篡改
- Payload 不加密,敏感信息不要放入
- Token 存储推荐 httpOnly Cookie,防止 XSS 攻击
- 前端需处理 Token 过期的自动刷新或重新登录逻辑
目录