PassportJS req.isAuthenticated()在Chromium浏览器返回false,deserializeUser未执行
问题根因
该浏览器特异性问题来自Chrome 80+版本默认启用的Cookie SameSite=Lax策略,跨站请求下默认不会携带第三方Cookie,而Firefox、Postman、Electron要么未启用该默认限制,要么不属于普通浏览器的跨站限制场景,所以不受影响。你的前后端部署在不同域名下属于跨站场景,因此Chromium内核浏览器会拦截Session Cookie的携带,导致后端取不到Session,直接跳过passport.deserializeUser()执行,req.isAuthenticated()返回false。
修复步骤
- 首先配置Express开启反向代理信任,Heroku使用了反向代理,默认Express无法识别HTTPS请求,会导致Secure Cookie无法下发,在
app.use(session(...))之前添加代码:app.set('trust proxy', 1); - 修改Session的Cookie配置,SameSite=None属性必须搭配Secure=true才能在HTTPS场景下生效,配置修改为:
cookie: { maxAge: 1000 * 60 * 60 * 24, secure: true, sameSite: 'none' }
- 修正CORS白名单配置,你当前生产环境的后端白名单地址末尾多了斜杠,会导致origin匹配失败,修改为:
whitelist = [ "https://www.frontend.com", "https://www.backend.com" ]
- 删除前端Axios请求中手动添加的
Access-Control-Allow-Origin请求头,该头属于响应头,前端主动添加会触发CORS预检错误。 - 启用你注释掉的显式
req.logIn + req.session.save登录逻辑,不需要额外加延迟,该逻辑已经确保Session写入Redis完成后才执行重定向,避免Session未写入就跳转的问题,默认的passport authenticate重定向逻辑没有等待Session写入完成,确实可能出现偶发的认证失败。
验证方法
打开Chrome开发者工具>网络面板,登录时查看/login接口的响应头,确认存在Set-Cookie头,包含SameSite=None、Secure属性;再查看后续/login-success接口的请求头,确认携带了对应的Session Cookie,即可确认修复生效。
内容的提问来源于stack exchange,提问作者VericalId
相关产品推荐
相关产品推荐

