/** * 认证控制器 * @file authController.js * @description 处理用户认证相关的请求 */ const jwt = require('jsonwebtoken'); const { User, Role } = require('../models'); const { validationResult } = require('express-validator'); /** * 用户登录 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ const login = async (req, res) => { try { // 验证请求参数 const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, message: '请求参数错误', errors: errors.array() }); } const { username, password } = req.body; // 查找用户 const user = await User.findOne({ where: { username }, include: [{ model: Role, as: 'role' }] }); if (!user) { return res.status(401).json({ success: false, message: '用户名或密码错误' }); } // 检查用户状态 if (user.status !== 'active') { return res.status(401).json({ success: false, message: '账户已被禁用,请联系管理员' }); } // 验证密码 const isValidPassword = await user.validPassword(password); if (!isValidPassword) { // 增加登录失败次数 user.login_attempts += 1; if (user.login_attempts >= 5) { user.status = 'locked'; user.locked_until = new Date(Date.now() + 30 * 60 * 1000); // 锁定30分钟 } await user.save(); return res.status(401).json({ success: false, message: '用户名或密码错误' }); } // 重置登录失败次数 user.login_attempts = 0; user.locked_until = null; user.last_login = new Date(); await user.save(); // 生成JWT令牌 const token = jwt.sign( { userId: user.id, username: user.username, role: user.role?.name || 'user' }, process.env.JWT_SECRET || 'your_jwt_secret_key_here', { expiresIn: process.env.JWT_EXPIRES_IN || '24h' } ); // 返回成功响应 res.json({ success: true, message: '登录成功', data: { token, user: { id: user.id, username: user.username, name: user.real_name, email: user.email, phone: user.phone, role: user.role?.name || 'user', avatar: user.avatar, lastLogin: user.last_login }, expiresIn: process.env.JWT_EXPIRES_IN || '24h' } }); } catch (error) { console.error('登录错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 用户登出 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ const logout = async (req, res) => { try { // 在实际应用中,可以将token加入黑名单 res.json({ success: true, message: '登出成功' }); } catch (error) { console.error('登出错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 刷新令牌 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ const refreshToken = async (req, res) => { try { const { userId } = req.user; // 查找用户 const user = await User.findByPk(userId, { include: [{ model: Role, as: 'role' }] }); if (!user || user.status !== 'active') { return res.status(401).json({ success: false, message: '用户不存在或已被禁用' }); } // 生成新的JWT令牌 const token = jwt.sign( { userId: user.id, username: user.username, role: user.role?.name || 'user' }, process.env.JWT_SECRET || 'your_jwt_secret_key_here', { expiresIn: process.env.JWT_EXPIRES_IN || '24h' } ); res.json({ success: true, message: '令牌刷新成功', data: { token, expiresIn: process.env.JWT_EXPIRES_IN || '24h' } }); } catch (error) { console.error('刷新令牌错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 获取当前用户信息 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ const getCurrentUser = async (req, res) => { try { const { userId } = req.user; // 查找用户 const user = await User.findByPk(userId, { include: [{ model: Role, as: 'role' }] }); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } res.json({ success: true, message: '获取用户信息成功', data: { id: user.id, username: user.username, name: user.real_name, email: user.email, phone: user.phone, role: user.role?.name || 'user', avatar: user.avatar, status: user.status, lastLogin: user.last_login, createdAt: user.created_at } }); } catch (error) { console.error('获取用户信息错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; /** * 修改密码 * @param {Object} req 请求对象 * @param {Object} res 响应对象 */ const changePassword = async (req, res) => { try { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ success: false, message: '请求参数错误', errors: errors.array() }); } const { userId } = req.user; const { oldPassword, newPassword } = req.body; // 查找用户 const user = await User.findByPk(userId); if (!user) { return res.status(404).json({ success: false, message: '用户不存在' }); } // 验证旧密码 const isValidPassword = await user.validPassword(oldPassword); if (!isValidPassword) { return res.status(400).json({ success: false, message: '原密码错误' }); } // 更新密码 user.password = newPassword; await user.save(); res.json({ success: true, message: '密码修改成功' }); } catch (error) { console.error('修改密码错误:', error); res.status(500).json({ success: false, message: '服务器内部错误' }); } }; module.exports = { login, logout, refreshToken, getCurrentUser, changePassword };