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

未登录时触发网站404及onerror事件的Node.js实现疑问

解决方案

核心问题分析

  1. 路由优先级错误:express.static会优先匹配静态文件,导致自定义的/homepage.html路由从未执行,登录校验完全失效。
  2. 未登录响应错误:未登录时返回纯文本404,浏览器未加载homepage.html的脚本,自然无法触发onerror。
  3. 登录状态传递错误:用自定义请求头判断登录状态不现实,跳转页面时浏览器不会自动携带该头,应该用cookie实现服务端、客户端共享登录状态。

修改后的代码

1. server.js

const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser'); // 需要安装:npm install cookie-parser
const app = express();
const port = 27182;

app.use(cookieParser());
app.use(express.urlencoded({ extended: true })); // 解析表单提交数据

// 优先处理首页路由,再托管静态文件
app.get('/homepage.html', (req, res) => {
  // 从cookie读取登录状态
  const isLoggedIn = req.cookies.loggedIn === 'true';
  if (!isLoggedIn) {
    // 返回404状态码,同时返回homepage.html内容
    res.status(404).sendFile(path.join(__dirname, 'public', 'homepage.html'));
    return;
  }
  // 已登录则正常返回首页
  res.sendFile(path.join(__dirname, 'public', 'homepage.html'));
});

// 处理登录请求
app.post('/login', (req, res) => {
  const { username, password } = req.body;
  if (username === 'admin' && password === 'admin') {
    // 设置HttpOnly cookie,有效期1小时
    res.cookie('loggedIn', 'true', { httpOnly: true, maxAge: 3600000 });
    res.redirect('/homepage.html');
    return;
  }
  res.redirect('/login.html');
});

// 处理登出请求
app.get('/logout', (req, res) => {
  res.clearCookie('loggedIn');
  res.redirect('/login.html');
});

// 托管静态文件(放在路由之后,确保路由优先匹配)
app.use(express.static(path.join(__dirname, 'public')));

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}/`);
});

2. login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login Page</title>
</head>
<body>
    <h1>Login</h1>
    <!-- 表单提交到/login接口 -->
    <form id="loginForm" action="/login" method="POST">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required>
        <br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required>
        <br>
        <button type="submit">Login</button>
    </form>
    <script>
        // 同步设置localStorage,用于客户端提前判断登录状态
        document.getElementById('loginForm').addEventListener('submit', function(event) {
            const username = document.getElementById('username').value;
            const password = document.getElementById('password').value;
            if (username === 'admin' && password === 'admin') {
                localStorage.setItem('loggedIn', 'true');
            }
        });
    </script>
</body>
</html>

3. homepage.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Homepage</title>
    <script>
        // 提前检测登录状态,在页面加载最早期执行
        const loggedIn = localStorage.getItem('loggedIn') === 'true';
        if (!loggedIn) {
            // 抛出错误触发window.onerror
            throw new Error('Unauthorized access');
        }

        // 监听onerror事件
        window.onerror = function(message, source, lineno, colno, error) {
            document.documentElement.innerHTML = '<h1>404 Not Found</h1>';
            return true; // 阻止默认错误提示
        };
    </script>
</head>
<body>
    <h1>Welcome to the Homepage</h1>
    <a href="/logout">Logout</a>
    <script>
        // 已登录时触发onload事件
        window.addEventListener('load', function() {
            console.log('Homepage loaded successfully');
        });
    </script>
</body>
</html>

效果说明

  1. 已登录状态:直接访问/homepage.html,服务器返回200状态,页面正常加载,load事件触发。
  2. 未登录状态:直接访问/homepage.html,服务器返回404状态,页面加载时早期脚本抛出错误,触发onerror,后续页面内容被替换为404提示,且load事件不会触发(因为脚本执行错误导致页面加载中断)。

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 03:44:57