【问题标题】:Sessions not persisting with express-session and connect-mongo会话不与 express-session 和 connect-mongo 保持一致
【发布时间】:2020-04-08 16:29:57
【问题描述】:

我的 express 服务器正在使用 express-session 和 connect-mongo,它为来自同一用户的每个请求生成一个新会话,而不是像预期的那样持久化一个会话。这是我第一次使用快速会话,但我认为我的代码没有问题。在测试时,我是唯一的用户,当我查看我的 MongoDB 时,会有一堆新会话。每次我向需要使用会话变量的路由发出请求时,它都会生成另一个新会话。

编辑:客户端没有存储会话 ID,因此每个请求都会导致一个新会话。正在发送正确的 set-cookie 标头,所以我不确定它为什么不起作用。我使用 Firefox 作为我的客户端。

编辑 2:尝试使用 Edge 和 Chrome,它们也没有设置会话 cookie。我是会话新手,所以我不知道为什么它不能正常工作。

// 3rd party modules
const util = require('util');
const express = require('express');
const bodyParser = require('body-parser');
const multer = require('multer');
const morgan = require('morgan');
const mongoose = require('mongoose');
const config = require('config');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);

// Custom classes
const AuthService = require('./services/authService');

// Models
const Account = require('./models/account');

// Load .env config file
const envConfigResult = require('dotenv').config();
if (envConfigResult.error) {
    throw envConfigResult.error;
}

// Instances
let auth;
let upload = multer();
const app = express();

// Parse request data and store in req.body
app.use(bodyParser.json()); // json
app.use(bodyParser.urlencoded({ extended: true })); // x-www-form-url-encoded
app.use(upload.array()); // multipart/form-data

// Setup logging
app.use(morgan('dev'));

// JWT error handling
app.use(function (err, req, res, next) {
    // TODO: Implement proper error code
    res.status(401).send(err);
    if (err.name === 'UnauthorizedError') {
        res.status(401).send('invalid token...');
    }
});

async function main() {
    try {
        const mongoDbUrl = process.env.DB_HOST;
        // Use new url parser and unified topology to fix deprecation warning
        const mongoConnection = mongoose.connect(mongoDbUrl, { useNewUrlParser: true, useUnifiedTopology: true }).then(async function() {
            console.log(`Successfully connected to MongoDB database at ${mongoDbUrl}!`);
        }).catch(function(error) {
            console.log(`Error whilst connecting to MongoDB database at ${mongoDbUrl}! ${error}`);
        });
        mongoose.set('useCreateIndex', true); // Fixes deprecation warning
    } catch (err) {
        console.log(`Error whilst doing database setup! ${err}`);
    }
    try {
        app.use(session({
            store: new MongoStore({ mongooseConnection: mongoose.connection, ttl: 86400 }),
            secret: process.env.SESSION_SECRET,
            resave: false,
            saveUninitialized: false,
            cookie: {
                path: "/",
                maxAge: 3600000, // 1 hour
                httpOnly: false,
                secure: false // TODO: Update this on production
            }
        }));
        console.log("Sessions successfully initialized!");
    } catch (err) {
        console.log(`Error setting up a mongo session store! ${err}`);
    }
    try {
        // TODO: Initialize email service
        auth = new AuthService.AuthService();
        // TODO: Attach email service to auth service
    } catch (err) {
        console.log(`Error whilst doing initial setup. ${err}`);
    }
}

main();

// Routes
const rootRoute = require('./routes/root');
const tokensRoute = require('./routes/tokens');
const captchaRoute = require('./routes/captcha');

// Route middlewares
app.use('/v1/', rootRoute.router);
app.use('/v1/tokens', tokensRoute.router);
app.use('/v1/captcha', captchaRoute.router);

try {
    rootRoute.setAuthService(auth);
    tokensRoute.setAuthService(auth);
} catch (err) {
    console.log(`Error attaching auth service to routes! ${err}`);
}

var server = app.listen(8088, function() {
    let host = server.address().address;
    let port = server.address().port;

    if (host == "::") {
        console.log("Server running at http://127.0.0.1:%d", port);
    } else {
        console.log("Server running at http://%s:%d", host, port);
    }
});

【问题讨论】:

  • 我认为这是因为您的异步功能。我认为您不会在运行导出应用程序之前等待它。在您的 app.use(session...) 之前放置一个控制台日志,在 main() 之后放置一个控制台日志。如果main()之后的consoleLog之前被触发过,说明你的异步函数有问题......

标签: node.js express session express-session connect-mongo


【解决方案1】:

正如doc (or npm page) 中解释的那样,您似乎忘记了一行:

app.use(session({
    secret: 'foo',
    store: new MongoStore(options)
}));

【讨论】:

  • 我的 main 函数中有该代码。会话确实有效,因此它被正确初始化,而问题是用户没有获得单个唯一的持久会话。相反,用户的每个请求都被分配了一个新会话。
【解决方案2】:

事实证明,现代浏览器会忽略 set-cookie 标头,除非您在请求中包含 credentials: 'include'。所以我将客户端切换到使用 fetch 而不是 XMLHttpRequest 并将credentials: 'include' 添加到其选项中。 (如果您没有正确设置 CORS,则会忽略凭据,因此我也必须这样做。)现在它可以正常工作了。

TLDR:在您的请求中包含 credentials: 'include' 并确保服务器已配置 CORS。

【讨论】:

    猜你喜欢
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 2021-12-10
    • 1970-01-01
    • 2018-06-30
    • 2018-03-30
    • 2016-12-13
    相关资源
    最近更新 更多