在Yii2中通过链接使用AJAX提交时的CSRF问题

Bre*_*ett 5 php ajax yii yii2

我正在使用Yii2并且一直在使用通过AJAX执行POST的链接来检索一些数据并且它一直正常工作; 但是我注意到,如果我从页面中删除一个表单,它将不再起作用,并且由于某种原因不会在标题中发送CSRF令牌.

这两种情况下,我还在页面上有几个隐藏的表单.

以下是两种情况:

工作情况:

页面上的所有CSRF都是相同的 - meta标记的标记csrf-token,页面上的主要表单以及所有隐藏的表单,它们都使用SAME CSRF令牌,这与请求的标头中发送的标记相同.

...现在我改变了场景,因此我可以生成非工作版本.

不工作情况:

在这种情况下,页面上没有主要表单.meta命名的标记csrf-token具有与上一个请求不同的CSRF标记,但由于某种原因,所有隐藏的表单都具有来自先前请求/页面加载的相同CSRF标记.

当我点击通过AJAX POST的链接时,标题中没有发送CSRF令牌.

如果重要:

主要形式加载ActiveForm::begin(...)隐藏的形式加载Html::beginForm(...).

知道这里发生了什么吗?为什么不起作用?为什么隐藏的表单具有先前请求中的CSRF令牌?

Mut*_* Rg 2

工作:好的,所以我对问题的理解是,当您使用 ActiveFrom 时,它会创建一个新的 CSRF 令牌并存储在 cookie 中,例如 xxxxxx,因此该页面中的主表单和相应的 HTML 表单会从此 cookie 中读取 csrf 值。

不工作:现在,您进入了一个新页面,因此 Yii 引擎在服务器端创建了一个 csrf(这就是为什么您会看到带有新 csrf 令牌的元标记),除非您调用 ActiveForm,否则 cookie 是不可能的在客户端更新。因此,所有其他 HTML 表单都尝试从 cookie 值中读取以获取 csrf 值,但最终该值是旧的。

因此,除非您可能调用动态创建令牌的函数,否则我看不到值会发生变化。所以值保持不变。

我的想法是尝试一下

'_csrf="<?php echo Yii::$app->request->csrfToken ?>" '
Run Code Online (Sandbox Code Playgroud)

在 HTML 页面中,您没有主表单来从请求返回值。

我没有尝试过,但应该可以。

或者对于阿贾克斯

<head>
   .......
   <?= Html::csrfMetaTags() ?>
</head>

var csrfToken = $('meta[name="csrf-token"]').attr("content");
$.ajax({
         url: 'request',
         type: 'post',
         dataType: 'json',
         data: {param1: param1, _csrf : csrfToken},
});
Run Code Online (Sandbox Code Playgroud)