You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 10:53:11