如何在 Cakephp 3 的 ajax 调用中定义 CSRF 令牌。此外,对于某些 ajax 请求,如何关闭 CSRF

Posted

技术标签:

【中文标题】如何在 Cakephp 3 的 ajax 调用中定义 CSRF 令牌。此外,对于某些 ajax 请求,如何关闭 CSRF【英文标题】:How to define CSRF token in ajax call in Cakephp 3. Also How CSRF can be off for some ajax requests 【发布时间】:2017-11-11 07:03:31 【问题描述】:

在 Cakephp3 中启用 Csrf 组件时。我如何在 ajax 调用中使用它。 在这个 beforeSend ajax csrf 令牌的参数中,在 header 中设置。 csrfToken 的值是多少。因为它给出了错误

csrfToken 未定义

beforeSend: function(xhr)
    xhr.setRequestHeader('X-CSRF-Token', csrfToken);
,

另外,我怎样才能为某些 ajax 调用禁用 Csrf 组件。

【问题讨论】:

相关:***.com/questions/28417781/jquery-add-csrf-token-to-all-post-requests-data 【参考方案1】:

CSRF 组件将当前令牌作为_csrfToken 写入请求参数,您可以通过请求对象的param() 方法(或CakePHP 3.4 的getParam())获取它:

beforeSend: function(xhr)
    xhr.setRequestHeader(
        'X-CSRF-Token',
        <?= json_encode($this->request->param('_csrfToken')); ?>
    );
,

要使令牌可用于您的所有脚本,例如,您可以使其在布局模板中作为变量全局可用:

<script>
var csrfToken = <?= json_encode($this->request->param('_csrfToken')) ?>;
// ...
<script>

然后您可以轻松地在所有 AJAX 请求中使用它:

setRequestHeader('X-CSRF-Token', csrfToken);

可以通过从控制器事件管理器中删除 CSRF 组件来禁用它。您必须弄清楚您需要在什么条件下执行此操作,例如针对特定操作,如下所示:

public function beforeFilter(\Cake\Event\Event $event)

    parent::beforeFilter($event);

    if ($this->request->param('action') === 'actionXyz') 
        $this->eventManager()->off($this->Csrf);
    

如果您使用 CSRF 中间件,则令牌仍可用作名为 _csrfToken 的请求参数,但禁用中间件的工作方式有所不同,请参见例如 Cakephp 3.5.6 disable CSRF Middleware for controller

另见

Cookbook > Request & Response Objects > Request Parameters Cookbook > Controllers > Components > CSRF > Using the CsrfComponent Cookbook > Controllers > Components > CSRF > Disabling the CSRF Component for Specific Actions

【讨论】:

感谢您的回复。 :) 这可能是一个快速修复,但我认为,我们不应该禁用 CSRF 安全组件。它的存在是有原因的。就我而言,在 ajax 之前序列化表单工作正常。我认为,您也不需要使用 beforesend @Invincible 恕我直言有点笼统,在许多情况下使用标题是正确/明智的方法,例如可能根本没有表单,即没有可序列化的内容,或者表单可能不是通过表单助手创建的,因此其中不会有任何标记。虽然建议使用 CSRF 保护,但在某些情况下禁用它是完全可以的,有时甚至是必需的,例如在使用身份验证机制的 API(或接受“外部”非表单请求的类似端点)的情况下(或根本没有),从一开始就不容易出现 CSRF。 @ndm 是的,完全同意。视情况而定。【参考方案2】:

每个表单都有一个隐藏的_csrfToken 字段,当您启用 Csrf 组件时会自动添加该字段。现在您可以通过jquery 轻松获取该字段的token,例如$('[name="_csrfToken"]').val()

ajax 调用如下所示:

$.ajax(
   url: 'someUrl',
   headers : 
      'X-CSRF-Token': $('[name="_csrfToken"]').val()
   ,
   type: 'post',
   ...
);

【讨论】:

【参考方案3】:

CakePHP 3

请不要解锁字段/禁用任何 CSRF 安全组件 特定的动作。这对表单安全很重要。

对于那些收到“请求已被黑洞”的人。 ,"表单被篡改错误","您无权访问 该位置。”“POST 数据中的意外字段”。 主要是因为 CSRF 组件按预期工作。

禁用或修改它不是解决方案。请遵循正确的方法,而不是禁用。 在上述情况下,请尝试序列化表单,这应该会产生魔力。

var el = $("#xyzForm");

var ajaxTPCalls = el.serializeArray();
  $.ajax(
                            type: el.attr('method'),
                            async: true,
                            url:  el.attr('action'),
                            data: ajaxTPCalls,
                            dataType: "json",
                            cache: false,
                            success: function (data) 

                                toastr.success(data.message, data.title);
                            ,
                            error: function (jqXHR) 
                                if (jqXHR.status == 403) 
                                    $("body").html(jqXHR.responseText);
                                
                            
                        );

这样您不会禁用 CSRF 或解锁任何字段。

【讨论】:

令人沮丧的是,即使我使用序列化方法,我仍然以_Token was not found in request data结尾。表单是使用 FormHelper 创建的,其中包含所有正确的字段...

以上是关于如何在 Cakephp 3 的 ajax 调用中定义 CSRF 令牌。此外,对于某些 ajax 请求,如何关闭 CSRF的主要内容,如果未能解决你的问题,请参考以下文章

Cakephp 3:Json 渲染视图不起作用

PatchEntity 在 Cakephp 3.0 中忽略来自 ajax 请求的数据

Cakephp 3.4 AJAX 请求抛出 403 禁止错误

如何在 cakephp 中通过 ajax 提交 jquery 移动弹出表单

CakePHP 3 AJAX POST 不允许并返回 403

如何在cakephp 3中获取数据表搜索键?