PHP仅在联系表单页设置Cookie防篡改提交的配置咨询
你的需求非常明确,不需要复杂的防护方案,只要修正现有Cookie参数的配置问题,补上最基础的提交校验,就能完全满足要求。
现有代码参数修正
你代码里的expire、secure、httpOnly三个参数写的完全正确,不需要改,只需要调整path和domain两个参数:
$path不要写具体文件名,设置为/es/即可。这个参数是路径前缀匹配规则:如果写死/es/contacto.php,只有精确请求这个路径时浏览器才会携带Cookie,要是你后续把表单提交逻辑拆分到同目录下的其他处理脚本,就会出现提交时读不到Cookie的问题;设置为/es/之后,只有/es/目录下的请求会携带这个Cookie,其他目录的纯信息展示页完全不会收到这个Cookie,正好符合你不想给其他页面加Cookie的要求。$domain就保留www.mydomain.com,绝对不要写带路径/文件名的完整URL。Cookie的domain属性只支持匹配域名,不支持路径级别的配置,你要是写www.mydomain.com/es/contacto.php,浏览器会直接忽略这个配置,导致Cookie设置失效。
注意:HttpOnly属性只能阻止前端JS读取、修改Cookie,没法完全阻止恶意用户手动构造请求时伪造Cookie值。你现在把Cookie值写死成
spanish-visitor是有漏洞的,攻击者知道这个固定值之后,根本不需要访问表单页就能直接构造请求刷提交。
必须补充的防绕过校验
要实现「必须先访问表单页才能提交」的效果,只要把固定Cookie值改成随机一次性令牌,加个服务端校验就行,不需要额外引入复杂系统:
- 用户首次访问表单页时,生成一个随机不可预测的令牌,把这个令牌同时存到Cookie和服务端临时存储里(你没有登录系统,用PHP自带的session存最方便,过期时间和Cookie保持一致设1小时即可)
- 处理表单提交时,先校验请求携带的Cookie值和服务端存的令牌是否一致、是否过期,校验不通过直接拒绝请求即可。
调整后可直接使用的代码如下:
<?php // 放在contacto.php文件最顶部 session_start(); // 首次访问表单页时设置Cookie if (!isset($_COOKIE['contacto'])) { $formToken = bin2hex(random_bytes(16)); // 生成随机令牌,不可被预测 $_SESSION['contact_token'] = $formToken; $_SESSION['contact_token_expire'] = time() + 3600; setcookie( 'contacto', $formToken, time() + 3600, '/es/', 'www.mydomain.com', isset($_SERVER['HTTPS']), true // 开启HttpOnly,前端JS无法篡改Cookie ); } // 表单提交时的校验逻辑 if ($_SERVER['REQUEST_METHOD'] === 'POST') { $isInvalid = ( !isset($_COOKIE['contacto']) || !isset($_SESSION['contact_token']) || $_SESSION['contact_token_expire'] < time() || $_COOKIE['contacto'] !== $_SESSION['contact_token'] ); if ($isInvalid) { http_response_code(403); exit('非法提交,请先访问联系表单页面填写内容'); } // 校验通过后再执行后续的发邮件、存留言等逻辑 } ?>
补充说明
- 如果你的表单提交逻辑就是写在
contacto.php本身,没有拆分到同目录其他文件,$path也可以精确设置为/es/contacto.php,这样Cookie的作用范围更小,安全性更高。 - 其他纯信息展示页不需要加任何Cookie相关代码,浏览器会自动根据path和domain规则判断是否携带Cookie,不会对其他页面造成影响。
内容的提问来源于stack exchange,提问作者limakid
相关产品推荐
相关产品推荐

