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

登录后/index路由HTTP请求持续Pending问题求助

问题描述

登录验证通过后跳转至/index?user_name=xxx&password=xxx时,该路由请求始终处于Pending状态。已知登录函数entrar()可正常验证数据库中的用户名和密码,返回状态码200。


前端登录函数代码

async function entrar() {
        const user_name = document.getElementById('user_name').value.trim();
        const password = document.getElementById('password').value.trim();

    try {
        const response = await fetch('/user/search', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: `user_name=${encodeURIComponent(user_name)}&password=${encodeURIComponent(password)}`
        });

        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }

        const objJson = await response.json();

        if (objJson && objJson.user_name === user_name && objJson.password === password) {
            localStorage.setItem('objJson', JSON.stringify(objJson));
            window.location.href = `/index?user_name=${encodeURIComponent(user_name)}&password=${encodeURIComponent(password)}`;
        } else {
            window.location.href = '/login';
        }
    } catch (error) {
        console.error('Error fetching data:', error);
        window.location.href = '/login'; // Redirect to login page on error
    }
}

后端/index路由代码

app.get('/index', urlencodedParser, async function(req, res){
    let objJson = {};
    if(req.query.user_name) objJson.user_name = req.query.user_name; else objJson.user_name = false;
    if(req.query.password) objJson.password = req.query.password; else objJson.password = false;
    findUserOne(objJson, async function(result){
     if((result)&&(result.activate==true)){
         res.set('Content-Type', 'text/html');        
         const data = await fs.readFileSync('./index.html','utf8');
         await res.send(data);
     }else{
         res.set('Content-Type', 'text/html');
         const data = await fs.readFileSync('./login.html','utf8');
         await res.send(data);
     }
    });
});

登录表单代码

<div class="container">
        <h2 align="center">LOGIN</h2>
        <br>
        <center>
            <div align="center" style="width:30%;">
                <input type="text" id="user_name" class="form-control" placeholder="Nome de usuário"><br>
                <input type="password" id="password" class="form-control" placeholder="Senha"><br>
                <br>
                <button class="btn btn-lg btn-info" onclick="entrar()">Entrar</button>
            </div>
        </center>
    </div>

问题分析与解决

核心问题

后端/index路由中,findUserOne的回调函数被标记为async,但fs.readFileSync是同步IO操作,加await会导致异步上下文混乱;同时回调函数的异步逻辑可能未正确触发响应结束,导致请求一直处于Pending状态。

另外存在两个高风险安全问题:

  1. 跳转时将密码放在URL参数中,会暴露在地址栏、日志和浏览器历史中;
  2. 前端直接对比明文密码,数据库不应存储/返回明文密码,应使用哈希验证。

具体修复步骤

  1. 解决Pending问题
    去掉回调函数的async标记,移除fs.readFileSync前的await(同步方法无需异步等待):

    app.get('/index', urlencodedParser, function(req, res){
        let objJson = {
            user_name: req.query.user_name || false,
            password: req.query.password || false
        };
        findUserOne(objJson, function(result){
            if(result && result.activate){
                const data = fs.readFileSync('./index.html','utf8');
                res.set('Content-Type', 'text/html').send(data);
            }else{
                const data = fs.readFileSync('./login.html','utf8');
                res.set('Content-Type', 'text/html').send(data);
            }
        });
    });
    

    如果findUserOne支持Promise,建议改用async/await语法替代回调,代码更清晰:

    app.get('/index', urlencodedParser, async function(req, res){
        try {
            const result = await findUserOne({
                user_name: req.query.user_name || false,
                password: req.query.password || false
            });
            const htmlPath = result && result.activate ? './index.html' : './login.html';
            const data = fs.readFileSync(htmlPath,'utf8');
            res.set('Content-Type', 'text/html').send(data);
        } catch (err) {
            console.error(err);
            res.redirect('/login');
        }
    });
    
  2. 修复安全问题

    • 前端跳转时不再携带密码参数,仅存储必要用户信息:
      // 前端登录成功后修改逻辑
      if (objJson && objJson.user_name === user_name) {
          localStorage.setItem('userInfo', JSON.stringify({user_name: objJson.user_name}));
          window.location.href = '/index';
      }
      
    • 后端改用Session或JWT验证用户身份,不再依赖URL参数;数据库存储密码哈希(如bcrypt加密),登录时后端对比哈希值,不返回明文密码。

内容的提问来源于stack exchange,提问作者Mind full of blanks

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 09:50:12