如果不使用安全cookie真实设置,我的应用用户登录工作正常。当我启用安全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
}
}));
cloudflare和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。
答案 0 :(得分:8)
对我有用的设置组合:
proxy_set_header X-Forwarded-Proto $scheme;
在 express-session 配置内:
server.use(
session({
proxy: true, // NODE_ENV === 'production'
cookie: {
secure: true, // NODE_ENV === 'production'
},
// everything else
})
);
答案 1 :(得分:4)
使用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
答案 2 :(得分:2)
我的猜测是实际的问题是:
httpOnly: true
这意味着任何客户端代码都无法访问cookie(通过document.cookie
),并且您执行的任何XHR(“AJAX”)请求需要在任何cookie之前明确设置withCredentials
发送请求。
这取决于您正在使用的客户端设置如何执行此操作:
$.ajax()
xhrFields
选项
答案 3 :(得分:1)
这正是安全cookie的作用。浏览器在不安全的环境中不会保存它,请阅读http://
。
您需要添加一个ssl sert,将所有http请求重定向到https,然后cookie将保存在浏览器中。
在本地设置https是令人生气的,因此在配置/环境变量中设置secure
,在源代码管理中也设置为false,并启用它进行prod / staging。
编辑:
同时启用重新保存resave: true
答案 4 :(得分:1)
app.set('trust proxy',1);像魅力一样
答案 5 :(得分:0)
从cookie解析器中删除密钥似乎可以解决这个问题,并且出于某种原因允许登录。我使用与会话cookie相同的密钥(正如文档所说),所以我不明白它为什么不起作用,但它使用不安全的cookie。将密钥保留在cookie解析器上并启用会话重新保存也是有效的。如果有人能够解释这一点,将不胜感激。
答案 6 :(得分:0)
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/会话设置正确。查看 Stoyan Borov 对最低要求的回答。我是这样设置的:
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,
}));
答案 7 :(得分:-1)
<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>