如何将laravel CSRF令牌值传递给vue

时间:2016-10-08 23:04:13

标签: laravel vue.js laravel-5.3

我有这个表单,用户只应在文本区域内键入文本:

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

然后,我有这个脚本代码,我将vue.js与ajax一起使用,以便将该文本传递给控制器​​并最终将其保存到数据库中:

//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名称:

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

我该如何解决?有什么想法吗?

6 个答案:

答案 0 :(得分:18)

Very Easy Solution 只需在表单中添加隐藏字段即可。一个例子

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

现在在vue文件中的脚本中添加csrf变量,就像这样。 (请记住,它必须位于数据)内。

<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() }}">

如果没有这样的东西,你需要把它放在那里。

答案 1 :(得分:2)

简单地说,我建议将其放在PHP文件中:

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

通过这种方式,您可以轻松地从JS部件导入csrfToken(在本例中为Vue)。

此外,如果您在PHP布局文件中插入此代码,则可以使用应用程序的任何组件的令牌,因为window是JS全局变量。

来源:我从this发帖获得了这个技巧。

答案 2 :(得分:2)

更好的方法是简单地通过插槽将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>

答案 3 :(得分:1)

由于这两个答案,我解决了这个问题:

1)首先我读了this one,这导致我

2)这second one

所以,在我的表格中,我保留了这个:

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

答案 4 :(得分:0)

我的解决方案是所有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(),
      ]);
    }

答案 5 :(得分:0)

Axios CSRF自动令牌附加解决方案:

首先,将令牌存储在HTML元标记中:

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

然后将CSRF令牌注册为Axios的通用标头,以便所有传出的HTTP请求都自动附加它。

在引导程序/主JS文件中,包括:

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

现在,您可以发出附加了csrf的请求。