由于您没有包含您使用的完整代码,我假设您使用res.cookie(name, value[, options]);
or设置 cookie res.setHeader('set-cookie', serializedCookie);
。
set-cookie 标头似乎存在问题。添加多个 cookie 时,它们会附加到标题中,以逗号分隔,这在大多数当前浏览器中似乎不起作用。标头仅在第一个逗号之前被解释,因此仅保存第一个 cookie。在某些浏览器中,第一个等号和后面的分号之间的所有内容都用作第一个 cookie 的值。
可能的解决方案
我可以使用下面的代码重现旧版本的 Express (3.0.0) 的问题。使用 Express 4.13.4(以及 3.21.2)同样的代码运行良好。如果您使用的是旧版本的 Express,我建议您更新到最新版本,因为这应该可以解决问题。如果您已经在使用当前版本,请尝试该示例是否适合您。如果不是,请提供您的 express-app 发送的代码和标头。在某些应用程序更复杂的情况下,即使使用适用于示例代码的版本(我尝试过 Express 3.21.2),问题也存在。
如果您有任何理由不更新到最新版本或更新无法为您解决问题,则可以使用替代解决方案:
重现问题的代码
为了消除应用程序中其他代码可能产生的副作用,这是我用来重现您的问题的最小示例:
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)时,会发送以下响应头:
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 在这个例子中一切正常:
set-cookie: cookie=value; Path=/
set-cookie: connect.sid=s%3AR6TVTnUe3eyIvlpT0Hl5ikwcH_XMHXId.ouysyG5tGGekaVDxZMXJP4A8SJfsckLE4GZ3%2B1Eyd1o; Path=/; HttpOnly
替代修复
从 express-session 借用 setcookie 函数的代码来设置 cookie 可以为您解决问题,因为它会将包含所有 cookie 的数组写入标题,同时保留已添加到响应中的那些。为此,请安装 cookie 模块,在上面的代码中添加var cookie = require('cookie');
并替换res.cookie('cookie', 'value');
为以下行:
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 上使用 Google Chrome 49 测试):
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 节不应该这样做:
服务器不应在具有相同 cookie 名称的同一响应中包含多个 Set-Cookie 标头字段。(有关用户代理如何处理这种情况,请参阅第 5.2 节。)
有用的资源
以下文章也可能有所帮助: