iOS端Chrome浏览器中PHP POST请求重复执行问题求助
解决iOS端Chrome中PHP表单重复提交的问题
问题根源
这是iOS Chrome的会话恢复特性导致的:浏览器重启后会自动恢复之前的页面会话,包括已提交的POST请求链。即使你用了Post/Redirect/Get(PRG)模式,Chrome仍会误将POST请求标记为需要恢复的内容,进而重放请求导致重复插入。清空$_POST无效的原因是,Chrome重放的是原始POST请求数据,而非读取当前会话的$_POST变量。
简便解决方案
1. 用一次性令牌彻底阻断重复提交(最可靠)
生成唯一令牌存在Session中,表单提交时携带令牌,处理POST请求时验证令牌,验证通过后立即销毁令牌——即使Chrome重放POST,令牌已失效,不会执行插入逻辑。
表单页代码示例:
<?php session_start(); // 生成随机唯一令牌 $_SESSION['submit_token'] = bin2hex(random_bytes(16)); ?> <form method="post" action="submit.php"> <input type="hidden" name="token" value="<?php echo $_SESSION['submit_token']; ?>"> <!-- 其他表单字段 --> <button type="submit">提交</button> </form>
POST处理页(submit.php)代码示例:
<?php session_start(); $isValidRequest = $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['token']) && $_POST['token'] === $_SESSION['submit_token']; if ($isValidRequest) { // 执行MySQL插入操作 // ... unset($_SESSION['submit_token']); // 验证后立即销毁令牌 $_SESSION['success_msg'] = '插入成功'; header('Location: index.php', true, 303); exit(); } else { // 非法/重复请求,直接跳首页 header('Location: index.php', true, 303); exit(); }
2. 配合303状态码强化PRG模式
将默认的302重定向改为**303(See Other)**状态码,明确告知浏览器后续用GET请求获取页面,不要保留POST请求的上下文:
header('Location: index.php', true, 303); exit();
3. 添加缓存禁止头(辅助优化)
在POST处理页和首页添加缓存控制头,阻止Chrome缓存请求状态,减少会话恢复时重放请求的概率:
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); header("Pragma: no-cache"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
内容的提问来源于stack exchange,提问作者Andrew T
相关产品推荐
相关产品推荐

