PHP表单CSRF防护误判攻击,无法正常提交数据求助
问题根源及解决方案
你的代码每次请求页面(包括表单提交后的POST请求)都会重新生成CSRF令牌,导致提交时表单里的令牌和当前请求生成的$csrf_avoid不匹配,进而触发错误提示。此外代码缺少会话初始化的session_start(),会导致$_SESSION无法正常使用。
修正步骤:
- 必须在代码最开头调用
session_start()初始化会话 - 仅当会话中不存在CSRF令牌时才生成新的,避免每次请求都重置令牌
- 验证时使用会话中存储的令牌,而非当前请求重新生成的值
修正后的PHP代码:
<?php session_start(); // 初始化会话,必须放在最开头 // 仅当会话中没有令牌时生成新的 if (!isset($_SESSION['auth_token'])) { $_SESSION['auth_token'] = bin2hex(random_bytes(20)); } if (isset($_POST["save_entry"])) { // 使用会话中的令牌进行验证 if (!isset($_POST["auth_token"]) || $_POST["auth_token"] !== $_SESSION['auth_token']) { echo '<h1 class="error">Error: invalid form submission</h1><p>Your request was denied as this request could not be verified.</p>'; http_response_code(405); // 设置405状态码 exit(); } else { // 无CSRF攻击,执行后续逻辑 // 可选:验证成功后可以重置令牌,提升安全性 $_SESSION['auth_token'] = bin2hex(random_bytes(20)); } } ?>
修正后的HTML代码:
<input type="hidden" name="auth_token" value="<?php echo $_SESSION['auth_token']; ?>">
额外说明:
session_start()必须放在所有输出之前,否则会导致会话初始化失败- 验证成功后重置令牌可以避免令牌被重复使用,进一步提升安全性
内容的提问来源于stack exchange,提问作者amntago shifeg
相关产品推荐
相关产品推荐

