Express登录后session对象未赋值,其他路由无法获取authenticated变量
登录Session验证问题修复
问题描述
跟着教程实现基础登录功能(无数据库,接受任意用户名密码),登录时在session里设置req.session.authenticated,但这个变量在其他路由和checkAuth中间件里始终是undefined,调用中间件时触发以下错误:
TypeError: 无法读取undefined的属性'authenticated' 在 checkAuth (/home/giovanni/Projects/session-practicas/server.js:22:20) 在 Layer.handle [as handle_request] (/home/giovanni/Projects/session-practicas/node_modules/express/lib/router/layer.js:95:5) 在 next (/home/giovanni/Projects/session-practicas/node_modules/express/lib/router/route.js:144:13) 在 Route.dispatch (/home/giovanni/Projects/session-practicas/node_modules/express/lib/router/route.js:114:3) 在 Layer.handle [as handle_request] (/home/giovanni/Projects/session-practicas/node_modules/express/lib/router/layer.js:95:5) 在 /home/giovanni/Projects/session-practicas/node_modules/express/lib/router/index.js:284:15 在 Function.process_params (/home/giovanni/Projects/session-practicas/node_modules/express/lib/router/index.js:346:12) 在 next (/home/giovanni/Projects/session-practicas/node_modules/express/lib/router/index.js:280:10) 在 session (/home/giovanni/Projects/session-practicas/node_modules/express-session/index.js:479:7) 在 Layer.handle [as handle_request] (/home/giovanni/Projects/session-practicas/node_modules/express/lib/router/layer.js:95:5)
原代码如下:
server.js
const express = require('express'); const app = express(); const session = require('express-session'); const store = new session.MemoryStore(); app.use(express.json()); app.use(express.urlencoded({extended: false})); app.use("/", express.static('public')); app.use(session({ secret: "123", resave: false, saveUninitialized: false, store, cookie : { maxAge: 300000000, secure: false, sameSite: 'none' } })); function checkAuth(res, req, next){ // 这里req.session.authenticated是undefined,触发错误 if(req.session.authenticated){ return next(); } else { res.json({msg: "no estás logeado"}); } } app.post("/login", (req, res) => { const {user, password} = req.body; res.send("<h1>hola</h1>"); req.session.authenticated = true; }); app.get("/profile", checkAuth, (req, res) => { // 这里req.session.authenticated是undefined,触发错误 res.send("bienvenido"); }) app.listen(8000, () => { console.log("Server OK!"); })
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <form action="/login" method="POST"> <label for="user">Usuario :</label> <input type="text" id="user" name="user"> <label for="pass">Clave :</label> <input type="password" id="pass" name="password"> <input type="submit" value="Enviar"> </form> </body> </html>
错误原因及修复方案
1. 中间件参数顺序错误
checkAuth中间件的参数顺序写反了,Express中间件的标准顺序是(req, res, next),你写成了(res, req, next),导致代码里的req实际是res对象,自然不存在session属性,直接触发报错。
2. Session设置时机错误
登录路由里先执行res.send()再设置req.session.authenticated,res.send()会结束响应流程,此时session可能无法被正确保存到存储中,应该先设置session再发送响应。
3. Cookie配置不兼容本地环境
sameSite: 'none'要求secure: true(仅HTTPS环境生效),但本地开发是HTTP环境,浏览器会拒绝保存这个cookie,导致session无法在请求间共享。本地开发应将sameSite设为'lax'或默认值。
修复后的完整代码
server.js
const express = require('express'); const app = express(); const session = require('express-session'); const store = new session.MemoryStore(); app.use(express.json()); app.use(express.urlencoded({extended: false})); app.use("/", express.static('public')); app.use(session({ secret: "123", resave: false, saveUninitialized: false, store, cookie : { maxAge: 300000000, secure: false, // 本地HTTP环境设为false,HTTPS环境改为true sameSite: 'lax' // 本地开发用lax,避免浏览器拒绝保存cookie } })); // 修正参数顺序为req, res, next function checkAuth(req, res, next){ // 增加兜底判断,避免session未初始化时报错 if(req.session?.authenticated){ return next(); } else { res.json({msg: "你未登录"}); } } app.post("/login", (req, res) => { const {user, password} = req.body; // 先设置session再发送响应 req.session.authenticated = true; res.send("<h1>你好</h1>"); }); app.get("/profile", checkAuth, (req, res) => { res.send("欢迎"); }) app.listen(8000, () => { console.log("Server OK!"); })
验证步骤
- 启动服务器后,访问
http://localhost:8000提交登录表单 - 访问
http://localhost:8000/profile,此时会返回"欢迎",说明session验证生效 - 若未登录直接访问
profile,会返回{"msg":"你未登录"}
内容的提问来源于stack exchange,提问作者Wilman Pellegrion
相关产品推荐
相关产品推荐

