使用 Laravel Sanctum 和 Angular 未为跨域请求设置 CSRF Coo​​kie

CSRF Cookies Not Set for Cross Domain Requests using Laravel Sanctum and Angular

概览

我有一个 Laravel 供电 api 本地托管在 http://tenant.api.hydrogen.local and an Angular 9.2 SPA which is being served on http://localhost:8100. I recently installed Laravel Sanctum for authentication and followed instructions for SPA's listed in the docs 但 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 的响应返回了预期的 headers:

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

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

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

Laravel API

AngularSPA

发生此问题是因为 browser/angular 只会将 cookie 附加到与请求来自的域具有相同域的请求。

为了在 angular 应用程序在本地主机上运行并且 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

现在一切正常。