177 lines
4.9 KiB
TypeScript
177 lines
4.9 KiB
TypeScript
// 导入Express的Request和Response类型
|
||
import { Request, Response } from 'express';
|
||
// 导入bcrypt用于密码加密和验证
|
||
import bcrypt from 'bcrypt';
|
||
// 导入jsonwebtoken用于生成和验证JWT令牌
|
||
import jwt from 'jsonwebtoken';
|
||
// 导入数据源配置
|
||
import { AppDataSource } from '../config/database';
|
||
// 导入管理员用户模型
|
||
import { AdminUser } from '../models/AdminUser';
|
||
|
||
/**
|
||
* 管理员认证控制器
|
||
* 处理管理员登录、登出和获取当前用户信息等认证相关操作
|
||
*/
|
||
export class AdminAuthController {
|
||
/**
|
||
* 管理员登录
|
||
* 验证用户名和密码,生成JWT令牌并设置到cookie中
|
||
* @param req - Express请求对象,包含用户名和密码
|
||
* @param res - Express响应对象
|
||
*/
|
||
async login(req: Request, res: Response) {
|
||
try {
|
||
// 从请求体中获取用户名和密码
|
||
const { username, password } = req.body;
|
||
|
||
// 验证用户名和密码是否为空
|
||
if (!username || !password) {
|
||
return res.status(400).json({
|
||
success: false,
|
||
message: '用户名和密码不能为空'
|
||
});
|
||
}
|
||
|
||
// 获取管理员用户仓库
|
||
const adminUserRepository = AppDataSource.getRepository(AdminUser);
|
||
// 根据用户名查找管理员用户
|
||
const adminUser = await adminUserRepository.findOne({
|
||
where: { username }
|
||
});
|
||
|
||
// 用户不存在
|
||
if (!adminUser) {
|
||
return res.status(401).json({
|
||
success: false,
|
||
message: '用户名或密码错误'
|
||
});
|
||
}
|
||
|
||
// 验证密码是否正确
|
||
const isPasswordValid = await bcrypt.compare(password, adminUser.passwordHash);
|
||
|
||
// 密码错误
|
||
if (!isPasswordValid) {
|
||
return res.status(401).json({
|
||
success: false,
|
||
message: '用户名或密码错误'
|
||
});
|
||
}
|
||
|
||
// 检查账号状态是否被禁用
|
||
if (adminUser.status !== 1) {
|
||
return res.status(403).json({
|
||
success: false,
|
||
message: '账号已被禁用'
|
||
});
|
||
}
|
||
|
||
// 生成JWT令牌,包含用户ID、用户名和角色ID
|
||
const token = jwt.sign(
|
||
{
|
||
id: adminUser.id,
|
||
username: adminUser.username,
|
||
roleId: adminUser.roleId
|
||
},
|
||
process.env.JWT_SECRET || 'your-secret-key',
|
||
{ expiresIn: '2h' }
|
||
);
|
||
|
||
// 将令牌设置到cookie中,配置安全选项
|
||
res.cookie('admin_token', token, {
|
||
httpOnly: true, // 仅HTTP访问,防止XSS攻击
|
||
secure: process.env.NODE_ENV === 'production', // 生产环境仅HTTPS
|
||
sameSite: 'strict', // 防止CSRF攻击
|
||
maxAge: 2 * 60 * 60 * 1000 // 2小时过期
|
||
});
|
||
|
||
// 返回登录成功响应
|
||
return res.json({
|
||
success: true,
|
||
message: '登录成功',
|
||
data: {
|
||
token,
|
||
user: {
|
||
id: adminUser.id,
|
||
username: adminUser.username,
|
||
realName: adminUser.realName,
|
||
roleId: adminUser.roleId
|
||
}
|
||
}
|
||
});
|
||
} catch (error) {
|
||
console.error('管理员登录失败:', error);
|
||
return res.status(500).json({
|
||
success: false,
|
||
message: '服务器内部错误'
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 管理员登出
|
||
* 清除cookie中的令牌
|
||
* @param req - Express请求对象
|
||
* @param res - Express响应对象
|
||
*/
|
||
async logout(req: Request, res: Response) {
|
||
try {
|
||
// 清除cookie中的令牌
|
||
res.clearCookie('admin_token');
|
||
return res.json({
|
||
success: true,
|
||
message: '退出登录成功'
|
||
});
|
||
} catch (error) {
|
||
console.error('管理员退出登录失败:', error);
|
||
return res.status(500).json({
|
||
success: false,
|
||
message: '服务器内部错误'
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取当前登录用户信息
|
||
* 根据请求中的管理员ID查询并返回用户信息
|
||
* @param req - Express请求对象,包含已认证的管理员信息
|
||
* @param res - Express响应对象
|
||
*/
|
||
async getCurrentUser(req: any, res: Response) {
|
||
try {
|
||
// 获取管理员用户仓库
|
||
const adminUserRepository = AppDataSource.getRepository(AdminUser);
|
||
// 根据请求中的管理员ID查询用户信息
|
||
const adminUser = await adminUserRepository.findOne({
|
||
where: { id: req.admin.id }
|
||
});
|
||
|
||
// 用户不存在
|
||
if (!adminUser) {
|
||
return res.status(404).json({
|
||
success: false,
|
||
message: '用户不存在'
|
||
});
|
||
}
|
||
|
||
// 返回用户信息
|
||
return res.json({
|
||
success: true,
|
||
data: {
|
||
id: adminUser.id,
|
||
username: adminUser.username,
|
||
realName: adminUser.realName,
|
||
roleId: adminUser.roleId
|
||
}
|
||
});
|
||
} catch (error) {
|
||
console.error('获取用户信息失败:', error);
|
||
return res.status(500).json({
|
||
success: false,
|
||
message: '服务器内部错误'
|
||
});
|
||
}
|
||
}
|
||
}
|