// 登录处理模块 const formidable = require('formidable'); const crypto = require('crypto'); const { getDatabase } = require('./sql'); // 固定验证码 const FIXED_VERIFICATION_CODE = '9527'; // 密码加密(使用 SHA256) function hashPassword(password) { return crypto.createHash('sha256').update(password).digest('hex'); } // 设置 CORS 头的辅助函数 function setCORSHeaders(res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); } // 处理登录请求 async function handleLoginRequest(req, res) { // 设置 CORS 头 setCORSHeaders(res); if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; } if (req.method !== 'POST') { setCORSHeaders(res); res.writeHead(405, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: 'Method not allowed' })); return; } try { const form = formidable.formidable({ multiples: false }); let fields; try { [fields] = await form.parse(req); } catch (parseError) { console.error('[Login] 表单解析错误:', parseError); setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '请求格式错误' })); return; } // 提取表单字段 const loginType = Array.isArray(fields.loginType) ? fields.loginType[0] : (fields.loginType || 'account'); const account = Array.isArray(fields.account) ? fields.account[0] : (fields.account || ''); const password = Array.isArray(fields.password) ? fields.password[0] : (fields.password || ''); const phone = Array.isArray(fields.phone) ? fields.phone[0] : (fields.phone || ''); const code = Array.isArray(fields.code) ? fields.code[0] : (fields.code || ''); // 获取数据库实例 let db; try { db = await getDatabase(); } catch (dbError) { console.error('[Login] 数据库连接错误:', dbError); setCORSHeaders(res); res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '数据库连接失败' })); return; } console.log('[Login] 收到登录请求:', { loginType, account: account ? account.substring(0, 3) + '***' : '', hasPassword: !!password }); let user = null; if (loginType === 'account') { // 账号密码登录 if (!account || !password) { console.log('[Login] 缺少账号或密码'); setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '请输入账号和密码' })); return; } // 查找用户(可能是用户名或手机号) user = db.findUserByUsername(account); if (!user) { user = db.findUserByPhone(account); } if (!user) { console.log('[Login] 用户不存在:', account); setCORSHeaders(res); res.writeHead(401, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '账号不存在', errorType: 'USER_NOT_FOUND' })); return; } // 验证密码 const hashedPassword = hashPassword(password); console.log('[Login] 密码验证:', { storedHash: user.password ? user.password.substring(0, 10) + '...' : 'null', computedHash: hashedPassword.substring(0, 10) + '...', match: user.password === hashedPassword }); if (user.password !== hashedPassword) { console.log('[Login] 密码不匹配'); setCORSHeaders(res); res.writeHead(401, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '密码错误', errorType: 'WRONG_PASSWORD' })); return; } console.log('[Login] 登录成功:', user.username); } else if (loginType === 'phone') { // 手机验证码登录 if (!phone || !code) { setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '请输入手机号和验证码' })); return; } // 验证手机号格式 if (!/^1[3-9]\d{9}$/.test(phone)) { setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '请输入正确的手机号' })); return; } // 验证验证码(固定验证码 9527) if (code !== FIXED_VERIFICATION_CODE) { setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '验证码错误' })); return; } // 查找用户 user = db.findUserByPhone(phone); if (!user) { setCORSHeaders(res); res.writeHead(401, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '手机未注册', errorType: 'PHONE_NOT_REGISTERED' })); return; } } else { setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '无效的登录类型' })); return; } // 登录成功 res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: true, message: '登录成功', user: { id: user.id, username: user.username, phone: user.phone, avatar: user.avatar } })); } catch (error) { console.error('[Login] 登录处理错误:', error); console.error('[Login] 错误堆栈:', error.stack); // 如果响应头还没有发送,发送错误响应 if (!res.headersSent) { setCORSHeaders(res); res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '服务器错误: ' + (error.message || '未知错误') })); } else { console.error('[Login] 响应头已发送,无法发送错误响应'); } } } // 处理检查手机号请求 async function handleCheckPhoneRequest(req, res) { // 设置 CORS 头 setCORSHeaders(res); if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; } if (req.method !== 'POST') { setCORSHeaders(res); res.writeHead(405, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: 'Method not allowed' })); return; } try { const db = await getDatabase(); let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', async () => { try { const data = JSON.parse(body); const { phone, type } = data; // type: 'login' 或 'register' if (!phone) { setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '请输入手机号' })); return; } // 验证手机号格式 if (!/^1[3-9]\d{9}$/.test(phone)) { setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '请输入正确的手机号' })); return; } // 查找用户 const user = db.findUserByPhone(phone); const exists = !!user; // 根据类型判断 if (type === 'login') { // 登录场景:手机号必须存在 if (!exists) { setCORSHeaders(res); res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '手机未注册', exists: false })); return; } } else if (type === 'register') { // 注册场景:手机号必须不存在 if (exists) { setCORSHeaders(res); res.writeHead(409, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '手机号已被注册', exists: true })); return; } } // 检查通过 setCORSHeaders(res); res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: true, message: type === 'login' ? '手机号已注册' : '手机号可用', exists: exists })); } catch (parseError) { console.error('[CheckPhone] 解析请求数据失败:', parseError); setCORSHeaders(res); res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '请求格式错误' })); } }); } catch (error) { console.error('[CheckPhone] 检查手机号失败:', error); setCORSHeaders(res); res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ success: false, message: '服务器错误' })); } } module.exports = { handleLoginRequest, handleCheckPhoneRequest };