83 lines
2.1 KiB
JavaScript
83 lines
2.1 KiB
JavaScript
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,
|
||
};
|
||
|