繁体   English   中英

419 页面已过期使用 laravel sanctum

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM