通过 Yii2 中的链接使用 AJAX 提交时的 CSRF 问题
Posted
技术标签:
【中文标题】通过 Yii2 中的链接使用 AJAX 提交时的 CSRF 问题【英文标题】:CSRF issue when using AJAX submit via link in Yii2 【发布时间】:2015-11-15 19:05:12 【问题描述】:我正在使用Yii2
,并且一直在使用通过 AJAX 进行 POST 的链接来检索一些数据,并且它一直运行良好;但是我注意到,如果我从页面中删除一个表单,它就不再起作用,并且由于某种原因不会在标题中发送 CSRF 令牌。
我在页面上还有几个隐藏表单,它们在两种情况下都存在。
以下是两种情况的总结:
工作情况:
页面上的所有 CSRF 都是 same - 名为 csrf-token
的 meta
标签,页面上的主表单以及所有隐藏表单,它们都使用相同的 CSRF 令牌这与请求标头中发送的令牌相同。
...现在我更改场景,以便生成非工作版本。
不工作情况:
在这种情况下,页面上没有主窗体。名为csrf-token
的meta
标记与上一个请求具有不同的CSRF 令牌,但由于某种原因,所有隐藏 表单都具有与上一个 请求相同的CSRF 令牌/页面加载。
当我点击 POST 通过 AJAX no CSRF 令牌在标头中发送的链接时。
如果重要的话:
main 表单加载了ActiveForm::begin(...)
,而隐藏 表单加载了html::beginForm(...)
。
知道这里发生了什么吗?为什么它不起作用?为什么隐藏表单有来自先前请求的 CSRF 令牌?
【问题讨论】:
【参考方案1】:工作:好的,所以我对这个问题的理解是,当你使用 ActiveFrom 时,它会创建一个新的 CSRF 令牌并存储在一个 cookie 中,比如 xxxxxx,所以主表单和相应的 HTML 表单在该页面从此 cookie 中读取 csrf 值。
不工作: 现在,您进入了一个新页面,因此 Yii 引擎在服务器端创建了一个 csrf(这就是为什么您会看到带有新 csrf 令牌的元标记),除非您调用ActiveForm,没有办法在客户端更新cookie。因此,所有其他 HTML 表单都尝试从 cookie 值中读取以获取 csrf 值,该值最终是旧的。
因此,除非您可能调用动态创建令牌的函数,否则我看不到值发生变化。所以值保持不变。
我的想法是尝试一下
'_csrf="<?php echo Yii::$app->request->csrfToken ?>" '
在 HTML 页面中,您没有 Main 表单来从请求中返回值。
我没试过,但应该可以。
或者对于 Ajax
<head>
.......
<?= Html::csrfMetaTags() ?>
</head>
var csrfToken = $('meta[name="csrf-token"]').attr("content");
$.ajax(
url: 'request',
type: 'post',
dataType: 'json',
data: param1: param1, _csrf : csrfToken,
);
【讨论】:
我已经在我的元标记中使用了Html::csrfMetaTags()
,所以总是在那里,一旦我开始使用像这样通过 JS 传递令牌的解决方案,问题就停止了。我没有回答这个问题,因为我认为这只解决了 AJAX 问题,但似乎隐藏的表单现在也总是得到一个新的令牌。顺便说一句,Html::beginForm()
也会生成一个令牌,因此您不需要调用 ActiveForm 来获取新令牌。以上是关于通过 Yii2 中的链接使用 AJAX 提交时的 CSRF 问题的主要内容,如果未能解决你的问题,请参考以下文章