【问题标题】:CSRF Cookies Not Set for Cross Domain Requests using Laravel Sanctum and Angular未使用 Laravel Sanctum 和 Angular 为跨域请求设置 CSRF Coo​​kie
【发布时间】:2020-05-08 10:33:01
【问题描述】:

概述

我有一个本地托管在 http://tenant.api.hydrogen.local 的 Laravel 驱动的 api 和一个在 http://localhost:8100 上提供的 Angular 9.2 SPA。我最近安装了 Laravel Sanctum 进行身份验证,并按照docs 中列出的 SPA 说明进行操作,但 CSRF 令牌未附加到来自 SPA 的请求,因此我收到 CSRF 令牌不匹配错误。

按照指示,我在随后尝试登录之前先拨打了//abc.api.hydrogen.local/sanctum/csrf:

this.http.get('sanctum/csrf-cookie')
    .pipe(
        switchMap(result => this.http.post('auth/login', {'email': email, 'password': password}))
    );

注意:我有一个拦截器,它在请求 url 前面加上 api url '//abc.api.hydrogen.local/' 例如'sanctum/csrf-cookie' 将变为 '//abc.api.hydrogen.local/sanctum/csrf-cookie'

来自 sanctum/csrf-cookie 的响应与预期的标头一起返回:

Access-Control-Allow-Credentials: true
Set-Cookie: XSRF-TOKEN=eyJpdiI6Ilc3UkRLR1BSZ29TWVh3ZWZEQ3Y4aGc9PSIsInZhbHVlIjoiRUZBZXNFWTlZbWo5QWhIeWsrRmpjNUZVWkExSGtaT1hzUTVnSXpoaGQ4c3dFc2VLNjZsUHlUVWFmbG1uVVdKZSIsIm1hYyI6ImU1ZTAxNGFmMjAwNWRiMDhiODFjMGZhYTljYmU1NmRjYTUzYTNmNDJjNWM3YmQyM2FkY2I2OGYwNjYzNGU2MjkifQ%3D%3D; expires=Thu, 30-Apr-2020 13:35:06 GMT; Max-Age=7200; path=/; domain=localhost
Access-Control-Allow-Origin: http://localhost:8100

但是,当我查看浏览器控制台时,我在 storage > cookies 中看不到任何设置。此外,在随后的“login/”调用中没有附加任何 cookie,并且我收到 CSRF 令牌不匹配错误。

我已经阅读了许多详细描述类似问题的帖子,并实施了他们的建议和配置,包括以下内容:

Laravel API

  • 在 .env 中我设置了 SESSION_DRIVER=cookie 和 SESSION_DOMAIN=localhost:8100
  • 在 config/sanctum 中,我已将 localhost:8100 添加到有状态域中
  • 在 config/cors 中,我设置了 supports_credentials = true 并允许所有路径、标题和来源(使用 '*' 值)

角度 SPA

  • 我已经实现了一个全局拦截器,它将 withCredentials = true 设置为所有请求
  • 我已确保我的 api 调用使用 //abc.api.hydrogen.com/ 而不是 http://abc.api.hydrogen.com/
  • 我还尝试使用拦截器将 X-XSRF-TOKEN 标头设置为推荐的 here 但提取的令牌为空,因为它们尚未在浏览器中设置

【问题讨论】:

  • 我也面临同样的问题。我认为问题是 XSRF-TOKEN cookie 没有在浏览器中设置,即使 cookie 存在于响应中。因此登录请求失败,因为该请求没有发送 XSRF-TOKEN。完成sanctum/csrf-cookie 请求后,能否检查应用程序中的 cookie?

标签: angular laravel laravel-sanctum


【解决方案1】:

出现此问题是因为浏览器/角度只会将 cookie 附加到与请求来源具有相同域的请求。

为了在 Angular 应用程序在 localhost 上提供服务且 Laravel 应用程序位于 abc.api.hydrogen.local 之类的域上的开发环境中解决此问题,我代理了来自 Angular 应用程序的请求:

首先确保您的请求是相对路由,例如,我将调用更改为 /api/sanctum/crsf,然后将其代理到 http://abc.api.hydrogen.local/sanctum/crsf

然后在项目根目录下创建代理配置proxy.conf.json:

{
    "/api/*": {
      "target": "http://abc.api.hydrogen.local",
      "secure": false,
      "changeOrigin": true,
      "logLevel": "debug",
      "pathRewrite": {
        "^/api": ""
      }
    }
}

然后编辑angular.json 以在服务时使用代理:

"architect": {
    ...
    "serve": {
        ...
        "options": {
            ....
            "proxyConfig": "proxy.conf.json"
        }
    }
}

最后在您的.env 文件中添加以下内容,以确保 sanctum 将请求识别为来自第一方 SPA,并且浏览器能够读取 cookie 并将其附加到请求中。

SANCTUM_STATEFUL_DOMAINS=localhost,.hydrogen.local
SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost

现在一切都应该正常了。

【讨论】:

  • 很高兴你解决了你的问题。我遇到的问题几乎和你的完全一样,除了它内置的 react。前端位于 localhost:9000 中,api 位于 laravel.test/api/V1 中。仍然无法正常工作。SESSION_DOMAIN=laravel.test 并在有状态域中添加了 localhost:9000
  • 您的会话域应该是本地主机,否则浏览器将不会发送 cookie。有状态域应该是您代理的域,即 Laravel.test
  • 更改 .env 非常适合我的 react spa。谢谢,
猜你喜欢
  • 2020-09-10
  • 2021-08-16
  • 1970-01-01
  • 2020-08-22
  • 2013-07-16
  • 2018-12-30
  • 2016-03-16
  • 2016-04-19
相关资源
最近更新 更多