PHP简易联系表单反垃圾邮件优化方案求助
纯PHP反垃圾邮件优化方案
一、强化Session绑定的表单验证
机器人常绕过前端直接发送POST请求,通过Session绑定请求能有效拦截这类行为:
- 在表单生成页面初始化Session并生成随机令牌:
session_start(); // 标记表单有效状态 $_SESSION['form_valid'] = true; // 生成随机令牌 $_SESSION['form_token'] = bin2hex(random_bytes(16));
- 在表单中添加隐藏的令牌字段:
<input type="hidden" name="form_token" value="<?php echo $_SESSION['form_token']; ?>">
- 在邮件处理脚本中验证令牌与Session状态:
session_start(); // 验证表单有效性与令牌匹配 if (!isset($_SESSION['form_valid']) || !isset($_POST['form_token']) || $_POST['form_token'] !== $_SESSION['form_token']) { exit('无效请求'); } // 验证后销毁Session标记,防止重复提交 unset($_SESSION['form_valid']); unset($_SESSION['form_token']);
二、优化提交时长校验逻辑
单纯的最小时长校验不够,需同时限制最大时长,避免机器人长时间持有表单后提交:
- 表单加载时记录时间到Session:
session_start(); $_SESSION['form_load_time'] = time();
- 处理脚本中校验时间范围(示例:5秒~30分钟):
session_start(); $submit_interval = time() - $_SESSION['form_load_time']; if ($submit_interval < 5 || $submit_interval > 1800) { exit('请求超时或提交过快'); } unset($_SESSION['form_load_time']);
三、强化内容特征拦截
针对你提到的“SPAM”开头主题及垃圾邮件共性特征,添加精准拦截规则:
- 直接拦截主题以SPAM开头的提交:
$subject = trim($_POST['subject']); if (stripos($subject, 'SPAM') === 0) { exit('垃圾内容拦截'); }
- 拦截包含大量大写字母、异常链接的内容:
$message = $_POST['message']; // 拦截连续10个以上大写字母的内容 if (preg_match('/[A-Z]{10,}/', $message)) { exit('垃圾内容拦截'); } // 拦截包含3个及以上外部链接的内容 preg_match_all('/https?:\/\/\S+/', $message, $matches); if (count($matches[0]) >= 3) { exit('垃圾内容拦截'); }
- 校验内容长度合理性:
if (strlen($message) < 10 || strlen($message) > 10000) { exit('内容长度异常'); }
四、添加IP提交频率限制
限制同一IP在指定时间内的提交次数,降低垃圾邮件批量发送概率:
session_start(); $client_ip = $_SERVER['REMOTE_ADDR']; // 初始化提交计数Session if (!isset($_SESSION['submit_counts'])) { $_SESSION['submit_counts'] = []; } // 1小时内最多允许3次提交 $current_time = time(); $time_window = 3600; $max_submits = 3; if (isset($_SESSION['submit_counts'][$client_ip])) { $last_submit_time = $_SESSION['submit_counts'][$client_ip]['time']; $submit_count = $_SESSION['submit_counts'][$client_ip]['count']; if ($current_time - $last_submit_time < $time_window) { if ($submit_count >= $max_submits) { exit('提交过于频繁,请稍后重试'); } $_SESSION['submit_counts'][$client_ip]['count']++; } else { $_SESSION['submit_counts'][$client_ip] = ['count' => 1, 'time' => $current_time]; } } else { $_SESSION['submit_counts'][$client_ip] = ['count' => 1, 'time' => $current_time]; }
五、优化陷阱字段设计
普通隐藏字段易被机器人识别,改用迷惑性字段名提升拦截效果:
- 在表单中添加陷阱字段(用CSS隐藏,无需JS):
<div style="display:none;"> <label for="website">网站(请勿填写)</label> <input type="text" name="website" id="website"> </div>
- 处理脚本中检查陷阱字段:
if (!empty(trim($_POST['website']))) { exit('垃圾内容拦截'); }
六、强化HTTP请求合法性校验
通过请求头过滤非本站来源的提交(虽可伪造,但能增加机器人攻击成本):
$allowed_domains = ['your-domain.com', 'www.your-domain.com']; if (isset($_SERVER['HTTP_REFERER'])) { $referer_host = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST); if (!in_array($referer_host, $allowed_domains)) { exit('无效请求来源'); } }
七、严格校验表单字段格式
过滤格式异常的字段,拦截机器人自动填充的无效数据:
// 校验邮箱格式 $email = trim($_POST['email']); if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { exit('邮箱格式无效'); } // 校验姓名(仅允许字母、空格、部分特殊字符) $name = trim($_POST['name']); if (!preg_match('/^[a-zA-Z\s\-\']+$/', $name)) { exit('姓名格式无效'); }
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

