JWT+Session认证部署后仅客户端登录失败,请求排查内部错误
本地正常但虚拟主机部署后客户端登录失败问题
问题现象
本地环境中,基于JWT+Session实现的管理员/客户端认证功能运行正常,但部署到虚拟主机后出现内部服务器错误:仅管理员登录可正常跳转至admin.html,客户端登录无法跳转至client.html。
服务器报错信息
Checking whether to disconnect long-running connections for process 70002, application VBJ (production) at Function process_params App 70002 output: at /home/c2100699c/VBJ/app.js:229:5 App 70002 output: at isValidCredentials (/home/c2100699c/VBJ/app.js:244:14)
相关代码
app.js 核心代码
// JWT认证中间件 function verifyToken(req, res, next) { const token = req.cookies.token || ''; jwt.verify(token, 'secret', function (err, decoded) { if (err) { return res.redirect('/login.html'); } else { req.decoded = decoded; next(); } }); } // 登录接口 app.post('/auth', function (req, res) { const username = req.body.username; const password = req.body.password; const email = req.body.email; console.log('Request data:', username, password, email); // 管理员硬编码认证 if ((username === '***********' && email === '*****************') && password === '*********') { const token = jwt.sign({ username, email, role: 'admin' }, 'secret', { expiresIn: '1h' }); res.cookie('token', token, { httpOnly: true }); return res.redirect('/admin.html'); } else { // 普通用户数据库认证 isValidCredentials(username, password, email, function (valid, isAdmin) { if (valid) { const role = isAdmin ? 'admin' : 'client'; const token = jwt.sign({ username, email, role }, 'secret', { expiresIn: '1h' }); res.cookie('token', token, { httpOnly: true }); return res.redirect('/client.html'); } else { return res.redirect('/login.html'); } }); } }); // 验证用户凭证 function isValidCredentials(username, password, email, callback) { const query = 'SELECT * FROM users WHERE username = ? AND password = ? AND email = ? AND administrateur = 0'; connection.query(query, [username, password, email], function (error, results, fields) { if (error) throw error; if (results.length > 0) { const isAdmin = results[0].administrateur === 1; callback(true, isAdmin); } else { callback(false, false); } }); } // 管理员页面路由 app.get('/admin', verifyToken, function (req, res) { if (req.session.loggedin) { res.sendFile(__dirname + '/admin.html'); } else { res.send('请登录后访问此页面'); } res.end(); }); // 客户端页面路由 app.get('/client', verifyToken, function (req, res) { if (req.session.loggedin) { res.sendFile(__dirname + '/client.html'); } else { res.send('请登录后访问此页面'); } res.end(); });
login.js 前端代码
const loginForm = document.getElementById('login'); submit.addEventListener('click', function (event) { event.preventDefault(); login(); }); function login() { const username = document.getElementById('username').value; const password = document.getElementById('password').value; const email = document.getElementById('emailRegister').value; fetch('/auth', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password, email }) }) .then(res => { console.log('Response status:', res.status); console.log('Response headers:', res.headers); return res.json(); }) .then(data => { console.log('Response data:', data); if (data.userType === 'administrateur') { window.location.href = '/admin.html'; } else if (data.userType === 'client') { window.location.href = '/client.html'; } else { document.querySelector("#message2").innerText = "账号、邮箱或密码错误"; } }) .catch(error => { console.log('Error:', error); }); }
解决建议
- 修复SQL查询逻辑矛盾:
isValidCredentials函数中SQL查询添加了administrateur = 0条件,但后续又判断results[0].administrateur === 1,逻辑完全冲突。去掉查询中的AND administrateur = 0条件,确保查询结果能正确匹配用户的管理员状态。 - 处理数据库连接异常:虚拟主机的数据库配置(地址、端口、权限)可能与本地不同,检查
connection对象的生产环境配置是否正确;同时在isValidCredentials中添加错误捕获,避免直接抛出异常导致服务器崩溃,改为通过回调传递错误状态。 - 统一认证机制:当前同时混用JWT和Session,但登录接口仅设置了JWT Cookie,未初始化Session的
loggedin状态,导致客户端登录后访问/client路由时被判定为未登录。要么用JWT的req.decoded.role判断权限,去掉Session相关逻辑;要么在登录成功时同步设置req.session.loggedin = true。 - 适配前端跳转逻辑:后端登录接口返回的是重定向,但前端
fetch会自动跟随重定向并尝试解析HTML为JSON,触发错误。可修改后端返回JSON数据由前端负责跳转,或在前端判断响应的重定向状态直接跳转。
内容的提问来源于stack exchange,提问作者Miguel Vidal bravo jandia
相关产品推荐
相关产品推荐

