debug: 添加详细的登录调试日志
- 在后端login控制器中添加详细的执行步骤日志 - 添加错误捕获和处理,防止未捕获的异常 - 在前端LoginForm中添加详细的错误日志输出 - 在rate limiter中添加详细的限制日志 - 在请求日志中添加POST请求体信息 - 帮助定位401错误的具体原因 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -103,13 +103,18 @@ export const authController = {
|
|||||||
|
|
||||||
// 用户登录
|
// 用户登录
|
||||||
async login(req: Request, res: Response) {
|
async login(req: Request, res: Response) {
|
||||||
const { username, password } = req.body;
|
try {
|
||||||
|
const { username, password } = req.body;
|
||||||
|
|
||||||
|
console.log('登录请求:', { username, timestamp: new Date().toISOString() });
|
||||||
|
|
||||||
// Find user
|
// Find user
|
||||||
const user = await prisma.user.findUnique({
|
const user = await prisma.user.findUnique({
|
||||||
where: { username }
|
where: { username }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('查找用户结果:', { found: !!user, isActive: user?.isActive, userId: user?.id });
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
// 记录登录失败审计日志
|
// 记录登录失败审计日志
|
||||||
await prisma.auditLog.create({
|
await prisma.auditLog.create({
|
||||||
@@ -144,7 +149,10 @@ export const authController = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify password
|
// Verify password
|
||||||
|
console.log('开始验证密码...');
|
||||||
const isValidPassword = await bcrypt.compare(password, user.password);
|
const isValidPassword = await bcrypt.compare(password, user.password);
|
||||||
|
console.log('密码验证结果:', { isValid: isValidPassword });
|
||||||
|
|
||||||
if (!isValidPassword) {
|
if (!isValidPassword) {
|
||||||
// 增加登录失败次数
|
// 增加登录失败次数
|
||||||
const loginAttempts = (user.loginAttempts || 0) + 1;
|
const loginAttempts = (user.loginAttempts || 0) + 1;
|
||||||
@@ -199,17 +207,22 @@ export const authController = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Generate token
|
// Generate token
|
||||||
|
console.log('生成token...');
|
||||||
const token = generateToken(user.id);
|
const token = generateToken(user.id);
|
||||||
|
console.log('Token生成成功:', token.substring(0, 20) + '...');
|
||||||
|
|
||||||
// Delete existing sessions for this user (optional - for single session per user)
|
// Delete existing sessions for this user (optional - for single session per user)
|
||||||
|
console.log('删除用户现有sessions...');
|
||||||
await prisma.session.deleteMany({
|
await prisma.session.deleteMany({
|
||||||
where: { userId: user.id }
|
where: { userId: user.id }
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create session
|
// Create session
|
||||||
|
console.log('创建新session...');
|
||||||
await createSession(user.id, token, req);
|
await createSession(user.id, token, req);
|
||||||
|
|
||||||
// Update last login
|
// Update last login
|
||||||
|
console.log('更新最后登录时间...');
|
||||||
await prisma.user.update({
|
await prisma.user.update({
|
||||||
where: { id: user.id },
|
where: { id: user.id },
|
||||||
data: { lastLoginAt: new Date() }
|
data: { lastLoginAt: new Date() }
|
||||||
@@ -227,6 +240,7 @@ export const authController = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('登录成功,返回响应...');
|
||||||
return res.json({
|
return res.json({
|
||||||
message: '登录成功',
|
message: '登录成功',
|
||||||
token,
|
token,
|
||||||
@@ -236,6 +250,10 @@ export const authController = {
|
|||||||
isAdmin: user.isAdmin,
|
isAdmin: user.isAdmin,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('登录过程中发生错误:', error);
|
||||||
|
return res.status(500).json({ error: '服务器内部错误' });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 用户登出
|
// 用户登出
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ const limiter = rateLimit({
|
|||||||
max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '100'), // limit each IP to 100 requests per windowMs
|
max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || '100'), // limit each IP to 100 requests per windowMs
|
||||||
message: {
|
message: {
|
||||||
error: 'Too many requests from this IP, please try again later.'
|
error: 'Too many requests from this IP, please try again later.'
|
||||||
|
},
|
||||||
|
// 添加详细日志
|
||||||
|
handler: (req, res) => {
|
||||||
|
console.log('Rate limit exceeded for IP:', req.ip, 'Path:', req.path);
|
||||||
|
res.status(429).json({
|
||||||
|
error: 'Too many requests from this IP, please try again later.'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
app.use('/api/', limiter);
|
app.use('/api/', limiter);
|
||||||
@@ -47,6 +54,12 @@ app.use(express.urlencoded({ extended: true }));
|
|||||||
|
|
||||||
// Request logging
|
// Request logging
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
|
console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`, {
|
||||||
|
ip: (req.headers['x-forwarded-for'] as string) || req.socket.remoteAddress,
|
||||||
|
userAgent: req.get('User-Agent'),
|
||||||
|
body: req.method === 'POST' ? req.body : undefined
|
||||||
|
});
|
||||||
|
|
||||||
logger.info(`${req.method} ${req.path}`, {
|
logger.info(`${req.method} ${req.path}`, {
|
||||||
ip: (req.headers['x-forwarded-for'] as string) || req.socket.remoteAddress,
|
ip: (req.headers['x-forwarded-for'] as string) || req.socket.remoteAddress,
|
||||||
userAgent: req.get('User-Agent')
|
userAgent: req.get('User-Agent')
|
||||||
|
|||||||
@@ -116,7 +116,14 @@ const handleLogin = async () => {
|
|||||||
|
|
||||||
router.push('/dashboard')
|
router.push('/dashboard')
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.log(error)
|
console.error('登录失败,详细错误信息:', {
|
||||||
|
status: error.response?.status,
|
||||||
|
statusText: error.response?.statusText,
|
||||||
|
data: error.response?.data,
|
||||||
|
url: error.config?.url,
|
||||||
|
method: error.config?.method,
|
||||||
|
headers: error.config?.headers
|
||||||
|
})
|
||||||
// 根据不同的错误类型显示不同的错误信息
|
// 根据不同的错误类型显示不同的错误信息
|
||||||
if (error.response?.status === 401) {
|
if (error.response?.status === 401) {
|
||||||
const errorMessage = error.response?.data?.error || '用户名或密码错误'
|
const errorMessage = error.response?.data?.error || '用户名或密码错误'
|
||||||
|
|||||||
Reference in New Issue
Block a user