Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

vue.js - How to retrieve laravel CSRF token using separated vue frontend

Is there a way to pass Laravel csrf token to Vue given that the Laravel backend and the Vue frontend are separated from each other (in diferent directory and in diferent subdomains) ??

I'm building an application and would like to have separated backend and frontend for organization purposes and for because it facilitates team work. So, it would be something like:

  • api.mydomainexample.com (Laravel backend)
  • mydomainexample.com (Vue frontend for public)
  • admin.mydomainexample.com (Vue Frontend for admin only)

Is this possible? What I thought was maybe running a nodejs server for the frontend project and make the nodejs server communicate with the laravel server. Don't know how to do that.

I found similiar stackoverflow questions, but the responses from them do not solve my problem. The best thing I found was this, which proposes to use Laravel passport. But, is the proposal the only one that works? If so, does Laravel passport protect users from CSRF attacks?

Actually, if there is an workaround which enables to have separated backend and frontend while protecting against CSRF tokens, then that would be perfect!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Use Sanctum

LARAVEL BACKEND

  1. Install Sanctum via Composer

    composer require laravel/sanctum


  1. Publish the Sanctum configuration and migration files

    php artisan vendor:publish --provider="LaravelSanctumSanctumServiceProvider"


  1. Run your migrations - Sanctum will add a table to store API tokens

    php artisan migrate


  1. Add Sanctum's middleware to your api middleware group in your App/Http/Kernel.php

use LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful;

'api' => [
    EnsureFrontendRequestsAreStateful::class,
    'throttle:60,1',
    IlluminateRoutingMiddlewareSubstituteBindings::class,
],
  1. Configure which domains your SPA will be making requests from. From the docs:

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.

So - Update your configsanctum.php to include something like this:

/*
    |--------------------------------------------------------------------------
    | 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. Configure your 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. Configure your 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. In your .env, add the following:

// 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. Run a php artisan config:clear

VUE FRONTEND

  1. In your front-end, create the following folder/file structure @/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;

In the root directory, place an .env file with the following in it:

VUE_APP_API_URL= 'http://api.your-site.local'  
  1. To authenticate, your SPA should first make a request to the /sanctum/csrf-cookie. This sets the XSRF-TOKEN cookie. This token needs to be sent on subsequent requests ( axios will handle this for you automatically ). Immediately after, you'll want to send a POST request to your Laravel /login route.
On your Vue front-end login component:
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;
    },

  },

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...