Files
nxxmdata/bank-backend/controllers/authController.js

301 lines
6.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.

/**
* 认证控制器
* @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
};