Files
WebWork/backend/middleware/auth.js
2025-12-21 21:50:37 +08:00

170 lines
4.5 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 db = require('../config/database');
/**
* 认证中间件 - 检查用户是否已登录
*/
const requireAuth = (req, res, next) => {
if (!req.session.user) {
return res.status(401).json({
success: false,
message: '请先登录'
});
}
next();
};
/**
* 角色权限中间件 - 检查用户是否具有指定角色
* @param {Array} allowedRoles - 允许的角色数组
*/
const requireRole = (allowedRoles) => {
return (req, res, next) => {
if (!req.session.user) {
return res.status(401).json({
success: false,
message: '请先登录'
});
}
const userRole = req.session.user.role;
if (!allowedRoles.includes(userRole)) {
return res.status(403).json({
success: false,
message: '权限不足'
});
}
next();
};
};
/**
* 获取当前用户ID
*/
const getCurrentUserId = (req) => {
return req.session.user ? req.session.user.id : null;
};
/**
* 获取当前用户角色
*/
const getCurrentUserRole = (req) => {
return req.session.user ? req.session.user.role : null;
};
/**
* 检查是否是自己的数据(学生只能访问自己的数据)
*/
const checkOwnership = async (req, res, next) => {
try {
const userId = getCurrentUserId(req);
const userRole = getCurrentUserRole(req);
// 管理员和教师可以访问所有数据
if (userRole === 'admin' || userRole === 'teacher') {
return next();
}
// 学生只能访问自己的数据
if (userRole === 'student') {
const studentId = req.params.studentId || req.body.studentId;
// 检查学生ID是否属于当前用户
const [students] = await db.execute(
'SELECT id FROM students WHERE user_id = ?',
[userId]
);
if (students.length === 0) {
return res.status(403).json({
success: false,
message: '未找到学生信息'
});
}
const userStudentId = students[0].id;
// 如果请求中没有指定学生ID默认使用当前用户的学生ID
if (!studentId) {
req.studentId = userStudentId;
return next();
}
// 检查请求的学生ID是否与当前用户的学生ID匹配
if (parseInt(studentId) !== userStudentId) {
return res.status(403).json({
success: false,
message: '无权访问其他学生的数据'
});
}
req.studentId = userStudentId;
return next();
}
// 其他角色无权访问
return res.status(403).json({
success: false,
message: '权限不足'
});
} catch (error) {
console.error('所有权检查错误:', error);
res.status(500).json({
success: false,
message: '服务器错误'
});
}
};
/**
* 输入验证中间件
*/
const validateInput = (schema) => {
return (req, res, next) => {
const { error } = schema.validate(req.body);
if (error) {
return res.status(400).json({
success: false,
message: error.details[0].message
});
}
next();
};
};
/**
* 日志记录中间件
*/
const logOperation = (operation) => {
return async (req, res, next) => {
try {
const userId = getCurrentUserId(req);
const userRole = getCurrentUserRole(req);
const ip = req.ip || req.connection.remoteAddress;
// 记录操作日志
await db.execute(
'INSERT INTO operation_logs (user_id, operation, ip_address, user_role) VALUES (?, ?, ?, ?)',
[userId, operation, ip, userRole]
);
next();
} catch (error) {
console.error('日志记录错误:', error);
// 日志记录失败不影响主要操作
next();
}
};
};
module.exports = {
requireAuth,
requireRole,
getCurrentUserId,
getCurrentUserRole,
checkOwnership,
validateInput,
logOperation
};