不使用安全cookie true设置时,我的应用程序用户登录工作正常。当我启用安全 cookie 时,登录似乎正常,但似乎 cookie 未保存且用户未登录。
换句话说,这有效:
app = express();
app.use(session({
secret: 'secret code',
store: sessionStore,
resave: false,
saveUninitialized: false,
cookie: {
secure: false,
maxAge: 5184000000 // 60 days
}
}));
这不起作用(用户无法登录(:
app = express();
app.set('trust proxy');
app.use(session({
secret: config.cookieSecret,
store: sessionStore,
resave: false,
saveUninitialized: false,
proxy: true,
secureProxy: true,
cookie: {
secure: true,
httpOnly: true,
maxAge: 5184000000 // 60 days
}
}));
在云焰和nginx的背后。这是我的nginx配置:
location ~ / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:3000;
}
从我读到的内容来看,我认为它应该有效。我错过了什么?
编辑:我正在运行带有有效SSL证书的https。
对我有用的设置组合:
- 在nginx服务器配置中,添加
proxy_set_header X-Forwarded-Proto $scheme;
-
在快速会话配置中:
server.use( session({ proxy: true, // NODE_ENV === 'production' cookie: { secure: true, // NODE_ENV === 'production' }, // everything else }) );
如果使用 Heroku 的解决方案:
在 Heroku 中,所有请求都以纯 http 的形式进入应用程序,但它们具有标头 X-Forwarded-Proto,以了解原始请求是 http 还是 https。这会导致 express 看到非 SSL 流量,因此它在 Heroku 上运行时拒绝设置安全 cookie。Express 只会通过 https 发送安全的 cookie。您必须通过启用"信任代理"设置来告诉 express 信任 X-Forwarded-Proto 标头中的信息,即原始请求是通过 https 进行的。在定义 cookie 属性之前,我把
app.set('trust proxy', 1);
1
意味着信任第一个代理。 1
足以让我设置cookie: secure
Apache 反向代理解决方案
对于那些正在寻找潜在解决方案并使用Apache反向代理的人:请确保在相应域的VirtualHost指令中的ProxyPass指令上方添加以下指令:
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RequestHeader set X-Forwarded-SSL expr=%{HTTPS}
ProxyPass / http://localhost:8001/
ProxyPassReverse / http://localhost:8001/
此更改允许我的 cookie 保留。
此外,正如其他人指出的那样,不要忘记将以下代码添加到您的生产(或使用代理的其他托管环境(快速配置中:
if (app.get('env') === 'production') {
app.set('trust proxy', 1); // trust first proxy, crucial
}
最后,请确保您的 Cookie/会话设置正确。查看斯托扬·博罗夫对最低要求的回答。这是我的设置方式:
app.use(session({
cookie: {
sameSite: 'lax', // lax or strict
secure: process.env.NODE_ENV === 'production', // Crucial
maxAge: 1000 * 60 * 60 * 24 * 30, // 30 days
},
proxy: true, // Crucial
resave: false,
saveUninitialized: true,
secret: 'Gotta love cookies',
store: yourSessionStore,
rolling: true,
}));
我的猜测是实际问题是这样的:
httpOnly: true
这意味着任何客户端代码都无法访问 cookie(通过 document.cookie
(,并且您执行的任何 XHR("AJAX"(请求都需要在请求中发送任何 cookie 之前显式设置withCredentials
。
这取决于您使用的客户端设置如何执行此操作:
- 普通 XHR:查看示例代码
- 获取:这里
- jQuery:使用
xhrFields
选项进行$.ajax()
- 角度 1:这里
- 角度2:这里
这正是安全cookie的作用。它不会被浏览器保存在不安全的环境中,请阅读http://
。
您需要添加一个 ssl 证书,将所有 http 请求重定向到 https,然后 cookie 将保存在浏览器中。
在本地设置 https 很烦人,因此在配置/环境变量中设置secure
,您在源代码管理上也设置为 false,并启用它以进行生产/暂存。
编辑:同时启用重新保存,resave: true
从 cookie 解析器中删除密钥似乎可以解决问题并出于某种原因允许登录。我使用的是与会话 cookie 相同的密钥(如文档所述(,所以我不明白为什么它不起作用,但它适用于不安全的 cookie。将密钥保留在 cookie 解析器上并启用会话重新保存 true 也有效。如果有人能解释这一点,将不胜感激。
<VirtualHost *:80>
ServerName xx.com
ProxyPreserveHost On
<Location "/">
ProxyPreserveHost On
ProxyPass http://localhost:8080/
ProxyPassReverse http://localhost:8080/
RequestHeader set X-Forwarded-Port "443"
RequestHeader set X-Forwarded-Proto "https"
</Location></VirtualHost>
app.set('trust proxy', 1(; 像魅力一样工作