web-dev-qa-db-ja.com

laravel CSRFトークン値をvueに渡す方法

ユーザーがテキスト領域内にのみテキストを入力する必要があるこのフォームがあります:

            <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>

次に、そのテキストをコントローラーに渡し、最終的にデータベースに保存するために、ajaxでvue.jsを使用している次のスクリプトコードがあります。

//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,
                    }
                });
            }
        },
    });

ただし、このトークンの不一致の例外があるため、これは今のところ機能しません。私はそれを機能させる方法がわかりません。このトークン値をコントローラーに渡す方法。私は次を試しました:

1)フォーム内で、トークンにvue nameを追加しました:

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

2)このトークン値を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,
                    }
                });
            }
        },
    });

...しかし、コンソールでは、vueはキャッチさえしません:(

これにより、次のエラーが発生します。

VerifyCsrfToken.php行68のTokenMismatchException:

どうすれば修正できますか?何か案は?

23
Pathros

次の2つの答えのおかげで解決しました。

1)最初に this one を読みました。

2)これ 2番目

したがって、私のフォームではこれを保持します:

{{ csrf_field() }}

そして、jsファイル内に次のものを追加するだけです(Vueインスタンス)の外側と上):

var csrf_token = $('meta[name="csrf-token"]').attr('content');

したがって、jsコード全体は次のようになります。

var csrf_token = $('meta[name="csrf-token"]').attr('content');
    /*Event handling within vue*/
    //when we actually submit the form, we want to catch the action
    new Vue({
        el      : '#timeline',
        data    :   {
            post    : '',
            token   : csrf_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,
                    }
                });
            }
        },
    });
2
Pathros

Very Easy Solution非表示フィールドをフォーム内に追加するだけです。例

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

このように、vueファイルで、script内にcsrf変数を追加します。(data内にある必要があります)。

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

N.B。メタタグがblade.phpこのようなファイル。

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

このようなものがない場合は、そこに配置する必要があります。

21

より良い方法は、スロットを介してcsrfトークンをvueコンポーネントに渡すだけです。

Blade.phpファイル内:

@extends('layouts.app')

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

MyVueComponent.vueで

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

単純に、これをPHPファイルに入れることをお勧めします。

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

この方法で、JSパーツ(この場合はVue)からcsrfTokenを簡単にインポートできます。

さらに、このコードをPHPレイアウトファイルに挿入すると、windowはJSグローバル変数であるため、アプリの任意のコンポーネントでトークンを使用できます。

ソース: this postからトリックを得ました。

2
Jacopo Pace

これに対する私の解決策は、すべてのvueコンポーネントがリクエストが行われる直前にcsrfトークンを取得することです。これをbootstrap.jsファイルに入れます。

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

次に、クラスCoolApp.phpを用意します

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