NodeJS+ExpressJS+SQLite3用户登出功能问题求助
问题解决方案
一、前端按钮状态切换实现
当前仅用CSS隐藏登出按钮,需通过JavaScript根据登录状态动态切换按钮显示逻辑:
- 页面加载时自动检查本地Token,初始化按钮显示状态
- 登录成功后立即切换按钮状态
- 登出时清除Token并恢复初始状态
修改signInScript.js如下:
document.addEventListener('DOMContentLoaded', function() { const emailInput = document.getElementById('signInEmailAddress'); const passwordInput = document.getElementById('signInPassword'); const submitButton = document.getElementById('submitButton'); const togglePasswordIcon = document.getElementById('togglePassword'); // 替换为你实际的登录/登出按钮ID const loginButton = document.getElementById('loginButton'); const logoutButton = document.getElementById('logoutButton'); // 初始化按钮显示状态 function setButtonVisibility() { const token = localStorage.getItem('token'); if (token) { loginButton.style.display = 'none'; logoutButton.style.display = 'block'; } else { loginButton.style.display = 'block'; logoutButton.style.display = 'none'; } } // 页面加载时执行初始化 setButtonVisibility(); // 绑定登出按钮事件 logoutButton.addEventListener('click', function() { localStorage.removeItem('token'); setButtonVisibility(); // 可选:跳转到首页或登录页面 window.location.href = '/'; }); // 原表单验证逻辑 function checkFormValidity() { const isValid = emailInput.value.trim() !== '' && passwordInput.value.trim() !== ''; submitButton.disabled = !isValid; } // 原密码显示切换逻辑 function togglePasswordVisibility() { const type = passwordInput.type === 'password' ? 'text' : 'password'; passwordInput.type = type; togglePasswordIcon.classList.toggle('fa-eye-slash'); } // 原输入事件监听 emailInput.addEventListener('input', checkFormValidity); passwordInput.addEventListener('input', checkFormValidity); togglePasswordIcon.addEventListener('click', togglePasswordVisibility); // 原表单提交逻辑 document.getElementById("signInForm").addEventListener("submit", function(event) { event.preventDefault(); const email = document.getElementById("signInEmailAddress").value; const password = document.getElementById("signInPassword").value; const data = { email: email, password: password }; fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) .then(response => { if (response.ok) { return response.json(); } else { console.error('Login failed'); alert("Login Failed!"); throw new Error('Login failed'); } }) .then(data => { console.log('User data:', data.user); alert("Login Successful!"); localStorage.setItem('token', data.token); // 登录成功后切换按钮状态 setButtonVisibility(); }) .catch(error => { console.error('Error:', error); }); }); });
二、服务器端登出功能修正
当前/logout接口依赖express-session,但你使用的是JWT无状态认证,req.logout()和req.session.destroy()完全无效,且你未正确配置session中间件,会导致运行报错。
JWT的登出核心逻辑是前端清除本地存储的Token,服务器端无需额外操作(若需强制Token失效,可维护Token黑名单,简单场景下可省略)。修改server.js中的登出接口:
// 移除未使用的session和cookie-parser依赖(你原本也没配置) // const cookieParser = require('cookie-parser'); // const session = require('express-session'); // 修改登出接口 app.get('/logout', (req, res) => { // JWT无状态,仅返回成功响应即可 res.status(200).json({ message: 'Logout successful' }); });
三、Token与用户关联验证
1. 前端验证Token内容
登录成功后可解析Token,确认用户信息是否正确:
// 在登录成功的then回调中添加 const decodedToken = jwt.decode(data.token); console.log('解析后的Token:', decodedToken); // 应包含userId和email字段
注:前端需引入jsonwebtoken包,或使用在线JWT解析工具验证。
2. 服务器端添加Token验证中间件
创建中间件验证请求中的Token,确保请求来自已登录用户:
// 在server.js中添加JWT验证中间件 function authenticateToken(req, res, next) { // 从请求头获取Token(前端需携带Authorization: Bearer <token>) const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; if (!token) { return res.status(401).json({ error: '需要登录凭证' }); } jwt.verify(token, 'your-secret-key', (err, user) => { if (err) { return res.status(403).json({ error: 'Token无效或已过期' }); } req.user = user; // 将用户信息挂载到req对象,后续接口可直接使用 next(); }); } // 示例:用中间件保护需要登录的接口 app.get('/user/profile', authenticateToken, (req, res) => { res.json({ message: '用户个人信息', user: req.user }); });
3. 前端请求时携带Token
在需要登录权限的请求中,将Token放在请求头:
fetch('/user/profile', { method: 'GET', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }) .then(response => response.json()) .then(data => console.log(data));
额外优化建议
- 删除
server.js中的GET方式/login接口,该方式会将密码暴露在URL中,存在安全风险 - 生产环境中禁止明文存储密码,需使用
bcrypt等工具对密码进行哈希处理
内容的提问来源于stack exchange,提问作者Aadil Hafesji
相关产品推荐
相关产品推荐

