web-dev-qa-db-fra.com

Comment passer la valeur du jeton CSRF de laravel à la vue

J'ai ce formulaire où l'utilisateur ne doit taper du texte qu'à l'intérieur d'une zone de texte:

            <form action="#" v-on:submit="postStatus">{{-- Name of the method in Vue.js --}}
                <div class="form-group">
                    <textarea class="form-control" rows="5" maxlength="140" autofocus placeholder="What are you upto?" required v-model="post"></textarea>
                </div>
                <input type="submit" value="Post" class="form-control btn btn-info">

                {{ csrf_field() }}

            </form>

Ensuite, j'ai ce code de script où j'utilise vue.js avec ajax afin de passer ce texte à un contrôleur et éventuellement de l'enregistrer dans la base de données:

//when we actually submit the form, we want to catch the action
    new Vue({
        el      : '#timeline',
        data    :   {
            post    : '',
        },
        http    :   {
            headers: {
                'X-CSRF-Token': $('meta[name=_token]').attr('content')
            }
        },
        methods : {
            postStatus : function (e) {
                e.preventDefault();
                console.log('Posted: '+this.post+ '. Token: '+this.token);
                $.ajax({
                    url         :   '/posts',
                    type        :   'post',
                    dataType    :   'json',
                    data        :   {
                        'body'  :   this.post,
                    }
                });
            }
        },
    });

Cependant, cela ne fonctionne pas jusqu'à présent, car il existe cette exception d'incompatibilité de jeton. Je ne sais pas comment le faire fonctionner. Comment transmettre cette valeur de jeton au contrôleur. J'ai essayé ce qui suit:

1) dans le formulaire, j'ai ajouté un nom de vue au jeton:

<input type="hidden" name="_token" value="YzXAnwBñC7qPK9kg7MGGIUzznEOCi2dTnG9h9çpB" v-model="token">

2) J'ai essayé de passer cette valeur de jeton dans la vue: 

//when we actually submit the form, we want to catch the action
    new Vue({
        el      : '#timeline',
        data    :   {
            post    : '',
            token   : '',
        },
        methods : {
            postStatus : function (e) {
                e.preventDefault();
                console.log('Posted: '+this.post+ '. Token: '+this.token);
                $.ajax({
                    url         :   '/posts',
                    type        :   'post',
                    dataType    :   'json',
                    data        :   {
                        'body'  :   this.post,
                        '_token':   this.token,
                    }
                });
            }
        },
    });

... mais dans la console, la vue ne l'attrape même pas :(

Cela me conduit à l'erreur suivante:

TokenMismatchException dans la ligne VerifyCsrfToken.php 68:

Comment je le répare? Des idées?

17
Pathros

Very Easy Solution Ajoutez simplement un champ masqué à l'intérieur du formulaire. Un exemple

<form id="logout-form" action="/logout" method="POST" style="display: none;">
    <input type="hidden" name="_token" :value="csrf">
</form>

Ajoutez maintenant la variable csrf dans script au fichier de vue, comme ceci. (Rappelez-vous, il doit être dans data ).

<script>
     export default {
        data: () => ({
            csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
          }),        
    }
</script>

N.B. Vous verrez une balise meta dans votre fichier blade.php comme ceci. 

<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">

S'il n'y a rien de tel, vous devez le placer là.

12

Simplement, je suggérerais de mettre ceci dans votre fichier PHP:

<script>
    window.Laravel = <?php echo json_encode(['csrfToken' => csrf_token()]); ?>
</script>

De cette façon, vous pourrez facilement importer votre csrfToken à partir de la partie JS (Vue dans ce cas).

De plus, si vous insérez ce code dans votre fichier de mise en page PHP, vous pouvez utiliser le jeton de tout composant de votre application, car window est une variable globale JS.

Source: J'ai eu le truc de this post.

2
Jacopo Pace

Une meilleure solution consiste simplement à faire passer le jeton csrf via un emplacement dans le composant vue.

Dans le fichier blade.php: 

@extends('layouts.app')

@section('content')
          <my-vue-component>
            {{ csrf_field() }}
          </my-vue-component>
@endsection

Dans MyVueComponent.vue

   <form role="form">
       <slot>
         <!-- CSRF gets injected into this slot -->
       </slot> 
       <!-- form fields here -->
    </form>
0
user247261

Ma solution à cela est que tous les composants vue obtiennent le jeton csrf juste avant qu'une demande soit faite. Je mets cela dans mon fichier bootstrap.js.

Vue.http.interceptors.Push((request, next) => {
   request.headers.set('X-CSRF-TOKEN', CoolApp.csrfToken);
   next();
});

Puis avoir une classe CoolApp.php

    public function getScriptVariables()
    {
      return json_encode([
          'csrfToken' => csrf_token(),
      ]);
    }
0
Marcus