2026-07-27 11:28:33 +08:00

83 lines
2.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const jwt = require("jsonwebtoken");
const logger = require("../utils/logger");
const { sendError } = require("../utils/response");
/**
* JWT 认证中间件
* 验证请求头中的 token如果有效则允许访问否则返回 401
* 支持从 Authorization header 或 URL 查询参数token中获取 token
*/
const jwtAuth = (req, res, next) => {
// 优先从请求头中获取 token
let token = null;
const authHeader = req.headers.authorization;
if (authHeader) {
// 支持两种格式: "Bearer token" 或 "token"
token = authHeader.startsWith("Bearer ")
? authHeader.substring(7)
: authHeader;
} else if (req.query && req.query.token) {
// 如果请求头中没有,尝试从 URL 查询参数中获取(用于文件下载等场景)
token = req.query.token;
}
if (!token) {
return sendError(res, "未提供认证令牌", "No token provided", 401);
}
const secret = process.env.JWT_SECRET || "your-secret-key";
jwt.verify(token, secret, (err, decoded) => {
if (err) {
if (err.name === "TokenExpiredError") {
return sendError(res, "令牌已过期", "Token expired", 401);
}
if (err.name === "JsonWebTokenError") {
return sendError(res, "无效的令牌", "Invalid token", 401);
}
logger.error("Token验证失败:", err);
return sendError(res, "令牌验证失败", "Token verification failed", 401);
}
// 将解码后的用户信息添加到请求对象
req.user = decoded;
next();
});
};
/**
* 可选的 JWT 认证中间件
* 如果提供了有效 token 则解析用户信息,否则继续执行(不阻止请求)
*/
const optionalJwtAuth = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader) {
return next();
}
const token = authHeader.startsWith("Bearer ")
? authHeader.substring(7)
: authHeader;
if (!token) {
return next();
}
const secret = process.env.JWT_SECRET || "your-secret-key";
jwt.verify(token, secret, (err, decoded) => {
if (!err) {
req.user = decoded;
}
next();
});
};
module.exports = {
jwtAuth,
optionalJwtAuth,
};