| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- // 登录处理模块
- 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
- };
|