关于 jwt-authentication
为 Node.js 应用添加 JWT 身份验证的学习与实现指南,涵盖注册、登录和受保护路由,也介绍令牌刷新、基于角色的访问控制等模式。
主要功能
- 01生成并验证 JWT
- 02注册用户并验证密码
- 03用中间件保护路由
- 04刷新令牌并管理有效期
- 05实现基于角色的访问控制
适用场景
- 01为 Node.js REST API 添加身份验证
- 02使用 JWT 保护应用路由
- 03构建令牌刷新和访问控制流程
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ pluginagentmarketplace/ custom-plugin-nodejs --skill jwt-authentication安装后在 Claude Code 中输入/jwt-authentication确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/config.yamlreferences/GUIDE.mdscripts/helper.py详细介绍
JWT 身份验证技能
使用 JSON Web Token 在 Node.js 应用中实现安全、可扩展的身份验证。
快速开始
JWT 身份验证分为 4 个步骤:
- 安装 -
npm install jsonwebtoken bcryptjs - 注册 - 对密码进行哈希处理、创建用户、生成令牌
- 登录 - 验证密码、生成令牌
- 保护 - 在中间件中验证令牌
核心概念
生成 JWT
const jwt = require('jsonwebtoken');
function generateToken(userId) {
return jwt.sign(
{ id: userId },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
}
function generateRefreshToken(userId) {
return jwt.sign(
{ id: userId },
process.env.JWT_REFRESH_SECRET,
{ expiresIn: '7d' }
);
}
用户注册
const bcrypt = require('bcryptjs');
async function register(req, res) {
const { email, password, name } = req.body;
// Check if user exists
const existingUser = await User.findOne({ email });
if (existingUser) {
return res.status(409).json({ error: 'User already exists' });
}
// Hash password
const hashedPassword = await bcrypt.hash(password, 10);
// Create user
const user = await User.create({
email,
password: hashedPassword,
name
});
// Generate tokens
const accessToken = generateToken(user._id);
const refreshToken = generateRefreshToken(user._id);
res.status(201).json({
user: { id: user._id, email, name },
accessToken,
refreshToken
});
}
用户登录
async function login(req, res) {
const { email, password } = req.body;
// Find user
const user = await User.findOne({ email });
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Verify password
const isValid = await bcrypt.compare(password, user.password);
if (!isValid) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Generate tokens
const accessToken = generateToken(user._id);
const refreshToken = generateRefreshToken(user._id);
res.json({
user: { id: user._id, email: user.email },
accessToken,
refreshToken
});
}
身份验证中间件
async function authenticate(req, res, next) {
try {
// Get token from header
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No token provided' });
}
const token = authHeader.split(' ')[1];
// Verify token
const decoded = jwt.verify(token, process.env.JWT_SECRET);
// Get user
const user = await User.findById(decoded.id).select('-password');
if (!user) {
return res.status(401).json({ error: 'User not found' });
}
req.user = user;
next();
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
}
// Usage
router.get('/profile', authenticate, getProfile);
学习路径
初级(1-2 周)
- ✅ 了解 JWT 结构
- ✅ 实现注册/登录
- ✅ 创建身份验证中间件
- ✅ 保护路由
中级(3-4 周)
- ✅ 刷新令牌流程
- ✅ 基于角色的访问控制
- ✅ 密码重置流程
- ✅ 令牌黑名单
高级(5-6 周)
- ✅ OAuth 集成
- ✅ 双重身份验证
- ✅ 会话管理
- ✅ 安全最佳实践
高级模式
基于角色的访问控制
const authorize = (...roles) => {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ error: 'Not authenticated' });
}
if (!roles.includes(req.user.role)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
};
// Usage
router.delete('/users/:id',
authenticate,
authorize('admin', 'moderator'),
deleteUser
);
令牌刷新
async function refreshAccessToken(req, res) {
const { refreshToken } = req.body;
try {
const decoded = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET);
// Verify refresh token exists in database
const stored = await RefreshToken.findOne({
token: refreshToken,
userId: decoded.id
});
if (!stored) {
return res.status(401).json({ error: 'Invalid refresh token' });
}
// Generate new access token
const accessToken = generateToken(decoded.id);
res.json({ accessToken });
} catch (error) {
res.status(401).json({ error: 'Token refresh failed' });
}
}
密码重置流程
async function requestPasswordReset(req, res) {
const { email } = req.body;
const user = await User.findOne({ email });
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
// Generate reset token (short expiry)
const resetToken = jwt.sign(
{ id: user._id, purpose: 'reset' },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
// Send email with reset link
await sendResetEmail(user.email, resetToken);
res.json({ message: 'Reset email sent' });
}
async function resetPassword(req, res) {
const { token, newPassword } = req.body;
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
if (decoded.purpose !== 'reset') {
return res.status(400).json({ error: 'Invalid token' });
}
const hashedPassword = await bcrypt.hash(newPassword, 10);
await User.findByIdAndUpdate(decoded.id, { password: hashedPassword });
res.json({ message: 'Password reset successful' });
} catch (error) {
res.status(400).json({ error: 'Invalid or expired token' });
}
}
安全最佳实践
- ✅ 使用强 JWT 密钥(32 个以上字符,随机生成)
- ✅ 访问令牌设置较短的有效期(15 分钟 - 1 小时)
- ✅ 刷新令牌设置较长的有效期(7 天 - 30 天)
- ✅ 将刷新令牌存储在数据库中
- ✅ 使用 bcrypt 对密码进行哈希处理(10 轮以上)
- ✅ 在生产环境中使用 HTTPS
- ✅ 实施速率限制
- ✅ 验证所有输入
- ✅ 不要在 JWT 负载中存储敏感数据
JWT 结构
header.payload.signature
Header (base64):
{
"alg": "HS256",
"typ": "JWT"
}
Payload (base64):
{
"id": "user123",
"iat": 1516239022,
"exp": 1516242622
}
Signature:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
常见 JWT 声明
iss- 颁发者sub- 主体(用户 ID)aud- 受众exp- 过期时间iat- 签发时间nbf- 生效时间
适用场景
以下情况适合使用 JWT 身份验证:
- 构建无状态 REST API
- 需要可扩展性(无需服务端会话)
- 移动应用身份验证
- 微服务架构
- 单点登录(SSO)
相关技能
- Express REST API(保护 API 端点)
- 数据库集成(存储用户)
- 测试与调试(测试身份验证流程)
- 性能优化(令牌缓存)
资源
评论
支持 Markdown