Несоответствие токена CSRF Laravel sanctum и Angular http
Я пытался реализовать Laravel sanctum, но у меня возникает эта ошибка "Несоответствие токена CSRF", хотя я следил за всем, что сказано в документации Laravel Sanctum.
cors.php
файл конфигурации
'paths' => [
'api/*',
'login',
'logout',
'sanctum/csrf-cookie'
],
'supports_credentials' => true,
kernal добавлен в соответствии с документацией, поэтому не теряйте место, добавляя здесь свой код
.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')
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);
}
}
Мне удалось решить эту проблему, добавив
http://
перед
localhost
в
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'
)),
У меня похожая проблема в моем случае, но только у некоторых пользователей возникает эта проблема. Я решил свою проблему, изменив SESSION_DOMAIN на
.localhost
в файле session.php в папке конфигурации.
Моя проблема заключалась в том, что я обращался к api через порт 8001. Он работал, когда я добавлял его (127.0.0.1:8001) в "stateful" в config/sanctum.php.
В моем случае эта проблема решилась странным образом. Я зашел в файл Illuminate\Foundation\Http\Middleware\VerifyCsrfToken и там в строке 76 в методе «handle» внутри «if case» была такая строка:
$this->tokensMatch($request);
В целях тестирования я вернул эту строку
return response()->json($this->tokensMatch($request));
и, что удивительно, он вернет нормальный токен. Потом вернул все на место, и как ни странно, но этой ошибки уже не было.