在我的Yii2应用程序中,有用户提交的表格。该站点已启用CSRF验证,但是如果用户禁用了Cookie,则会引发错误。处理这种情况的最佳方法是什么?我真的不想禁用CSRF验证以确保仅从我的站点提交表单。不涉及登录过程。对于用户而言,这只是一次性使用情况。谢谢。
您可以通过将enableCsrfCookie
组件的yii\web\Request
属性设置为false
来强制应用程序将CSRF令牌存储在会话中,而不是cookie中。您可以在web.php配置中执行此操作:
$config = [
// ...
'components' => [
'request' => [
'enableCsrfCookie' => false,
],
// ...
],
// ...
];
但这会导致应用为每个请求启动会话。默认情况下,会话也使用cookie来存储会话ID,因此,如果您想避免使用任何cookie,最终可能不会有太大的改善。]
您还可以扩展yii\web\Request
并覆盖其方法generateCsrfToken()
和loadCsrfToken()
以对令牌使用不同的存储。但是请记住,默认情况下无法识别来自同一会话的请求。您必须将某种sessionId保存在客户端中,然后将其发送回服务器,以便能够将提交表单的请求与CSRF令牌和生成CSRF令牌的请求配对。
另一种可能性是关闭标准CSRF保护并实施您自己的形式保护。例如,您可以在应用程序配置中存储一些密钥。然后,在生成表单时,将使用yii\base\Security::hashData()
方法将时间戳添加到表单中:
$timestamp = Yii::$app->security->hashData(time(), $yourSecurityKey); Html::hiddenInput('my-csrf', $timestamp);
然后您可以在控制器操作中验证它:
$timestamp = Yii::$app->security->validateData(
Yii::$app->request->post('my-csrf'),
$yourSecurityKey
);
if ($timestamp === false || $timestamp < (time() - $timeLimitInSeconds)) {
//Do something when CSRF validation is not valid (for example throw bad request exception)
}
// continue form processing