【问题标题】:dealing with CSRF and XSRF-token error messages处理 CSRF 和 XSRF-token 错误消息
【发布时间】:2016-04-16 18:37:36
【问题描述】:

这个问题与一个仍然无法解决的问题相关联,但我现在已经非常准确地确定了它,我专注于我所知道的错误原因,但我已经尝试了我所知道的所有方法。

问题是从 jquery 到控制器的 $.post 会引发 500 内部服务器错误,这实际上是在 VerifyCSRFToken.php 文件的第 67 行中捕获的“不匹配令牌异常”。

因此,控制器没有获取到值,因为中间件停留在中间

为了解决这个问题,我做了:

1) 转到 App\Middleware\VerifyCSRFToken.php 并包含 jquery sn-p 中的路由以被忽略。这应该足够了,但事实并非如此。

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;

class VerifyCsrfToken extends BaseVerifier
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = ['findcountries', 'findpaises','prueba'];
}

2) 另外,我在视图页面中添加了这个元标记。 (实际上,如果我想允许使用 csrf 发送)

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

3) 我包含了我从视图中调用的这段代码 sn-p

// public/js/config.js
$(function () {
    $.ajaxSetup({
        headers: { 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content') }
    });
});

让我感到困惑的是,复制粘贴代码在我的生产服务器上工作了几个月,实际上 CSRFVerifyToken php 文件中的忽略路由起到了作用,我什至不需要元标记和其他 sn-p。

现在我正在 cloud9 中开发 web 的改进版本,我无法摆脱这个问题。

有谁知道怎么办?

谢谢你 更新

这是给出问题的代码:

    function cargarProvincias() {        

            var country = $('#country').val();       
              $url = "{{URL::route('findcountries')}}";   

 this one ==>       $.post($url, {pais:country},function(data){
                    $('#regions').empty();                 
                    $.each(data, function(key, value){                 
                    $('#regions').append('<option value="' + key + '">' + value + '</option>')});
                        cargarCiudades();         
                  });
              }

【问题讨论】:

    标签: laravel csrf


    【解决方案1】:

    您使用的令牌来自元标记,这是错误的。假设您在同一页面上有 2 个不同的表单,这将无法正常工作!

    您应该在 Laravel 生成的表单中使用令牌。我从另一个可能对您有帮助的问题中获取此代码。

    How to call route of controller with ajax serialize

    var formId = '#radicado';
    
    var token = document.getElementById('token').value;
    $.ajax({
        async: true,
        headers: {'X-CSRF-TOKEN': token},
        url: ip+'/storeVersion',
        type:  'POST',
        data: $(formId).serialize(),
        dataType: 'html',
        success: function(result){
            $(formId)[0].reset();
            alert(result);
            document.getElementById("version").style.display = "none";
            document.getElementById("preview").style.display = "none";
            parent.formulario.location.reload() 
        },
        error: function(){
            alert('No se ha actualizado el documento.');
        }
    });
    

    请记住,CSRF 令牌位于您尝试发送的表单中。

    【讨论】:

    • 我看到了你的代码,但是正在做的是序列化一个表单以通过 ajax 发送,就像你在联系表单中所做的那样。但在我的例子中,jquery 将国家发送给控制器,控制器进行数据库查询,检索区域的 json 数组并将其返回给 jquery sn-p,以便它填充选择列表。所以,这种情况不同,我不是通过 ajax 发送表单,而是在 Selected 列表中选择了一个 Value =。
    • 首先,查询不应该在控制器中完成,模型持有MVC模式中的业务逻辑。其次,您正在使用选定的国家/地区对服务器进行 Ajax 调用,最后,这不是我的代码,它是从另一个问题中提取的。如果您请求的路由在 CSRF 中间件下,您必须发送令牌,否则请求将被拒绝。发送一个字段或整个表单都没有关系。
    • 您好,我知道逻辑当然在模型中,但是如果您有模型,在控制器中进行简单查询是一种快速的方法,实际上在文档中您经常会看到查询排序时在控制器中。关于发送令牌,就像我在描述中所说的那样,您可以排除某些路由必须发送 csrf,这就是 Middleware 文件夹中的文件 CSRFVerifyToken.php 的用途。我让它这样工作了 9 个月。 Te agradezco la ayuda y no te enfades tío que no estaba criticalando nada。
    • 在元标记中使用标记是可以的,这简化了每次将其添加到 ajax 请求的需要。它甚至记录在 Laravel CSRF 中,我已经使用它多年了。
    【解决方案2】:

    问题在于开发c9.io的httpS SSL加密环境。

    我在页面中的内容,无论是从谷歌调用js而不是在https下但http都会被阻止作为混合内容的冲突。

    我禁用了浏览器保护以使其全部为 http,但是 https 下的站点会告诉我我正在做某种跨站点请求伪造,因为表单 (http) 的来源不一样环境在 (https)

    因此,只有当表单所在页面的 URL 不在 https 下时,代码才能工作。我可以即时编辑标题,删除或添加 http 中的 s,然后查看成功或失败的情况。

    我首先摆脱了表单,只留下了一个选择列表和一个简单的选择列表以及这个非常简单的 jquery 代码:

    <script>
    
        jQuery(document).ready(function () {
        cargarProvincias();
     //   cargarCiudades();
        $('#country').change(cargarProvincias);
    
         });
    
            function cargarProvincias() {     
    
            var country = $('#country').val();   
          //  alert(country);
              $url = "{{ URL::route('findcountries')}}";   
             // alert($url);
              $.post($url, {input:country},function(data){
                   $('#feedback').text(data);
              });
    
            }
    
       </script> 
    

    然后我把这个选择列表放在一个表单中,没问题。像这样的:

    {!! Form::open(array('route' => 'property.store', 'files'=>true)) !!}
    

    第一张图,如果我从这里删除路线,你会看到 500 错误:

    <?php
    
    namespace App\Http\Middleware;
    
    use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
    
    class VerifyCsrfToken extends BaseVerifier
    {
        /**
         * The URIs that should be excluded from CSRF verification.
         *
         * @var array
         */
        protected $except = [ 'findpaises','prueba','/', 'propertyfound'];
    }
    

    因此,正如我所说,您可以避免在 Ajax 或表单中不发送任何 CSRF,并且仅当您将其包含在上面的忽略列表数组中时。

    另外我必须说,Firefox 不是检查开发问题的好浏览器。您可能已经解决了这个问题,firefox 将保留其存储的错误。

    今天我发现了 slimjet 作为浏览器,如果你使用它,你就会明白我的意思。 Firefox 因为它的血腥插件而让我的电脑崩溃了,而所有东西都内置在 Slimjet 中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-13
      • 2018-02-12
      • 2015-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多