Files
webssh/backend/routes/auth.js
T
2026-02-12 11:09:43 +08:00

223 lines
5.7 KiB
JavaScript

const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const db = require('../config/database');
const router = express.Router();
// 用户注册
router.post('/register', async (req, res) => {
try {
const { email, phone, password } = req.body;
// 验证输入
if (!email || !password) {
return res.status(400).json({ error: '邮箱和密码是必填项' });
}
if (password.length < 6) {
return res.status(400).json({ error: '密码长度至少6位' });
}
// 检查用户是否已存在
const [existingUsers] = await db.pool.execute(
'SELECT id FROM users WHERE email = ?',
[email]
);
if (existingUsers.length > 0) {
return res.status(400).json({ error: '该邮箱已被注册' });
}
// 加密密码
const saltRounds = 12;
const passwordHash = await bcrypt.hash(password, saltRounds);
// 创建用户
const [result] = await db.pool.execute(
'INSERT INTO users (email, phone, password_hash) VALUES (?, ?, ?)',
[email, phone || null, passwordHash]
);
// 生成JWT令牌
const token = jwt.sign(
{ userId: result.insertId, email },
process.env.JWT_SECRET || 'webssh-secret-key',
{ expiresIn: '7d' }
);
res.status(201).json({
message: '注册成功',
token,
user: {
id: result.insertId,
email,
phone
}
});
} catch (error) {
console.error('注册错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 用户登录
router.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json({ error: '邮箱和密码是必填项' });
}
// 查找用户
const [users] = await db.pool.execute(
'SELECT * FROM users WHERE email = ?',
[email]
);
if (users.length === 0) {
return res.status(401).json({ error: '邮箱或密码错误' });
}
const user = users[0];
// 检查用户是否激活
if (user.is_active !== 1) {
return res.status(403).json({ error: '账户已被禁用,请联系管理员' });
}
// 验证密码
const isValidPassword = await bcrypt.compare(password, user.password_hash);
if (!isValidPassword) {
return res.status(401).json({ error: '邮箱或密码错误' });
}
// 更新最后登录时间
await db.pool.execute(
'UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = ?',
[user.id]
);
// 生成JWT令牌(包含管理员信息)
const token = jwt.sign(
{
userId: user.id,
email: user.email,
isAdmin: user.is_admin === 1
},
process.env.JWT_SECRET || 'webssh-secret-key',
{ expiresIn: '7d' }
);
res.json({
message: '登录成功',
token,
user: {
id: user.id,
email: user.email,
phone: user.phone,
is_admin: user.is_admin === 1
}
});
} catch (error) {
console.error('登录错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 验证令牌中间件
const authenticateToken = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: '访问令牌缺失' });
}
jwt.verify(token, process.env.JWT_SECRET || 'webssh-secret-key', (err, user) => {
if (err) {
return res.status(403).json({ error: '令牌无效' });
}
req.user = user;
next();
});
};
// 获取当前用户信息
router.get('/me', authenticateToken, async (req, res) => {
try {
const [users] = await db.pool.execute(
'SELECT id, email, phone, is_admin, is_active, last_login, created_at FROM users WHERE id = ?',
[req.user.userId]
);
if (users.length === 0) {
return res.status(404).json({ error: '用户不存在' });
}
const user = users[0];
res.json({
user: {
id: user.id,
email: user.email,
phone: user.phone,
is_admin: user.is_admin === 1,
is_active: user.is_active === 1,
last_login: user.last_login,
created_at: user.created_at
}
});
} catch (error) {
console.error('获取用户信息错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
// 修改密码
router.put('/password', authenticateToken, async (req, res) => {
try {
const { currentPassword, newPassword } = req.body;
if (!currentPassword || !newPassword) {
return res.status(400).json({ error: '当前密码和新密码是必填项' });
}
if (newPassword.length < 6) {
return res.status(400).json({ error: '新密码长度至少6位' });
}
// 获取用户当前密码
const [users] = await db.pool.execute(
'SELECT password_hash FROM users WHERE id = ?',
[req.user.userId]
);
if (users.length === 0) {
return res.status(404).json({ error: '用户不存在' });
}
// 验证当前密码
const isValidPassword = await bcrypt.compare(currentPassword, users[0].password_hash);
if (!isValidPassword) {
return res.status(401).json({ error: '当前密码错误' });
}
// 加密新密码
const saltRounds = 12;
const newPasswordHash = await bcrypt.hash(newPassword, saltRounds);
// 更新密码
await db.pool.execute(
'UPDATE users SET password_hash = ? WHERE id = ?',
[newPasswordHash, req.user.userId]
);
res.json({ message: '密码修改成功' });
} catch (error) {
console.error('修改密码错误:', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
module.exports = router;