【问题标题】:laravel TokenMismatchException in ajax requestajax请求中的laravel TokenMismatchException
【发布时间】:2014-03-04 19:56:15
【问题描述】:

我正在使用资源组并使用此过滤器来解决TokenMismatchException 问题:

Route::filter('csrf', function($route, $request) {
    if (strtoupper($request -> getMethod()) === 'GET') {
        return;
        // get requests are not CSRF protected
    }

    $token = $request -> ajax() ? $request -> header('X-CSRF-Token') : Input::get('_token');

    if (Session::token() != $token) {
        throw new Illuminate\Session\TokenMismatchException;
    }
});

我的路线:

Route::group(array('prefix'=> 'admin', 'before' => 'csrf'), function(){
    Route::resource('profile' , 'ProfileController', array('as'=>'profile') );
});

现在。我收到 Ajax 请求错误,例如此代码:

<script type="text/javascript">
    $(document).ready(function() {
       $('#frm').submit(function(e){
           e.preventDefault();
           name         = $('#name').val();
           family       = $('#family').val();
           email        = $('#email').val();
           currPassword = $('#currPassword').val();
           password     = $('#password').val();
           password_confirmation = $('#password_confirmation').val();     

           $.post("{{ route('admin.profile.update', $profile->id) }}",
                { 
                  _method : 'PUT',
                  name                  : name,
                  family                : family,
                  email                 : email,
                  currPassword          : currPassword,
                  password              : password,
                  password_confirmation : password_confirmation  
                },
                function(data)
                {
                    alert(data.errors.name);
                },'json');
                return false;
       });
});
</script>

错误:

{"error":{"type":"Illuminate\\Session\\TokenMismatchException","message":"","file":"\/var\/www\/alachiq\/app\/filters.php","line":83}}

我想我必须在$.post 中发送_token。但我无法获得带有name 属性的input 标签。我得到这个错误:

TypeError: 'stepUp' called on an object that does not implement interface HTMLInputElement.

【问题讨论】:

    标签: php ajax laravel laravel-4


    【解决方案1】:

    Laravel 文档中有一个关于如何执行此操作的提示。这可能在提出问题时不可用,但我想我会用答案更新它。

    http://laravel.com/docs/master/routing#csrf-x-csrf-token

    我已经测试了文档中的元标记方法并使其正常工作。将以下元标记添加到您的全局模板中

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

    添加此 JavaScript,为 jQuery 中的所有 ajax 请求设置默认值。最好在您的应用中包含的 js 文件中。

    $.ajaxSetup({
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
    })
    

    此令牌可以存在于请求标头或表单中。这会将其填充到每个 ajax 请求的请求标头中。

    【讨论】:

    • 嗨,保罗!即使我的网站上有很多表格,这是否安全?我只是在考虑它,因为我正在使用模板并将其扩展到我的所有视图。
    • 是的,表格的数量与此无关。它只是在每个 ajax 请求中添加一个 http 标头。
    【解决方案2】:

    您必须使用 _token 插入隐藏输入,然后像获取 ajax 帖子中的其他表单字段一样获取该值。

    <input type="hidden" name="_token" value="{{ csrf_token() }}" />
    

    另一种方法,

    在您的视图中,您可以使用 _token 设置对象

    <script type="text/javascript">
        var _globalObj = {{ json_encode(array('_token'=> csrf_token())) }}
    </script>
    

    稍后在您的 ajax 调用中,您可以像这样从对象中获取 _token:

    var token = _globalObj._token;
    

    并将其包含在您的 ajax 帖子中。

    【讨论】:

    • 我正在使用{{ Form::model() }},这可以插入_token隐藏input标签。这不是我的问题
    • 在您发布 ajax 帖子时,您是否看到 _token 字段已通过?如果是这样,那与您会话中的正确/相同吗?
    • 是的,这是正确的,在我将Route::resource('profile' , 'ProfileController', array('as'=&gt;'profile') ); 转换为group 之后,我遇到了这个问题。
    【解决方案3】:

    只需按照我在以下代码中显示的简单操作,

        $.ajax({
            type: 'POST',
            url: 'your-post-route-url',
            data: {
                "_token": "{{ csrf_token() }}",
                "form_data": $('#Form').serialize(),
            },
            success: function (data) {
                console.log(data);
            },
            error: function (reject) {
                console.log(reject);
            }
        });
    

    我希望这是解决此问题的最简单方法,无需任何隐藏字段,并且在 laravel 5.4 版本中对我有用 :)

    希望对你有帮助。

    【讨论】:

    • 只对内联javascript有用,不能在外部javascript文件中使用
    【解决方案4】:

    您也可以在

    VerifyCsrfToken.php 文件中添加导致错误的 url
    protected $except = [
        //
    ]
    

    假设您的路线是帖子。你可以像这样添加

    protected $except = ['post',
        //
    ];`... 
    

    希望这对其他人有所帮助。

    【讨论】:

    • 最简单的解决方案
    • 这不安全。如果没有 CsrfToken 保护,有人可能会滥用这个开放端点。
    【解决方案5】:
      <html>
      <head>
      <title>Ajax Example</title>
          <meta name="csrf-token" content="<?php echo csrf_token() ?>" />    
      <script src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js">
      </script>
    
      <script type="text/javascript">
            $.ajaxSetup({
              headers: {
                  'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
              }
            });
      </script>
    
      <script>
         function getMessage(){
            $.ajax({
               type:'POST',
               url:'/getmsg',
               data:'_token = <?php echo csrf_token() ?>',
               data:'',
               success:function(data){
                  $("#msg").html(data.msg);
               }
            });
         }
      </script>
      </head>
    
      <body>
    
    
      <div id = 'msg'>This message will be replaced using Ajax. 
         Click the button to replace the message.</div>
      <?php
         echo Form::button('Replace Message',['onClick'=>'getMessage()']);
      ?>
      </br>
    
    
      </body>
    
      </html>
    

    VerifyCsrfToken.php文件添加这个功能

    protected function tokensMatch($request)
    {
        // If request is an ajax request, then check to see if token matches token provider in
        // the header. This way, we can use CSRF protection in ajax requests also.
        $token = $request->ajax() ? $request->header('X-CSRF-Token') : $request->input('_token');
    
        return $request->session()->token() == $token;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-10-12
      • 2018-11-21
      • 1970-01-01
      • 2014-12-28
      • 2016-06-17
      • 2015-12-19
      • 2019-03-14
      • 1970-01-01
      • 2016-06-23
      相关资源
      最近更新 更多