[英]419 Page expired using laravel sanctum
我仍在构建使用 SPA 的身份验证方法,我已经安装了 laravel sanctum 并按照正确的步骤在欢迎刀片上创建了一个演示表单,只是为了测试一下,我使用 sanctum/csrf 正确接收 xsrf-cookie -cookie,但是登录返回 419 页面已过期。 我试过清除缓存、路由、配置
服务于本地主机:8000
.env
SANCTUM_STATEFUL_DOMAINS=localhost:8000
SESSION_DOMAIN=localhost
cors
'paths' => ['api/*','login','sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];
web 路线
Route::post('login', function(){
echo"a";
});
// Route::post('register', [UserController::class,'register']);
Route::get('/',function(){
return view('welcome');
});
形式
<form method="post" action="/login">
<button type="submit">Submit</button>
</form>
我手动访问 localhost:8000/sanctum/csrf-cookie,我可以看到 xsrf 的 cookies 和 session 正在设置,在提交时我仍然得到 419 页过期。 (添加@csrf 使它工作,但是,这只是为了测试,我打算使用SPA)
以下是它对我的工作方式:
在 kernel.php
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:5000,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Session\Middleware\StartSession::class
],
在 config/sanctum.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Stateful Domains
|--------------------------------------------------------------------------
|
| Requests from the following domains / hosts will receive stateful API
| authentication cookies. Typically, these should include your local
| and production domains which access your API via a frontend SPA.
|
*/
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. If this value is null, personal access tokens do
| not expire. This won't tweak the lifetime of first-party sessions.
|
*/
'expiration' => null,
/*
|--------------------------------------------------------------------------
| Sanctum Middleware
|--------------------------------------------------------------------------
|
| When authenticating your first-party SPA with Sanctum you may need to
| customize some of the middleware Sanctum uses while processing the
| request. You may change the middleware listed below as required.
|
*/
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
];
in.env(我对主要的 API 和 SPA 网站都使用子域)
SESSION_DRIVER=cookie
SESSION_LIFETIME=86400
SESSION_DOMAIN=".myapidomain.com"
SANCTUM_STATEFUL_DOMAINS=".myapidomain.com"
在 cors.php
'paths' => ['api/*','sanctum/csrf-cookie'],
'supports_credentials' => true,
在用户 model 例如:App\User
use Laravel\Sanctum\HasApiTokens;
我没有在前端使用 vuejs,所以我使用了 Laravel HTTP Facade,所以我创建了一个 class 来管理已验证请求和未验证请求的 SPA 请求
<?php
namespace App\Http\Controllers\Api\Settings;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Session;
class Master
{
public $domainApiLink = "https://subdomain.mydomain/api/";
public $domainWebLink = "https://sbdomain.mydomain.com/";
private $cookies;
public function __construct(){
$this->generate_cookies();
}
public function generate_cookies(){
if(empty(Session::get('cookies'))) {
$cookies = Http::acceptJson()->asJson()->get($this->domainWebLink . 'sanctum/csrf-cookie')->throw()->cookies();
Session::put('cookies', $cookies);
}
}
public function getRequest($get_link_part, $type = '')
{
$activeLocale = app()->getLocale();
if(Session::has('auth_token') ) {
$response = Http::acceptJson()->asJson()
->withToken( Session::get('auth_token'))
->withOptions([
//'debug' => true
])
->get($this->domainApiLink . $activeLocale . $get_link_part)
->throw();
}else{
$response = Http::acceptJson()->asJson()
->withToken($this->website_token)
->withOptions([
//'debug' => true,
'cookies' => Session::get('cookies'),
])
->get($this->domainApiLink . $activeLocale . $get_link_part)
->throw();
}
switch ($type) {
case 'json':
$response = $response->json();
break;
case 'assoc':
if (is_array($response->json())) {
return $response->json();
} else {
$response = json_decode($response->json(), true);
if (empty($response)) {
return ['error' => 'Invalid Json response'];
}
}
break;
case 'object':
$response = $response->object();
break;
default:
$response = $response->body();
break;
}
return $response;
}
public function postRequest($inputs, $get_link_part, $type = '')
{
$activeLocale = app()->getLocale();
if(Session::has('auth_token') ) {
$response = Http::acceptJson()->asJson()
->withToken(Session::get('auth_token'))
//->withOptions(['debug' => true])
->post($this->domainApiLink . $activeLocale . $get_link_part, $inputs)
->throw();
}
else{
$response = Http::acceptJson()->asJson()
->withToken($this->website_token)
->withOptions([
//'debug' => true,
])
->post($this->domainApiLink. $activeLocale . $get_link_part, $inputs)
->throw();
}
switch ($type) {
case 'json':
$result = $response->json();
break;
case 'assoc':
if (is_array($response->json())) {
$result = $response->json();
} else {
$result = json_decode($response->json(), true);
if (empty($result)) {
$result = ['error' => 'Invalid Json response'];
}
}
break;
case 'object':
$result = $response->object();
break;
default:
$result = $response->body();
break;
}
return $result;
}
/**
* @return mixed
*/
public function getCookies()
{
return $this->cookies;
}
/**
* @param mixed $cookie
*/
public function setCookies($cookie): void
{
$this->cookies = $cookie;
}
}
我希望这对您有所帮助,如果需要,我很乐意解释更多
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.