PHP网站联系表单遭垃圾邮件攻击,求无UI影响的解决方案
解决垃圾邮件机器人突破简易加法验证码的问题
看起来你的简易加法验证码失效是因为机器人能轻松读取到页面里的隐藏字段值——你把sec1和sec2直接放在了隐藏输入框里,还在页面上输出了完整的算式,现在的垃圾机器人完全能解析HTML拿到这两个数字,自动算出结果提交。下面给你几个不用大改UI就能解决的方案:
方案1:用Session存储验证码数值(最有效且改动小)
核心思路是:不在前端传递真实的两个数字,而是把它们存在服务器端的Session里,前端只显示算式,后端验证时从Session取数对比。这样机器人拿不到真实的计算基数,就没法自动生成正确答案。
修改前端代码:
<?php session_start(); // 必须放在页面最顶部 $_SESSION['sec1'] = rand(0,9); // 改成一位数,简化用户输入,不影响防御效果 $_SESSION['sec2'] = rand(0,9); ?> <div id="leftpanel"> <div align="justify" class="graypanel"> <img src="images/computer.jpg"/> <br><hr> <form action="thankyou.php" method="POST" > <fieldset><legend>Get in touch</legend> <input type="text" name="name" placeholder="Your Name" class="formdata"> <input type="text" name="email" placeholder="Your Email" class="formdata"> <select name="business" class="formdata"> <option value="Business Not Disclosed">-------Select Business-------</option> <option value="llp">LLP</option> <option value="inc">Inc</option> <option value="privateLimited">Private Limited</option> <option value="publicLimited">Public Limited</option> <option value="proprietor">Proprietor</option> <option value="startup">Startup</option> </select> <input type="text" name="ans" placeholder="Captcha : <?php echo $_SESSION['sec1']; ?>+<?php echo $_SESSION['sec2']; ?>=?"><br><br> <input type="hidden" name="trigger" value="true"> <!-- 删掉原来的sec1和sec2隐藏字段,不再传递给前端 --> <input type="submit" value="submit" class="submit"> </fieldset> </form> </div> </div>
修改thankyou.php的验证逻辑:
<?php session_start(); if(isset($_POST['trigger']) && $_POST['trigger'] == 'true'){ // 先验证验证码 $user_ans = intval($_POST['ans']); $correct_ans = $_SESSION['sec1'] + $_SESSION['sec2']; if($user_ans != $correct_ans){ // 验证码错误,跳回表单页或提示错误 header("Location: your_form_page.php?error=invalid_captcha"); exit; } // 验证码正确,继续处理邮件发送逻辑... // 验证完成后销毁session里的验证码,防止重复提交 unset($_SESSION['sec1'], $_SESSION['sec2']); } ?>
方案2:添加蜜罐字段(完全不影响UI,辅助防御)
这是一种对用户完全透明的防御手段:在表单里加一个隐藏的输入字段,人类看不到,但垃圾机器人会自动填充它。后端只要检查这个字段是否有值,有值就判定为机器人,直接拒绝提交。
添加蜜罐字段到表单里:
<!-- 放在表单任意位置,用CSS强制隐藏 --> <input type="text" name="honeypot" style="display:none !important; visibility:hidden !important; position:absolute !important;" placeholder="Leave this blank">
在thankyou.php里验证:
if(!empty($_POST['honeypot'])){ // 机器人填了这个字段,直接终止处理 exit; }
这个方法可以和方案1结合使用,双重防御,效果会更好。
为什么原来的验证码失效?
你原来的实现把计算的两个数字直接暴露在HTML里(隐藏字段和页面显示的算式),现在的垃圾机器人已经能轻松解析HTML内容,提取sec1和sec2的值,自动计算出答案提交。把数值存在Session里,机器人就无法获取到真实的计算基数了。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

