4

概述

我有一个本地托管在http://tenant.api.hydrogen.local的 Laravel 驱动的 api 和一个在http://localhost:8100上提供的 Angular 9.2 SPA 。我最近安装了 Laravel Sanctum 进行身份验证,并按照文档中列出的 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

但是,当我查看浏览器控制台时,我没有看到存储 > cookie 中设置的任何内容。此外,在随后的“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 标头,但是提取的令牌为空,因为它们尚未在浏览器中设置
4

1 回答 1

4

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

为了在 localhost 上提供 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

现在一切都应该工作了。

于 2020-05-08T02:33:01.933 回答