CakePHP 3.7.3:将SecurityComponent与Ajax和SPA一起使用

时间:2019-02-06 21:26:18

标签: cakephp cakephp-3.0

这是启用了SecurityComponent的ajax请求的经典问题。 我主要有一个SPA。这是主要问题。

我也在使用CSRF组件,它工作正常:

const response = await axios.post("/items/add.json", data, {
  headers: {"X-CSRF-Token": "<?= $this->getRequest()->getParam('_csrfToken') ?>"}
});

不起作用的是发送用于安全组件的_Token:

{message: "'_Token' was not found in request data.", url: "/.../add.json", code: 400,…}

我当然可以禁用SecurityComponent。

我不需要请求表单/表单帮助器,那么问题是,当我不使用传统的基于表单的应用程序时,在这里完全使用SecurityComponent是否有意义。当然,我期望某些操作中的某些发布字段/值是有道理的,但是我不确定如何将其与SecurityComponent结合使用。

我想我可以使用助手创建一个虚拟表单并从中提取令牌,但这仅生成一次,并且我有一个SPA。

这当然起作用:

beforeFilter:$this->getEventManager()->off($this->Security);

1 个答案:

答案 0 :(得分:0)

我只是提供技术上的答案,而不是就使用 SecurityComponent 是否有意义发表意见 - 安全性不是我的强项。

如果您需要从 SPA 提交许多 AJAX 调用,是否可以通过 AJAX 请求生成请求表单,然后从中提取令牌?这听起来可能有点 hacky,但实际上可以非常巧妙地完成 - 您提交的每个 AJAX 请求都可以执行您需要执行的操作,然后返回一个新的 <form> 元素(带有新令牌)作为其响应的一部分- 然后您可以将其存放在不可见的地方,覆盖前一个并从中检索令牌以备下次调用。

当涉及到管理提交时,我发现处理令牌等的最简单方法是将 this answer 与序列化(例如 jQuery 的 serialize())结合起来。这整齐地打包了所有隐藏的表单值。我的(基于 jQuery 的)代码如下所示:

var ele_form = $('#some-form-id');
var ele_csrf = ele_form.find('input[name="_csrfToken"]');
var target_url = ele_form.attr('action'); // form-action is validated, so need to generate this correctly
var csrf_token = ele_csrf.val();
$.ajax({
    type: 'POST',
    url: target_url,
    beforeSend: function(xhr){
        xhr.setRequestHeader('X-CSRF-Token', csrf_token);
    },
    data: ele_form.serialize()
});

如果您想更具体地了解您在 SPA 中发送的请求类型,很高兴详细说明该示例。