Express-会话与passport.js多个cookie [英] Express-session with passport.js multiple cookies

查看:601
本文介绍了Express-会话与passport.js多个cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用passport.js和express-session实现登录功能,效果很好。

I'm trying to implement the login functionality with passport.js and express-session, it works well,

var passport = require('passport'),
    session = require('express-session'),
    MongoDBStore = require('connect-mongodb-session')(session);

var sessionStore = new MongoDBStore({
    uri: config.db,
    collection: 'sessions'
});

var sessionOptions = {
    name: 'very-secure-cookie',
    secret: config.secret,
    resave: false,
    saveUninitialized: true,
    cookie: {
        secure: true,
        maxAge: null
    },
    store: sessionStore
};

app.use(session(sessionOptions));
app.use(passport.initialize());
app.use(passport.session());

这里, maxAge null ,这意味着客户端在关闭浏览器窗口时会注销。但是,我希望在客户的电子邮件地址中存储一个额外的Cookie,以便预填充< input type =textname =email>

Here, maxAge is null, meaning that the client gets logged out when they close the browser window. However, I want to store an additional cookie with the client's email address in order to pre-fill the <input type="text" name="email"> when they want to log back in if they come later.

我尝试过 app.use()另一个会话对象,只是为了存储电子邮件信息在另一个cookie,但由于某种原因cookie只设置一次(第一个)。

I've tried app.use()'ing another session object just to store the email information in another cookie, but for some reason the cookie is set only once (the first one).

app.use(session(returningSessionOptions));

在任何地方找不到任何合理的解决方案:(

Couldn't find any sensible solution anywhere :(

哦,我必须提及我想到使用 cookie-parser 中间件以及 express-session ,但文档声明可能会导致冲突

Oh, and I have to mention that I thought about using cookie-parser middleware alongside with express-session, but the docs state that it may result in conflicts.

推荐答案

由于您没有使用完整的代码,我假设您使用 res.cookie(name,value [,options]); res.setHeader('set-cookie',serializedCookie);

As you didn't include the complete code you used, I assume you set the cookie using res.cookie(name, value[, options]); or res.setHeader('set-cookie', serializedCookie);.

set-cookie标头似乎有一个问题,当添加多个cookie时,它们被附加到标题,用逗号分隔,在大多数当前浏览器中工作,标题只能解析,直到第一个逗号,因此只保存第一个cookie。在一些浏览器中,第一个等号和后面的分号之间的所有内容用作第一个cookie的值。

There seems to be an issue with the set-cookie header. When adding multiple cookies, they are appended to the header, separated by comma, which doesn't seem to work in most current browsers. The header is only interpreted until the first comma and therefore only the first cookie is saved. In some browsers everything between the first equals sign and the following semicolon is used as value for that first cookie.

我可以使用下面的代码重现旧版本Express(3.0.0)的问题。使用Express 4.13.4(和3.21.2)相同的代码工作正常。如果您使用的是旧版本的Express,我建议您更新到最新的版本,因为这应该解决这个问题。如果您已经在使用当前版本,请尝试如果该示例适用于您。如果没有,请提供您的快递应用程序发送的代码和标题。在某些情况下,使用更复杂的应用程序时,即使使用与示例代码一起使用的版本也存在问题(我试过Express 3.21.2)。

I could reproduce the issue with an old version of Express (3.0.0) using the code below. Using Express 4.13.4 (and also 3.21.2) the same code worked fine. If you are working with an old version of Express, I recommend that you update to the latest one as this should fix the problem. If you are already using a current version, please try if the example works for you. If not, please provide the code and the headers sent by your express-app. In some cases with a more complex application the problem exists even when using versions that work with the example code (I tried Express 3.21.2).

如果有任何原因对于您不能更新到最新版本或更新不能解决您的问题,有一个替代解决方案的问题:

If there is any reason for you not to update to the latest version or the update doesn't fix the issue for you, there is an alternative solution for the problem:

为了消除应用程序中其他代码可能产生的副作用,以下是我用来重现您的问题的最小示例:

To eliminate possible side-effects by other code in the application, here is the minimal example that I used to reproduce your issue:

    var express = require('express');
    var session = require('express-session');
    var passport = require('passport');
    var app = express();

    app.use(session({
        secret: 'keyboard cat',
        resave: false,
        saveUninitialized: true
    }));

    app.use(passport.initialize());
    app.use(passport.session());

    app.get('/', function (req, res) {
        res.cookie('cookie', 'value');
      res.send('Hello World!');
    });

    app.listen(3000, function () {
      console.log('Example app listening on port 3000!');
    });

通过浏览器访问express-app(运行Express 3.0.x)时,发送:

When accessing the express-app (running Express 3.0.x) via the browser, the following response headers are sent:

    set-cookie: cookie=value; Path=/
    set-cookie: cookie=value; Path=/,connect.sid=s%3ARPkxiLfy0dbeBs5eILYBLK6Yh-sOjABS.ykNXCmaOsxtIAXV%2Ba9GCW6YnBi0cBhvZIGvwlj%2F%2Fsy0; Path=/; HttpOnly

使用Express> = 3.21.2一切都适用于此示例:

Using Express >=3.21.2 everything works fine for this example:

    set-cookie: cookie=value; Path=/
    set-cookie: connect.sid=s%3AR6TVTnUe3eyIvlpT0Hl5ikwcH_XMHXId.ouysyG5tGGekaVDxZMXJP4A8SJfsckLE4GZ3%2B1Eyd1o; Path=/; HttpOnly



替代修复



借用代码的setcookie从express-session设置您的cookie可以为您做的伎俩,因为它写一个包含所有的cookie到头,同时保留已经添加到响应的数组。要这样做,安装cookie模块,添加 var cookie = require('cookie'); 并替换 res.cookie value'); 在上面的代码中有以下行:

Alternative fix

Borrowing the code of function setcookie from express-session for setting your cookies could do the trick for you, as it writes an array containing all the cookies to the header while preserving the ones already added to the response. To do this, install the cookie module, add var cookie = require('cookie'); and replace res.cookie('cookie', 'value'); in the above code with the following lines:

    var data = cookie.serialize('cookie', 'value');
    var prev = res.getHeader('set-cookie') || [];
    var header = Array.isArray(prev) ? prev.concat(data)
      : Array.isArray(data) ? [prev].concat(data)
      : [prev, data];

    res.setHeader('set-cookie', header);

现在,以下标题被发送到浏览器,并保存所有Cookie MacOS):

Now the following headers are sent to the browser and all cookies are saved (tested using Google Chrome 49 on MacOS):

    set-cookie:cookie=value
    set-cookie:cookie=value
    set-cookie:connect.sid=s%3Aa1ZPDmERtKwUaPjY__SrPtIrpYC7swQl.0KOs83RSmUTG%2FgPoyOLo4u5UFTjC89yS0Ch0ZVXWVo8; Path=/; HttpOnly

不幸的是,当使用Express 3.0.0时,头文件与第一个cookie重复,根据RFC6265第4.1.1节:

Unfortunately the header is duplicated for the first cookie when using Express 3.0.0, which shouldn't be done according to RFC6265 Section 4.1.1:


服务器不应在
中包含多个Set-Cookie头字段相同的响应具有相同的cookie名称。 (请参阅第5.2节中的
用户代理如何处理此情况。)

Servers SHOULD NOT include more than one Set-Cookie header field in the same response with the same cookie-name. (See Section 5.2 for how user agents handle this case.)



有用的资源



以下文章也可能有帮助:

Helpful resources

The following articles may also be helpful:

  • Someone facing a similar problem, but with ASP.NET/Web API instead of node.js/express. However, in my opinion this page provides helpful information on the topic: Set-Cookie Header With Multiple Cookies
  • Another possible solution for setting multiple cookies with node.js/express that might help: http://www.connecto.io/blog/nodejs-express-how-to-set-multiple-cookies-in-the-same-response-object/

这篇关于Express-会话与passport.js多个cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆