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

已配置登录验证仍可直接访问admin.html等受保护页面的问题求助

解决直接输入URL绕过登录验证的权限问题

问题根源

你的代码里配置了app.use(express.static(__dirname + '/')),这会把项目根目录设为静态资源目录。当用户直接在地址栏输入/admin.html或/client.html时,Express的静态文件中间件会优先匹配并直接返回对应的HTML文件,完全跳过了你后面定义的带权限验证的路由逻辑。这就是直接输入URL能绕过验证的核心原因。

解决方案

1. 调整静态资源目录结构

不要把项目根目录暴露为静态资源目录,仅将需要公开的静态文件(如样式、脚本、图片等)放在单独的子目录(比如public)中:

// 先引入path模块(如果还没引入)
const path = require('path');

// 修改静态中间件配置,只暴露指定目录的资源
app.use(express.static("style"));
app.use(express.static(path.join(__dirname, 'public')));

将admin.html和client.html保留在项目根目录,不要放到public或style目录下,这样静态中间件无法直接访问它们。

2. 确保路由逻辑正常生效

调整静态中间件后,当用户访问/admin.html或/client.html时,请求会落到你定义的带权限验证的路由上,触发isAuthenticated和角色验证中间件,未登录用户会被重定向到登录页。

3. 增强Cookie安全性(可选但推荐)

为了防止Cookie被窃取或篡改,设置Cookie时添加安全属性:

// 登录时设置Cookie的代码修改如下
res.cookie('loggedIn', true, { 
  httpOnly: true, 
  sameSite: 'Strict', 
  secure: process.env.NODE_ENV === 'production' 
});
res.cookie('isAdmin', isAdministrateur, { 
  httpOnly: true, 
  sameSite: 'Strict', 
  secure: process.env.NODE_ENV === 'production' 
});
res.cookie('isClient', isClient, { 
  httpOnly: true, 
  sameSite: 'Strict', 
  secure: process.env.NODE_ENV === 'production' 
});
  • httpOnly:防止前端JS读取Cookie,降低XSS风险
  • sameSite: 'Strict':防止CSRF攻击
  • secure:生产环境下仅通过HTTPS传输Cookie

修改后的核心代码示例

const express = require('express');
const path = require('path');
const app = express();

// 静态资源配置(仅暴露指定目录)
app.use(express.static("style"));
app.use(express.static(path.join(__dirname, 'public')));

// Logout路由
app.get('/logout', (req, res) => {
    res.clearCookie('loggedIn');
    res.clearCookie('isAdmin');
    res.clearCookie('isClient');
    res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    res.redirect('/login.html');
});

// Login路由(保持原有逻辑)
app.post('/login', async (req, res) => {
    const { username, password } = req.body;

    if (!username || !password) {
        return res.status(400).json({ message: "Veuillez fournir un nom d'utilisateur et un mot de passe." });
    }

    const query = "SELECT * FROM users WHERE username = ? AND password = ?";
    try {
        const [rows, fields] = await pool.execute(query, [username, password]);

        if (rows.length === 0) {
            return res.status(401).json({ message: "Nom d'utilisateur ou mot de passe incorrect." });
        }

        const user = rows[0];
        const isAdministrateur = user.administrateur === 1;
        const isClient = user.client === 1;

        // 带安全属性的Cookie设置
        res.cookie('loggedIn', true, { httpOnly: true, sameSite: 'Strict', secure: process.env.NODE_ENV === 'production' });
        res.cookie('isAdmin', isAdministrateur, { httpOnly: true, sameSite: 'Strict', secure: process.env.NODE_ENV === 'production' });
        res.cookie('isClient', isClient, { httpOnly: true, sameSite: 'Strict', secure: process.env.NODE_ENV === 'production' });

        if (isAdministrateur) {
            return res.redirect('/admin.html');
        } else if (isClient) {
            return res.redirect('/client.html');
        } else {
            return res.status(401).json({ message: "Ce compte n'est pas autorisé à se connecter." });
        }
    } catch (error) {
        console.error(error);
        res.status(500).send("Une erreur est survenue lors de la connexion de l'utilisateur.");
    }
});

// 权限验证中间件(保持原有逻辑)
function isAuthenticated(req, res, next) {
    if (req.cookies.loggedIn) {
        next();
    } else {
        res.redirect('/login.html');
    }
}

function isAdmin(req, res, next) {
    if (req.cookies.isAdmin) {
        next();
    } else {
        res.redirect('/login.html');
    }
}

function isClient(req, res, next) {
    if (req.cookies.isClient) {
        next();
    } else {
        res.redirect('/login.html');
    }
}

// 带权限验证的页面路由(保持原有逻辑)
app.get('/client.html', isAuthenticated, isClient, (req, res) => {
    res.sendFile(path.join(__dirname, 'client.html'));
});

app.get('/admin.html', isAuthenticated, isAdmin, (req, res) => {
    res.sendFile(path.join(__dirname, 'admin.html'));
});

// ...其他服务器启动代码

内容的提问来源于stack exchange,提问作者Miguel Vidal bravo jandia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 02:52:58