CSRF 令牌与 Laravel API 不匹配,使用 Digital Ocean Load Balancer with Sticky Session
Posted
技术标签:
【中文标题】CSRF 令牌与 Laravel API 不匹配,使用 Digital Ocean Load Balancer with Sticky Session【英文标题】:CSRF Token Mismatch with Laravel API using Digital Ocean Load Balancer with Sticky Session 【发布时间】:2022-01-11 01:25:56 【问题描述】:我正在使用 Laravel 8 开发一个项目,现在我正在测试生产服务器上的部署。我已经设置了 2 个 Digital Ocean Droplet,它们位于启用了粘性会话的负载均衡器后面。我正在尝试通过带有单独 Laravel API 的 SPA 应用程序登录,因此将中间件配置为 api 路由为有状态 API 并执行 CSRF 验证。当我只点击一个 Droplet 并绕过负载均衡器时,这工作得非常好,但是一旦负载均衡器在使用中,我总是会收到 419 CSRF 令牌不匹配。
我在 Google 上找到的所有内容都表明会话需要在服务器之间共享,但我不认为在这种情况下会出现这种情况。我在负载均衡器中打开了一个名为 DO-LB 的 cookie 的粘性会话,因此来自同一会话的所有请求都转到同一台服务器,我在两台服务器上跟踪 Apache 访问日志,我可以看到所有请求,例如get-csrf 和 auth 路由(使用 Sanctum)都命中同一个服务器,所以我仍然会得到令牌不匹配。
我也在使用 cookie 会话驱动程序。
更新
我发现了一些奇怪的东西,如果我将我的 DNS 指向一个单独的 droplet,我会看到 X-XSRF-TOKEN 作为请求标头发送,但如果我将 DNS 更改为指向负载均衡器,那么 X- xSRF-TOKEN 不作为请求标头发送。我正在使用 Axios 发送请求,但我看不到负载均衡器如何影响 Axios
更新 2
看起来当我在本地运行时 XSRF-TOKEN 不是 HttpOnly cookie,但是当在生产环境中运行时,XSRF-TOKEN 被标记为 HttpOnly,从我所读到的意思是它无法从 javascript 访问,因此为什么 Axios 不是t发送它。我似乎已经通过执行 Cookies.get("XSRF-TOKEN") 并打印结果来确认这一点,它在本地将令牌打印到控制台,但在生产中它是未定义的。
更新 3
我更新了我的 Apache 配置以覆盖标头作为测试以删除似乎已经成功的 HttpOnly 标志,现在我可以看到当我登录时,Chrome 甚至在请求中发送了 X-XSRF-TOKEN虽然我仍然得到一个 CSRF 令牌不匹配。
我已经将 chrome cookie 存储中的字符串与 X-XSRF-TOKEN 中发送的字符串进行了比较,它们都匹配,所以我不明白为什么 Laravel 总是返回不匹配的结果,我完全不知所措.
【问题讨论】:
我认为这应该在Server Fault 上询问。您将在那里获得更多帮助。 其实,是的,我认为你是对的,不知道为什么我没有想到这一点——这是令人沮丧的一天 【参考方案1】:我想我已经弄清楚了,如果它可以迁移到服务器故障,那么请这样做,但我认为它可以说出它是什么而不是仅仅删除。
我正在使用 cloudflare,并在 DO droplet 和 cloudflare 之间使用自签名证书时出错,并将此证书提供给负载均衡器。尽管 DO 没有引发任何错误,但在 Apache 日志中我注意到虽然网站加载,但当发出 API 请求时,我注意到 apache 错误日志Server name not provided via TLS extension (using default/first virtual host)
。不确定这是否是实际原因,但让我想到问题是否是由自签名证书引起的。
我从 Cloudflare 生成了一个新的源服务器,这意味着它具有受信任的 CA,然后将其提供给 DO 负载均衡器,问题就消失了。
【讨论】:
以上是关于CSRF 令牌与 Laravel API 不匹配,使用 Digital Ocean Load Balancer with Sticky Session的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 CSRF 令牌与 Laravel 和 Sanctum 不匹配?
使用 laravel-cors 和 axios 进行 POST 的 Laravel “CSRF 令牌不匹配”
Laravel:CSRF 令牌与 X-XSRF-TOKEN 不匹配 [重复]