如何配置 laravel sainttum 来授权其他域并且可由 NuxtJS 使用

问题描述 投票:0回答:1

我有一个 Nuxt 应用程序作为客户端和一个 laravel 9 API,该 api 使用 Laravel-Sanctum,我在将 Nuxt 应用程序与 Laravel 连接时遇到问题,因为管理 sainttum 的端点告诉我我没有获得授权,无论是前面还是和后域不同,是否有我跳过的配置,这就是它不起作用的原因?在这里我与您分享我的代码:

配置/cors.php

<?php

return [

    'paths' => ['api/*',  'login', 'logout', 'sanctum/csrf-cookie', 'api'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

];

配置/sanctum.php

<?php

use Laravel\Sanctum\Sanctum;

return [

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,https://mango-grass-0b3b8cd10.3.azurestaticapps.net/',
        Sanctum::currentApplicationUrlWithPort()
    ))),

    // 'guard' => ['web'],

   'expiration' => null,

    'middleware' => [
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
    ],

];

配置/session.php

<?php

use Illuminate\Support\Str;

return [

    'driver' => env('SESSION_DRIVER', 'file'),

    'lifetime' => env('SESSION_LIFETIME', 120),

    'expire_on_close' => false,

    'encrypt' => false,

    'files' => storage_path('framework/sessions'),

    'connection' => env('SESSION_CONNECTION'),

    'table' => 'sessions',

    'store' => env('SESSION_STORE'),

    'lottery' => [2, 100],

    'cookie' => env(
        'SESSION_COOKIE',
        Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
    ),

    'path' => '/',

    'domain' => env('SESSION_DOMAIN'),

    'secure' => env('SESSION_SECURE_COOKIE'),

    'http_only' => true,

    'same_site' => 'lax',

];

配置/kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

class Kernel extends HttpKernel
{
    protected $middleware = [
        \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        // \App\Http\Middleware\TrustHosts::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
        \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    \Fruitcake\Cors\HandleCors::class,
    ];

    protected $middlewareGroups = [
        'web' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            // \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Fruitcake\Cors\HandleCors::class,
        ],

        'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:60,1',
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Fruitcake\Cors\HandleCors::class,
        ],
    ];

    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \App\Http\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];
}

nuxt.config.js

auth: {
    redirect: {
      home: '/',
      logout: '/login',
      login: '/login',
    },
    plugins: [
      '~/plugins/auth.js',
      { src: '~/plugins/sweetalert2.js', mode: 'client' },
      { src: '~/plugins/VueDebounce.js' },
    ],
    strategies: {
      laravelSanctum: {
        provider: 'laravel/sanctum',
        url: backendUrl,
        endpoints: {
          login: {
            url: '/api/login',
          },
          logout: {
            url: '/api/logout',
          },
        },
      },
    },
  },

登录.vue

const handleSubmit = async () => {
      if (email.value === '' || password === '') {
        Swal.fire({
          title: '¡Información!',
          text: '¡Existen campos obligatorios vacíos.!',
          icon: 'info',
          confirmButtonText: 'Aceptar',
        })
      } else {
        loaderButton.value = true
        await $auth
          .loginWith('laravelSanctum', {
            data: { email: email.value, password: password.value },
          })
          .then((response) => {
            backendService.value.getMe().then((responseMe) => {
              localStorage.setItem('UserName', responseMe.name)
              localStorage.setItem('UserEmail', responseMe.email)
              localStorage.setItem('token', response.data.token)
              getPermissionRol(responseMe.permission)
              router.push('/')
            })
          })
          .catch((error) => {
            if (error.code === 'ECONNREFUSED') {
              Swal.fire({
                title: '¡Error!',
                text: 'No se puede conectar con el servidor. Verifique su conexión a internet o inténtelo más tarde.',
                icon: 'error',
                confirmButtonText: 'Aceptar',
              })
            } else if (error.request && error.request.message) {
              Swal.fire({
                title: '¡Error!',
                text: error.request.message,
                icon: 'error',
                confirmButtonText: 'Aceptar',
              })
            } else {
              Swal.fire({
                title: '¡Error!',
                text: '¡Error!',
                icon: 'error',
                confirmButtonText: 'Aceptar',
              })
            }
          })
          .finally(() => {
            loaderButton.value = false
          })
      }

非常感谢您的帮助。

我遵循了有关 sainttum 配置的文档中的步骤,我尝试将值放入 .env 文件中,但它也不起作用,当我尝试登录时,它不断向我发送错误“419 未知状态”。

laravel nuxt.js laravel-sanctum
1个回答
0
投票

设置 sainttumn.php :

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8080,::1',
        Sanctum::currentApplicationUrlWithPort()
    ))),

然后在 .env 文件中设置 env 变量,如下所示:

FRONTEND_URL=http://localhost:3000
ROOT_URL=//127.0.0.1:8080
APP_URL=http://localhost
SESSION_DRIVER=cookie
SESSION_DOMAIN=.localhost 

然后在 laravel 项目中运行这些命令:

php artisan config:clear && php artisan cache:clear && php artisan optimize && php artisan serve

然后在你的 nuxt login.vue 中:

async function validate() {

  await useFetch("http://localhost:8080/sanctum/csrf-cookie", {
    credentials: "include",
  });

  const token = useCookie('XSRF-TOKEN');

  await useFetch("http://localhost:8080/api/login", {
    credentials: "include",
    method: "POST",
    body: {
      'email': 'email',
      'password': 'password'
    },
    headers: {
      'X-XSRF-TOKEN': token.value as string,
    },
    watch: false
  })
// remaining codes...
}
© www.soinside.com 2019 - 2024. All rights reserved.