您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# JWT在Node中怎么使用
## 目录
- [JWT基础概念](#jwt基础概念)
- [什么是JWT](#什么是jwt)
- [JWT的组成结构](#jwt的组成结构)
- [JWT的工作原理](#jwt的工作原理)
- [Node.js环境准备](#nodejs环境准备)
- [初始化项目](#初始化项目)
- [安装必要依赖](#安装必要依赖)
- [JWT核心实现](#jwt核心实现)
- [生成JWT令牌](#生成jwt令牌)
- [验证JWT令牌](#验证jwt令牌)
- [处理令牌过期](#处理令牌过期)
- [实战应用场景](#实战应用场景)
- [用户认证系统](#用户认证系统)
- [API接口保护](#api接口保护)
- [跨服务通信](#跨服务通信)
- [安全最佳实践](#安全最佳实践)
- [密钥管理方案](#密钥管理方案)
- [令牌刷新机制](#令牌刷新机制)
- [常见攻击防护](#常见攻击防护)
- [性能优化技巧](#性能优化技巧)
- [负载压缩策略](#负载压缩策略)
- [缓存验证结果](#缓存验证结果)
- [调试与问题排查](#调试与问题排查)
- [常见错误分析](#常见错误分析)
- [日志记录策略](#日志记录策略)
- [扩展进阶](#扩展进阶)
- [自定义Claims](#自定义claims)
- [多因素认证集成](#多因素认证集成)
- [总结与展望](#总结与展望)
## JWT基础概念
### 什么是JWT
JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。这种信息可以被验证和信任,因为它是经过数字签名的。
**典型特征**:
- 紧凑的URL安全表示形式
- 可自包含(包含所有必要信息)
- 适用于分布式系统的身份验证
- 支持跨域身份验证
### JWT的组成结构
标准JWT由三部分组成,通过点(.)连接:
Header.Payload.Signature
1. **Header**(头部):
```json
{
"alg": "HS256",
"typ": "JWT"
}
Payload(负载): 包含声明(claims),分为三类:
Signature(签名): 通过指定算法对前两部分签名,例如:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
sequenceDiagram
participant Client
participant Server
Client->>Server: 登录请求(用户名/密码)
Server->>Client: 返回JWT
Client->>Server: 业务请求(携带JWT)
Server->>Client: 返回业务数据
mkdir node-jwt-demo
cd node-jwt-demo
npm init -y
npm install jsonwebtoken bcryptjs dotenv express
npm install --save-dev @types/jsonwebtoken
关键包说明:
- jsonwebtoken
:JWT核心库
- bcryptjs
:密码哈希处理
- dotenv
:环境变量管理
- express
:Web框架
const jwt = require('jsonwebtoken');
require('dotenv').config();
function generateAccessToken(user) {
return jwt.sign(
{
userId: user.id,
email: user.email
},
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
}
// 示例用法
const user = { id: 123, email: 'test@example.com' };
const token = generateAccessToken(user);
console.log('Generated Token:', token);
function authenticateToken(req, res, next) {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) {
console.error('Token verification failed:', err);
return res.sendStatus(403);
}
req.user = user;
next();
});
}
function generateTokenPair(user) {
const accessToken = jwt.sign(
{ userId: user.id },
process.env.ACCESS_TOKEN_SECRET,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ userId: user.id },
process.env.REFRESH_TOKEN_SECRET,
{ expiresIn: '7d' }
);
return { accessToken, refreshToken };
}
完整登录流程示例:
const express = require('express');
const bcrypt = require('bcryptjs');
const app = express();
app.post('/login', async (req, res) => {
try {
// 1. 验证用户凭证
const user = await User.findOne({ email: req.body.email });
if (!user) return res.status(401).send('Invalid credentials');
// 2. 验证密码
const validPassword = await bcrypt.compare(
req.body.password,
user.passwordHash
);
if (!validPassword) return res.status(401).send('Invalid credentials');
// 3. 生成令牌
const token = generateAccessToken(user);
// 4. 返回响应
res.json({
accessToken: token,
expiresIn: 3600
});
} catch (err) {
console.error('Login error:', err);
res.status(500).send('Internal Server Error');
}
});
保护路由示例:
app.get('/protected', authenticateToken, (req, res) => {
// 只有携带有效JWT才能访问
res.json({
message: 'Protected data',
user: req.user
});
});
微服务间认证示例:
// 服务A生成令牌
const serviceToken = jwt.sign(
{ service: 'service-a' },
process.env.INTER_SERVICE_SECRET,
{ expiresIn: '5m' }
);
// 服务B验证令牌
function verifyServiceToken(req, res, next) {
const token = req.headers['service-token'];
jwt.verify(token, process.env.INTER_SERVICE_SECRET, (err, decoded) => {
if (err || decoded.service !== 'service-a') {
return res.status(403).send('Forbidden');
}
next();
});
}
推荐做法: 1. 使用环境变量存储密钥
JWT_SECRET=your_strong_secret_here
ACCESS_TOKEN_SECRET=access_secret
REFRESH_TOKEN_SECRET=refresh_secret
app.post('/refresh', (req, res) => {
const refreshToken = req.body.token;
if (!refreshToken) return res.sendStatus(401);
jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
const newAccessToken = generateAccessToken({
id: user.userId
});
res.json({ accessToken: newAccessToken });
});
});
防护策略: 1. CSRF防护:SameSite Cookie属性 2. XSS防护:HttpOnly Cookie 3. 重放攻击:使用jti(JWT ID)和nonce 4. 令牌劫持:短期有效期+HTTPS
对于大型payload:
const zlib = require('zlib');
function compressPayload(payload) {
return zlib.deflateSync(JSON.stringify(payload)).toString('base64');
}
function generateCompressedToken(user) {
const compressed = compressPayload(user);
return jwt.sign(
{ data: compressed },
process.env.JWT_SECRET
);
}
使用Redis缓存已验证令牌:
const redis = require('redis');
const client = redis.createClient();
function cachedVerify(token) {
return new Promise((resolve, reject) => {
client.get(`jwt:${token}`, (err, cached) => {
if (cached) return resolve(JSON.parse(cached));
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) return reject(err);
client.setex(`jwt:${token}`, 300, JSON.stringify(decoded));
resolve(decoded);
});
});
});
}
错误 | 原因 | 解决方案 |
---|---|---|
Invalid token | 令牌格式错误 | 检查Authorization头格式 |
Token expired | 令牌过期 | 实现刷新令牌机制 |
Invalid signature | 密钥不匹配 | 验证密钥一致性 |
Algorithm mismatch | 算法不一致 | 检查header中的alg声明 |
增强版验证中间件:
function verboseAuth(req, res, next) {
const token = extractToken(req);
if (!token) {
console.warn('Authorization header missing');
return res.sendStatus(401);
}
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
if (err) {
console.error(`JWT verification failed: ${err.name}`);
console.debug('Token content:', jwt.decode(token));
return res.sendStatus(403);
}
console.log(`Authenticated user: ${decoded.userId}`);
req.user = decoded;
next();
});
}
添加业务特定声明:
function generateCustomToken(user) {
return jwt.sign(
{
// 标准声明
sub: user.id,
iat: Math.floor(Date.now() / 1000),
// 自定义声明
'https://yourdomain.com/is_premium': user.isPremium,
roles: ['user', 'editor']
},
process.env.JWT_SECRET,
{ algorithm: 'HS256' }
);
}
结合MFA的令牌生成:
function generateMfaToken(user, mfaVerified = false) {
return jwt.sign(
{
sub: user.id,
mfa: mfaVerified
},
process.env.JWT_SECRET,
{
expiresIn: mfaVerified ? '8h' : '15m'
}
);
}
最佳实践建议:对于新项目,建议采用JWT作为认证基础,但必须配合HTTPS、合理的密钥管理和完善的令牌生命周期管理方案。
完整代码示例:可参考GitHub仓库 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。