Nginx反向代理在Safari下无法传递X-Forwarded-Proto致会话失效
解决方案
问题根源
你的Nginx配置中,proxy_set_header X-Forwarded-Proto $scheme; 定义在外层/ac-hoteling location下,但内层/ac-hoteling/api/的独立location不会自动继承外层的proxy头配置,导致API请求在Safari中未携带X-Forwarded-Proto头,触发issecure函数返回false,最终无法设置secure属性的connect.sid cookie,造成会话无法持久化。此外,Safari对Cookie的SameSite属性校验比Chrome/Firefox更严格,也是问题的辅助诱因。
修复步骤
- 修正Nginx配置,确保API请求携带代理头
将proxy_set_header移至/ac-hoteling/api/的location内部,同时补充必要的代理头信息:
location /ac-hoteling { try_files $uri /ac-hoteling/myoffice/index.html; location ~ \.(css|js|png|jpeg|jpg|svg)$ { try_files $uri =404; } location /ac-hoteling/api/ { proxy_pass http://0.0.0.0:8000; # 强制API请求携带X-Forwarded-Proto头 proxy_set_header X-Forwarded-Proto $scheme; # 补充其他必要代理头,确保Express能正确识别请求来源 proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $host; } }
- 完善Express的代理信任配置
除了express-session中的proxy: true,需在Express应用初始化后明确声明信任反向代理:
// 初始化express app后添加 app.set('trust proxy', true);
这会让Express正确解析反向代理传递的头信息,保证req.secure值的准确性。
- 调整Cookie配置适配Safari规则
Safari要求Secure Cookie必须搭配SameSite: None(跨域场景下),且仅在HTTPS环境生效。修改sessionConfig:
const sessionConfig = { secret: process.env.COOKIE_SECRET, resave: false, saveUninitialized: true, proxy: true, cookie: { secure: process.env.NODE_ENV === 'production', sameSite: process.env.NODE_ENV === 'production' ? 'None' : 'Lax', httpOnly: true, ...appCookieOptions, }, };
注意:SameSite: None必须与secure: true同时设置,否则Safari会拒绝存储该Cookie。
验证
重启Nginx和Express服务后,在Safari中测试API请求,检查请求头是否包含X-Forwarded-Proto: https,同时查看响应头的Set-Cookie字段是否带有secure; SameSite=None属性,确认connect.sid Cookie已正常设置。
内容的提问来源于stack exchange,提问作者Yash
相关产品推荐
相关产品推荐

