【问题标题】:A session that is created in a route is not available in other routes在一个路由中创建的会话在其他路由中不可用
【发布时间】:2020-02-03 16:43:41
【问题描述】:

我正在尝试在我的 node.js 应用程序中设置会话。为了做到这一点,我使用模块“express”、“express-session”和“express-mysql-session”将它们存储在我服务器上的数据库中。只要我只访问创建会话的路由中的 req.session 参数,我的代码就可以正常工作。在其他路由(甚至启动文件)中,创建的参数会引发未定义的错误。

我已经尝试在启动文件中创建 app.use(session(...))。如果我这样做,一切正常,并且在某些路线中创建的参数也可以在其他路线中使用。但是因为我想保持启动文件尽可能小,所以这些代码行应该在一个路由中处理。

这是我的代码: login.js(路由)

var express = require('express');
var router = express.Router();
var session = require('express-session');
var MySQLStore = require('express-mysql-session');

var dbOptions = {
    host: "ip",
    user: "user",
    password: "pw",
    database: "some db"
};

var sessionStore = MySQLStore(dbOptions);

router.use(session({
    key: 'some key',
    secret: 'some secret',
    store: sessionStore,
    resave: false,
    saveUninitialized: false
}));

router.post('/login', (req, res) =>{
    req.session.username = req.body.username;
    res.end("done");
});

router.get('/sessionTest', (req, res) => {
    if(req.session.username) {
        res.write(`<h1>Hello ${req.session.username} </h1><br>`);
        res.end('<a href='+'/timetracking/logout'+'>Logout</a>');
    }
    else {
        res.write('<h1>Please login first.</h1>');
        res.end('<a href='+'/timetracking/login'+'>Login</a>');
    }
});

router.get('/logout',(req,res) => {
    req.session.destroy((err) => {
        if(err) {
            return console.log(err);
        }
        res.redirect('/timetracking/login');
    });

});

module.exports = router;

timetracking.js(启动文件)

var http = require('http');
const express = require('express');
const app = express();
var gets = require('./lib/gets');
var login = require('./lib/login');
const session = require('express-session');


//Make '/timetracking/' to the standard handler for get requests
app.use('/timetracking', [gets, login]);

app.get('/test', (req, res) =>{
    res.send(req.session.username);
});

app.listen(80);

当我加载 localhost/test 时,我仍然可以在 Web 开发人员工具中看到 cookie。但是“req.session.username”是未定义的。

感谢您的帮助!

【问题讨论】:

  • req.session 仅在会话中间件执行之后发生的路由中可用(取决于顺序)。而且,如果会话中间件仅在一个路由器上,那么 req.session 将仅在与该路由器匹配的路由中可用,并且仅在该路由器在给定请求上运行之后才可用。因此,如果您希望 req.session 在您的所有路由中有效,则需要尽早定义中间件,并且中间件应在所有可能的路由(您想要使用它)上运行,而不仅仅是在某些仅在一些路径上运行。
  • 记住,是你的会话中间件在任何给定的传入请求上设置req.session。在您想要访问 req.session 之前,它必须在给定的请求上运行。
  • @jfriend00 好的,谢谢。这就是我所期望的情况。所以现在我将在我的应用程序的启动文件中定义我的会话。我只是希望有更好的解决方案,让我的启动文件尽可能简单。

标签: javascript node.js express express-session


【解决方案1】:

req.session 仅在会话中间件执行之后发生的路由中可用(取决于顺序)。而且,如果会话中间件仅在一个路由器上,那么 req.session 将仅在与该路由器匹配的路由中可用,并且仅在该路由器在给定请求上运行之后才可用。

因此,如果您希望 req.session 在您的所有路由中都有效,则需要尽早定义中间件,并以中间件在所有可能的路由(您想要使用它的路由)上运行的方式进行定义,而不仅仅是在某些仅在某些路径上运行的路由器。

请记住,是您的会话中间件在任何给定的传入请求上设置req.session。在您想要访问 req.session 之前,它必须在给定的请求上运行。

您不必将会话中间件直接放入启动文件中。您仍然可以将它放在自己的模块中,您只需从启动文件中加载该模块并将app 对象传递给它,以便它可以在您的任何路由之前初始化全局中间件。

这是一个示例启动文件:

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

// initialize global middleware
require('./myMiddleware')(app);

// set up other routers and routes here
// and start the server

还有一个 myMiddlware.js 文件:

// load and initialize session stuff
const session = ....;

module.exports = function(app) {
    // install session middleware
    app.use(session(...))
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-09
    • 2020-10-11
    • 2018-06-30
    • 2016-07-07
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多