基于Express+SQL Server的会话认证漏洞:已登录用户可访问登录页
解决方案:修复已登录用户可返回登录页的安全问题
问题根源在于登录成功后未在会话中标记用户身份,且路由未做登录状态校验。以下是具体修复步骤:
1. 完善登录会话标记
在登录接口验证通过后,将用户登录状态存入Session,让服务器能识别已登录用户:
修改router.js中的/login接口:
router.post('/login', async (req, res) => { const { username, password } = req.body; try { const pool = await poolPromise; const result = await pool.request() .input('Username', sql.NVarChar, username) .query('SELECT * FROM Users WHERE Username = @Username'); if (result.recordset.length > 0) { const user = result.recordset[0]; const passwordMatch = await bcrypt.compare(password, user.PasswordHash); if (passwordMatch) { // 关键:将用户登录状态存入Session req.session.isLoggedIn = true; req.session.user = { id: user.Id, username: user.Username }; // 按需存储必要字段 res.status(200).json({ message: 'Login successful' }); } else { res.status(401).json({ error: 'Invalid username or password' }); } } else { res.status(401).json({ error: 'Invalid username or password' }); } } catch (err) { console.error('Error during login:', err); res.status(500).json({ error: 'An internal error occurred. Please try again later.' }); } });
2. 编写登录状态校验中间件
在主app.js中添加两个中间件,分别控制不同路由的访问权限:
// 中间件:仅允许已登录用户访问(用于首页等受保护路由) const requireAuth = (req, res, next) => { if (req.session.isLoggedIn && req.session.user) { return next(); // 已登录,继续执行后续逻辑 } res.redirect('/'); // 未登录,重定向到登录页 }; // 中间件:仅允许未登录用户访问(用于登录页) const requireGuest = (req, res, next) => { if (!req.session.isLoggedIn || !req.session.user) { return next(); // 未登录,继续加载登录页 } res.redirect('/home'); // 已登录,直接重定向到首页 };
3. 为路由应用权限校验
修改app.js中的路由配置,给对应路由绑定中间件:
// 登录页:仅未登录用户可访问 app.get('/', requireGuest, (req, res) => { res.sendFile(path.join(__dirname, 'public', 'login.html')); }); // 首页:仅已登录用户可访问 app.get('/home', requireAuth, (req, res) => { res.sendFile(path.join(__dirname, 'public', 'home.html')); });
4. 优化Session配置(可选但推荐)
调整Session参数提升安全性,减少无效会话存储:
app.use(session({ secret: config.sessionSecret, saveUninitialized: false, // 仅会话有修改时才存储 resave: false, // 避免重复存储未修改的会话 cookie: { secure: process.env.NODE_ENV === 'production', // 生产环境强制HTTPS httpOnly: true, // 禁止前端JS访问Cookie,防范XSS maxAge: 24 * 60 * 60 * 1000 // 会话有效期1天,按需调整 } }));
5. 前端辅助校验(可选)
在登录页加载时补充会话检查,避免不必要的页面渲染:
在login.html的脚本中添加:
window.addEventListener('load', async () => { try { const response = await fetch('/api/check-auth', { credentials: 'include' }); if (response.ok) { window.location.href = '/home'; } } catch (err) { console.log('未登录,显示登录页'); } });
同时在router.js中新增校验接口:
router.get('/check-auth', (req, res) => { if (req.session.isLoggedIn && req.session.user) { res.status(200).json({ isLoggedIn: true }); } else { res.status(401).json({ isLoggedIn: false }); } });
经过以上修改,已登录用户无论直接访问登录页URL还是通过其他方式返回,都会被自动重定向到首页;未登录用户访问首页则会被引导至登录页,彻底解决安全漏洞。
内容的提问来源于stack exchange,提问作者Ganza Tombola Nelson
相关产品推荐
相关产品推荐

