未登录时触发网站404及onerror事件的Node.js实现疑问
解决方案
核心问题分析
- 路由优先级错误:
express.static会优先匹配静态文件,导致自定义的/homepage.html路由从未执行,登录校验完全失效。 - 未登录响应错误:未登录时返回纯文本404,浏览器未加载
homepage.html的脚本,自然无法触发onerror。 - 登录状态传递错误:用自定义请求头判断登录状态不现实,跳转页面时浏览器不会自动携带该头,应该用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>
效果说明
- 已登录状态:直接访问
/homepage.html,服务器返回200状态,页面正常加载,load事件触发。 - 未登录状态:直接访问
/homepage.html,服务器返回404状态,页面加载时早期脚本抛出错误,触发onerror,后续页面内容被替换为404提示,且load事件不会触发(因为脚本执行错误导致页面加载中断)。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

