Files
aijianhua/backend/middlewares/auth.js

165 lines
3.8 KiB
JavaScript
Raw 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 dbConnector = require('../utils/dbConnector');
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';
/**
* JWT认证中间件
* 验证token并附加用户信息到req对象
*/
const authMiddleware = async (req, res, next) => {
try {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return res.status(401).json({
code: 401,
message: '未提供有效的认证token',
data: null
});
}
const token = authHeader.substring(7); // 移除'Bearer '前缀
try {
// 验证token
const decoded = jwt.verify(token, JWT_SECRET);
// 查询用户信息
const users = await dbConnector.query(
'SELECT id, username, phone, email, user_type, avatar_url, status FROM users WHERE id = ?',
[decoded.userId]
);
if (users.length === 0) {
return res.status(401).json({
code: 401,
message: '用户不存在',
data: null
});
}
const user = users[0];
// 检查用户状态
if (user.status !== 1) {
return res.status(401).json({
code: 401,
message: '用户已被禁用',
data: null
});
}
// 附加用户信息到请求对象
req.user = {
id: user.id,
username: user.username,
phone: user.phone,
email: user.email,
user_type: user.user_type,
avatar_url: user.avatar_url
};
next();
} catch (jwtError) {
if (jwtError.name === 'TokenExpiredError') {
return res.status(401).json({
code: 401,
message: 'token已过期',
data: null
});
}
if (jwtError.name === 'JsonWebTokenError') {
return res.status(401).json({
code: 401,
message: '无效的token',
data: null
});
}
throw jwtError;
}
} catch (error) {
console.error('认证中间件错误:', error);
return res.status(500).json({
code: 500,
message: '服务器内部错误',
data: null
});
}
};
/**
* 可选认证中间件
* 如果提供了token就验证不提供也不报错
*/
const optionalAuth = async (req, res, next) => {
try {
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith('Bearer ')) {
const token = authHeader.substring(7);
try {
const decoded = jwt.verify(token, JWT_SECRET);
const users = await dbConnector.query(
'SELECT id, username, phone, email, user_type, avatar_url, status FROM users WHERE id = ? AND status = 1',
[decoded.userId]
);
if (users.length > 0) {
const user = users[0];
req.user = {
id: user.id,
username: user.username,
phone: user.phone,
email: user.email,
user_type: user.user_type,
avatar_url: user.avatar_url
};
}
} catch (error) {
// token无效但不阻止请求继续
console.warn('可选认证失败:', error.message);
}
}
next();
} catch (error) {
console.error('可选认证中间件错误:', error);
next();
}
};
/**
* 管理员权限检查中间件
*/
const adminRequired = (req, res, next) => {
if (!req.user) {
return res.status(401).json({
code: 401,
message: '需要登录',
data: null
});
}
if (req.user.user_type !== 'admin') {
return res.status(403).json({
code: 403,
message: '需要管理员权限',
data: null
});
}
next();
};
module.exports = {
authMiddleware,
optionalAuth,
adminRequired
};