【问题标题】:CSRF token mismatch Laravel sanctum and Angular httpCSRF 令牌不匹配 Laravel sanctum 和 Angular http
【发布时间】:2020-07-18 16:02:31
【问题描述】:

我一直在尝试实现 Laravel sanctum,但即使我遵循 Laravel Sanctum 文档中所说的所有内容,我仍然遇到“CSRF 令牌不匹配”错误

cors.php 配置文件

'paths' => [
    'api/*',
    'login',
    'logout',
    'sanctum/csrf-cookie'
],
'supports_credentials' => true,

内核是根据文档添加的,所以在这里添加代码不会浪费空间

.env文件

SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost

我在这里使用 Angular 9 作为我的前端

这是我的拦截器

request = request.clone({
    withCredentials: true
})

这就是我向 Laravel 发送请求的方式

this.http.get<any>(url('sanctum/csrf-cookie')).subscribe(() => {
     this.http.post<any>(url('login'), { this.username, this.password })
         .subscribe(success => console.log(success), error => console.log(error))
})

一旦第一个路由被命中,我可以确认 cookie 的创建,但问题在于第二个路由('/login')

【问题讨论】:

    标签: angular laravel http laravel-sanctum


    【解决方案1】:

    您需要在标头中发送x-csrf-token,(Angular 仅在相对 URL 而非绝对 URL 中自动包含它)

    您可以创建一个解释器来执行此操作,这样应该可以工作:

    import {Injectable} from '@angular/core';
    import {
      HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpXsrfTokenExtractor
    } from '@angular/common/http';
    
    import { Observable } from 'rxjs';
    
    @Injectable()
    export class HttpXsrfInterceptor implements HttpInterceptor {
      headerName = 'X-XSRF-TOKEN';
    
      constructor(private tokenService: HttpXsrfTokenExtractor) {}
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
        if (req.method === 'GET' || req.method === 'HEAD') {
          return next.handle(req);
        }
    
        const token = this.tokenService.getToken();
    
        // Be careful not to overwrite an existing header of the same name.
        if (token !== null && !req.headers.has(this.headerName)) {
          req = req.clone({headers: req.headers.set(this.headerName, token)});
        }
        return next.handle(req);
      }
    }
    
    

    【讨论】:

    • 如何在我的 HttpClient 发布请求中使用它?
    【解决方案2】:

    我的问题是我正在访问端口 8001 上的 api。当我将它 (127.0.0.1:8001) 添加到 config/sanctum.php 中的“有状态”时它起作用了。

    【讨论】:

      【解决方案3】:

      我能够通过在config/sanctum.php 中的localhost 之前添加http:// 来解决此问题

      从这里

      'stateful' => explode(',', env(
              'SANCTUM_STATEFUL_DOMAINS',
              'localhost,127.0.0.1'
      )),
      

      到这里

      'stateful' => explode(',', env(
                  'SANCTUM_STATEFUL_DOMAINS',
                  'http://localhost,127.0.0.1'
          )),
      

      【讨论】:

        【解决方案4】:

        就我而言,这个问题以一种奇怪的方式解决了。我去了 Illuminate\Foundation\Http\Middleware\VerifyCsrfToken 文件,在第 76 行的“if case”中的“handle”方法中有这样一行:

        $this->tokensMatch($request);
        

        出于测试目的,我返回了这个字符串

        return response()->json($this->tokensMatch($request));
        

        令人惊讶的是它会返回一个正常的令牌。然后我把所有东西都放回原处,很奇怪,但是这个错误已经不存在了。

        【讨论】:

          【解决方案5】:

          在我的情况下,我遇到了类似的问题,但只有部分用户遇到了这个问题。我通过在 config 文件夹下的 session.php 文件中将 SESSION_DOMAIN 更改为 .localhost 解决了我的问题。

          【讨论】:

            猜你喜欢
            • 2021-08-18
            • 2021-10-22
            • 2022-01-11
            • 2020-07-31
            • 1970-01-01
            • 2022-09-27
            • 2020-12-11
            • 2022-12-05
            • 2020-07-08
            相关资源
            最近更新 更多