5

我一直在尝试实现 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')

4

5 回答 5

4

您需要在标头中发送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);
  }
}

于 2020-04-06T16:18:54.800 回答
4

我能够通过添加http://before localhostin来解决这个问题config/sanctum.php

由此

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

对此

'stateful' => explode(',', env(
            'SANCTUM_STATEFUL_DOMAINS',
            'http://localhost,127.0.0.1'
    )),
于 2021-06-07T13:19:39.650 回答
0

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

于 2022-02-09T11:09:18.420 回答
0

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

于 2020-07-31T07:07:34.930 回答
0

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

$this->tokensMatch($request);

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

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

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

于 2021-06-25T22:55:41.553 回答