我正在使用连接到Laravel 10 API的React 18构建一个SPA,其中已经包括用于身份验证的Sanctum,并且我安装了Breeze API来生成相应的脚手架。
我已经遵循了官方Laravel文档,但因为它不足以解决这个问题,我开始与谷歌研究其他开发人员做了什么来摆脱这个不便。我读过许多不同的修复方法,几乎都试过了(其中一些根本没有意义,或者不推荐),直到我在github上看到一个老帖子,由泰勒奥特韦尔自己回答,当时圣所被称为气闸:
因此,我在WAMP中创建了一个域和一个子域,以测试这个可能的解决方案,但仍然看到相同的错误弹出令人沮丧:
正如大家所看到的,GET请求没有问题,但是POST请求有问题。对于这个项目,我安装了AXIOS,但我注意到在发布数据时cookie没有被发送回API服务器。
axios.js
import axios from "axios";
export default axios.create({
baseURL: 'http://api.localdomain',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
withCredentials: true
})
这是我的.env文件:
APP_NAME=localdomain
APP_ENV=local
APP_KEY=base64:SjhdnO/kZ2IMWGKEdgrw+a5e1eToxvtLHsbJvwf0dAs=
APP_DEBUG=true
APP_URL=http://api.localdomain
FRONTEND_URL=http://localdomain
SESSION_DRIVER=cookie
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
SESSION_DOMAIN=.localdomain
SANCTUM_STATEFUL_DOMAINS=api.localdomain
config/cors.php
'paths' => [
'api/*',
'login',
'logout',
'register',
'user/password',
'forgot-password',
'reset-password',
'sanctum/csrf-cookie',
'user/profile-information',
'email/verification-notification',
],
'allowed_methods' => ['*'],
'allowed_origins' => [env('FRONTEND_URL')],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
config/session.php
'domain' => env('SESSION_DOMAIN'),
'http_only' => true,
'same_site' => 'lax',
config/sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf('%s%s%s',
'api.localdomain,localdomain,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : '',
env('FRONTEND_URL') ? ','.parse_url(env('FRONTEND_URL'), PHP_URL_HOST) : ''
))),
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
routes/auth.php
<?php
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\NewPasswordController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController;
use Illuminate\Support\Facades\Route;
Route::post('/register', [RegisteredUserController::class, 'store'])->middleware('guest');
Route::post('/login', [AuthenticatedSessionController::class, 'store'])->middleware('guest');
Route::post('/logout', [AuthenticatedSessionController::class, 'destroy'])->middleware('auth');
Route::post('/forgot-password', [PasswordResetLinkController::class, 'store'])->middleware('guest');
Route::post('/reset-password', [NewPasswordController::class, 'store'])->middleware('guest');
这些路由是使用以下命令生成的路由:
# Install Breeze and dependencies...
composer require laravel/breeze --dev
php artisan breeze:install api
我已经尝试了.env文件cors.php和sanctum.php中可能值的许多不同组合,但到目前为止没有任何积极的结果。任何帮助如何使这项工作是真正的赞赏,因为我已经花了3天的时间尝试不同的修复无济于事。
编辑:(2023/08/19)
看看Axios如何确定是否设置响应头'X-XSRF-TOKEN',我知道POST请求(/login route)头值来自document.cookies
字符串。然而,文档. cookie不是由Laravel(或其软件包之一)设置的,尽管我改变了:
'domain' => '.localdomain',
'secure' => false,
'http_only' => false,
'same_site' => 'lax'
values in php/session.php
我已经在我的开发环境和我的本地域中测试过了。结果相同(状态代码419 / CSRF令牌不匹配)。
在后端端仍然缺少一些东西或配置错误。
2条答案
按热度按时间vc9ivgsu1#
好吧,经过大量的研究和测试,我终于得出了许多人可能正在寻找的答案:使用由Sanctum(Laravel 10)认证的ReactJS SPA,而无需对Laravel配置进行太多更改。
事实上,当你重新安装Laravel时,它已经包含了Sanctum包,所以你需要做的就是安装Breeze API,以创建路由和身份验证脚手架。整个安装过程如下:
1.运行迁移。
就是这样。你不需要在配置文件和原始路由中做任何改变,除非你确切地知道你想做什么。
当然,唯一需要的更改是在
.env
文件中。除此之外,不需要做任何其他事情。下面是我如何配置
.env
文件的例子:通过阅读
config/session.php
文件中的注解,我意识到应该(在两端)使用HTTPS
协议,以便将会话cookie发送回服务器(作为头)。当然,如果我们要发送一个安全的cookie进行身份验证,那么使用
HTTPS
协议是有意义的。如果没有,会话cookie不会被发送回服务器(在POST请求中),这就是为什么我们得到419错误。为了让它正常工作,我使用了Mkcert软件来创建我的证书。如何创建本地信任的SSL证书
这个软件让我省去了很多麻烦。
一旦创建了具有各自证书的虚拟主机,我的SPA就可以正常运行了。同样,泰勒奥特韦尔是正确的,当他说,这工作,一个真实的域和子域是必要的。无法使用Localhost,因为它不是真实的主机。
我希望这可以帮助其他人,因为有很多奇怪的修复和神话,真的很少或没有什么关系运行一个与Laravel Sanctum正确的SPA。
hzbexzde2#
编辑获取CSRF令牌并在cookie中设置
在发出登录的POST请求时,确保X-XSRF-TOKEN标头使用cookie中的CSRF令牌进行设置。Axios在使用CSRF令牌cookie时自动包含此标头。
**更新:**还需要在resources/js/bootstrap.js中设置withCredentials