CSRF令牌不匹配:Laravel Sanctum和Angular Http

10
我一直在尝试使用Laravel Sanctum,但是我遇到了"CSRF令牌不匹配"的错误,虽然我遵循了Laravel Sanctum文档中所说的一切。
`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))
})

一旦第一个路由被触发,我可以确认已创建cookies,但问题出现在第二个路由('/login')上。

5个回答

14

我可以通过在config/sanctum.php中在localhost前添加 http:// 来解决此问题。

由此可见:

'stateful' => explode(',', env(
        'SANCTUM_STATEFUL_DOMAINS',
        'localhost,127.0.0.1'
)),
< p > 至于这个

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

5

在头部需要发送 x-csrf-token,(Angular 只会在相对 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);
  }
}


1
我该如何在我的HttpClient post请求中使用它? - Luis Alfredo Serrano Díaz

2

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


1
在我的情况下,这个问题以一种奇怪的方式得到了解决。我进入了Illuminate\Foundation\Http\Middleware\VerifyCsrfToken文件,在那里的第76行,在“if case”内部的“handle”方法中有一行代码像这样:
$this->tokensMatch($request);

为了测试目的,我返回了这个字符串。
return response()->json($this->tokensMatch($request));

令人惊讶的是,它将返回一个正常的标记。然后我把一切都放回原处,很奇怪,但这个错误不再存在了。


1
我的问题是我正在访问端口8001上的API。当我将其添加到config/sanctum.php中的“stateful”时,它可以正常工作(127.0.0.1:8001)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接