如何使用分离的 vue 前端检索 laravel CSRF 令牌

How to retrieve laravel CSRF token using separated vue frontend

有没有办法将 Laravel csrf 令牌传递给 Vue,因为 Laravel 后端和 Vue 前端彼此分离(在不同的目录和不同的子域中)??

我正在构建一个应用程序,出于组织目的和为了促进团队合作,我希望将后端和前端分开。所以,它会是这样的:

这可能吗?我想的可能是 运行 前端项目的 nodejs 服务器,并使 nodejs 服务器与 laravel 服务器通信。不知道该怎么做。

找到similiar Whosebug questions, but the responses from them do not solve my problem. The best thing I found was this,建议使用Laravel passport。但是,该提案是唯一可行的吗?如果是这样,Laravel passport 是否可以保护用户免受 CSRF 攻击?

实际上,如果有一种解决方法可以在防止 CSRF 令牌的同时实现后端和前端的分离,那就太完美了!

使用Sanctum

LARAVEL 后端

  1. 通过 Composer 安装 Sanctum

    composer require laravel/sanctum


  1. 发布 Sanctum 配置和迁移文件

    php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"


  1. 运行 您的迁移 - Sanctum 将添加一个 table 来存储 API 代币

    php artisan migrate


  1. 将 Sanctum 的中间件添加到您 App/Http/Kernel.php 中的 api 中间件组

use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],
  1. 配置您的 SPA 将从哪些域发出请求。从文档:

You may configure these domains using the stateful configuration option in your sanctum configuration file. This configuration setting determines which domains will maintain "stateful" authentication using Laravel session cookies when making requests to your API.

所以 - 更新您的 config\sanctum.php 以包含如下内容:

/*
    |--------------------------------------------------------------------------
    | 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', 'localhost,localhost:8000,127.0.0.1,127.0.0.1:8000,::1')),

  1. 配置您的 config/cors.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure your settings for cross-origin resource sharing
    | or "CORS". This determines what cross-origin operations may execute
    | in web browsers. You are free to adjust these settings as needed.
    |
    | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    |
    */

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

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

];
  1. 配置您的 config/session.php

/*
    |--------------------------------------------------------------------------
    | Session Cookie Domain
    |--------------------------------------------------------------------------
    |
    | Here you may change the domain of the cookie used to identify a session
    | in your application. This will determine which domains the cookie is
    | available to in your application. A sensible default has been set.
    |
    */

    'domain' => env('SESSION_DOMAIN', null),
  1. 在您的 .env 中,添加以下内容:

// Change .your-site.local to whatever domain you are using
// Please note the leading '.'

SESSION_DOMAIN=.your-site.local 
SANCTUM_STATEFUL_DOMAINS=your-site.local:8000
CORS_ALLOWED_ORIGINS=http://app.your-site.local:8000

  1. 运行一个php artisan config:clear

VUE 前端

  1. 在您的前端中,创建以下 folder/file 结构 @/src/services/api.js

api.js:

import axios from 'axios';

const apiClient = axios.create({
    baseURL: process.env.VUE_APP_API_URL,
    withCredentials: true,
});

export default apiClient;

在根目录中,放置一个 .env 文件,其中包含以下内容:

VUE_APP_API_URL= 'http://api.your-site.local'  
  1. 要进行身份验证,您的 SPA 应首先向 /sanctum/csrf-cookie 发出请求。这会设置 XSRF-TOKEN cookie。此令牌需要在后续请求中发送(axios 会自动为您处理)。紧接着,您需要向 Laravel /login 路由发送 POST 请求。
在你的 Vue 前端登录组件上:
import Vue from 'vue'
import apiClient from '../services/api';

export default {
  data() {
    return {
        email: null,
        password: null,
        loading: false,
    };
  },
  methods: {

    async login() {
      this.loading = true; // can use this to triggle a :disabled on login button
      this.errors = null;

        try {
          await apiClient.get('/sanctum/csrf-cookie'); 
          await apiClient.post('/login', {
            email: this.email,
            password: this.password
          });

          // Do something amazing
          
        } catch (error) {
          this.errors = error.response && error.response.data.errors;
        }

      this.loading = false;
    },

  },