用PHP构建自己的验证码和联系表

人们每天都会编写代码来自动化各种流程。 我们利用计算机比人类更快,更准确的事实,这使我们简化了许多平凡的任务。 不幸的是,这些相同的功能可用于对计算机进行编程以执行恶意操作,例如发送垃圾邮件或猜测密码。 本教程的重点是打击垃圾邮件。

假设您有一个带有联系表的网站,以方便访问者与您联系。 他们所需要做的就是填写表格,然后点击发送按钮,让您知道问题或要求。 这是面向公众的网站的一项重要功能,但是恶意用户可以自动填写表单值,从而以自己的方式发送大量垃圾邮件。 这种类型的垃圾邮件发送技术不仅限于联系表格。 僵尸程序还可用于在您的论坛中填充垃圾邮件或链接到有害网站的评论。

解决此问题的一种方法是设计一种测试,以区分试图散布垃圾邮件的漫游器和有意与您联系的人。 这就是CAPTCHA的用处。它们通常由在彩色背景上书写的带有五个或六个字母的随机组合的图像组成。 这个想法是,人类将能够读取图像中的文本,而机器人则不能。 将用户填写的验证码值与原始值进行比较,可以帮助您区分机器人与人类。 CAPTCHA代表“完全自动化的公共Turing测试,以区分计算机和人类”。

在本教程中,我们将学习如何创建自己的验证码,然后将其与在教程中创建的联系表集成。

创建验证码

我们将使用PHP GD库创建我们的验证码。 您可以在我的较早的教程之一中了解有关使用GD编写文本和绘制形状的更多信息。 我们还必须编写一些代码来创建要在创建的图像上写入的随机字符串。 另一个名为“ 在PHP中生成随机字母数字字符串 ”的教程可以在这方面帮助我们。

产生随机字串

本节中的所有代码将放入captcha.php文件中。 让我们开始编写函数以创建随机字符串。

<?php

$permitted_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
 
function generate_string($input, $strength = 5) {
    $input_length = strlen($input);
    $random_string = '';
    for($i = 0; $i < $strength; $i++) {
        $random_character = $input[mt_rand(0, $input_length - 1)];
        $random_string .= $random_character;
    }
 
    return $random_string;
}

$string_length = 6;
$captcha_string = generate_string($permitted_chars, $string_length);


?>

$permitted_chars变量存储我们要用于生成验证码字符串的所有字符。 我们仅在英文字母中使用大写字母,以避免由于字母或数字看起来相似而引起的任何混淆。 您可以使用任何喜欢的字符集来增加或减少验证码的难度。

我们的函数默认情况下会创建一个由五个字母组成的字符串,但是您可以通过将另一个参数传递给generate_string()函数来更改该值。

渲染验证码背景

有了随机字符串后,就该编写代码以创建CAPTCHA图像的背景了。 图像大小为200 x 50像素,并将使用五种不同的颜色作为背景。

<?php

$image = imagecreatetruecolor(200, 50);

imageantialias($image, true);

$colors = [];

$red = rand(125, 175);
$green = rand(125, 175);
$blue = rand(125, 175);

for($i = 0; $i < 5; $i++) {
  $colors[] = imagecolorallocate($image, $red - 20*$i, $green - 20*$i, $blue - 20*$i);
}

imagefill($image, 0, 0, $colors[0]);

for($i = 0; $i < 10; $i++) {
  imagesetthickness($image, rand(2, 10));
  $rect_color = $colors[rand(1, 4)];
  imagerectangle($image, rand(-10, 190), rand(-10, 10), rand(-10, 190), rand(40, 60), $rect_color);
}

?>

我们从变量$red$green$blue随机值开始。 这些值确定图像背景的最终颜色。 之后,我们运行一个for循环以创建逐渐变暗的原始颜色阴影。 这些颜色存储在数组中。 最浅的颜色是$colors数组的第一个元素,最暗的颜色是最后一个元素。 最浅的颜色用于填充图像的整个背景。

下一步,我们使用for循环在原始图像上的随机位置绘制矩形。 矩形的厚度在2到10之间变化,而颜色是从$colors数组的最后四个值中随机选择的。

绘制所有这些矩形会为背景添加更多颜色,这使得将CAPTCHA字符串的前景与图像背景区分开来变得更加困难。

您的CAPTCHA背景现在看起来应该类似于下图。

PHP中的CAPTCHA背景

呈现CAPTCHA字符串

对于最后一步,我们只需要在背景上绘制CAPTCHA字符串。 随机确定各个字母的颜色,y坐标和旋转度,以使CAPTCHA字符串难以阅读。

<?php

$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);
$textcolors = [$black, $white];

$fonts = [dirname(__FILE__).'\fonts\Acme.ttf', dirname(__FILE__).'\fonts\Ubuntu.ttf', dirname(__FILE__).'\fonts\Merriweather.ttf', dirname(__FILE__).'\fonts\PlayfairDisplay.ttf'];

$string_length = 6;
$captcha_string = generate_string($permitted_chars, $string_length);

for($i = 0; $i < $string_length; $i++) {
  $letter_space = 170/$string_length;
  $initial = 15;
  
  imagettftext($image, 20, rand(-15, 15), $initial + $i*$letter_space, rand(20, 40), $textcolors[rand(0, 1)], $fonts[array_rand($fonts)], $captcha_string[$i]);
}

header('Content-type: image/png');
imagepng($image);
imagedestroy($image);

?>

如您所见,我使用从Google下载的某些字体来获取字符的变化。 图像两边都有15个像素的填充。 剩余的170个像素空间在所有验证码字母之间平均分配。

将文本字符串呈现在背景上方之后,结果应类似于下图。 字符将有所不同,但应略微旋转并混合使用黑白。

验证码背景与文本

将CAPTCHA添加到我们的联系表中

现在我们已经创建了验证码,是时候将其添加到我们的联系表中了。 我们将使用我之前的教程中的联系表,该联系表是关于如何创建PHP联系表并在“ 发送消息”按钮上方添加CAPTCHA的。

我们将使用会话来存储验证码文本,然后验证网站访问者输入的文本。 这是我们的captcha.php文件的完整代码:

<?php

session_start();

$permitted_chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ';
 
function generate_string($input, $strength = 10) {
    $input_length = strlen($input);
    $random_string = '';
    for($i = 0; $i < $strength; $i++) {
        $random_character = $input[mt_rand(0, $input_length - 1)];
        $random_string .= $random_character;
    }
 
    return $random_string;
}

$image = imagecreatetruecolor(200, 50);

imageantialias($image, true);

$colors = [];

$red = rand(125, 175);
$green = rand(125, 175);
$blue = rand(125, 175);

for($i = 0; $i < 5; $i++) {
  $colors[] = imagecolorallocate($image, $red - 20*$i, $green - 20*$i, $blue - 20*$i);
}

imagefill($image, 0, 0, $colors[0]);

for($i = 0; $i < 10; $i++) {
  imagesetthickness($image, rand(2, 10));
  $line_color = $colors[rand(1, 4)];
  imagerectangle($image, rand(-10, 190), rand(-10, 10), rand(-10, 190), rand(40, 60), $line_color);
}

$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);
$textcolors = [$black, $white];

$fonts = [dirname(__FILE__).'\fonts\Acme.ttf', dirname(__FILE__).'\fonts\Ubuntu.ttf', dirname(__FILE__).'\fonts\Merriweather.ttf', dirname(__FILE__).'\fonts\PlayfairDisplay.ttf'];

$string_length = 6;
$captcha_string = generate_string($permitted_chars, $string_length);

$_SESSION['captcha_text'] = $captcha_string;

for($i = 0; $i < $string_length; $i++) {
  $letter_space = 170/$string_length;
  $initial = 15;
  
  imagettftext($image, 24, rand(-15, 15), $initial + $i*$letter_space, rand(25, 45), $textcolors[rand(0, 1)], $fonts[array_rand($fonts)], $captcha_string[$i]);
}

header('Content-type: image/png');
imagepng($image);
imagedestroy($image);
?>

您要使用的字体将进入fonts目录。 现在,您只需在我们之前的有关使用HTML和PHP创建联系表单的教程的“ 发送消息”按钮上方添加以下HTML代码。

<div class="elem-group">
    <label for="captcha">Please Enter the Captcha Text</label>
    <img src="captcha.php" alt="CAPTCHA" class="captcha-image"><i class="fas fa-redo refresh-captcha"></i>
    <br>
    <input type="text" id="captcha" name="captcha_challenge" pattern="[A-Z]{6}">
</div>

有时,甚至对于人类来说,CAPTCHA文本也很难阅读。 在这种情况下,我们希望他们能够以用户友好的方式请求新的验证码。 上方的重做图标可以帮助我们做到这一点。 您所要做的就是将下面JavaScript与联系表单HTML添加在同一页面上。

var refreshButton = document.querySelector(".refresh-captcha");
refreshButton.onclick = function() {
  document.querySelector(".captcha-image").src = 'captcha.php?' + Date.now();
}

将CAPTCHA集成到表单中并添加刷新按钮后,您将获得一个如下图所示的表单。

PHP与CAPTCHA的联系表

我们与联系表单创建的CAPTCHA集成的最后一步涉及在填写表单并将其与会话中存储的值进行匹配时,检查用户输入的CAPTCHA值。 更新上一教程中的contact.php文件以具有以下代码。

<?php

session_start();

if($_POST) {
    $visitor_name = "";
    $visitor_email = "";
    $email_title = "";
    $concerned_department = "";
    $visitor_message = "";

    if(isset($_POST['captcha_challenge']) && $_POST['captcha_challenge'] == $_SESSION['captcha_text']) {
    
        if(isset($_POST['visitor_name'])) {
            $visitor_name = filter_var($_POST['visitor_name'], FILTER_SANITIZE_STRING);
        }
        
        if(isset($_POST['visitor_email'])) {
            $visitor_email = str_replace(array("\r", "\n", "%0a", "%0d"), '', $_POST['visitor_email']);
            $visitor_email = filter_var($visitor_email, FILTER_VALIDATE_EMAIL);
            
        }
        
        if(isset($_POST['email_title'])) {
            $email_title = filter_var($_POST['email_title'], FILTER_SANITIZE_STRING);
        }
        
        if(isset($_POST['concerned_department'])) {
            $concerned_department = filter_var($_POST['concerned_department'], FILTER_SANITIZE_STRING);
        }
        
        if(isset($_POST['visitor_message'])) {
            $visitor_message = htmlspecialchars($_POST['visitor_message']);
        }
        
        if($concerned_department == "billing") {
            $recipient = "billing@domain.com";
        }
        else if($concerned_department == "marketing") {
            $recipient = "marketing@domain.com";
        }
        else if($concerned_department == "technical support") {
            $recipient = "tech.support@domain.com";
        }
        else {
            $recipient = "contact@domain.com";
        }
        
        $headers  = 'MIME-Version: 1.0' . "\r\n"
        .'Content-type: text/html; charset=utf-8' . "\r\n"
        .'From: ' . $visitor_email . "\r\n";
        
        if(mail($recipient, $email_title, $visitor_message, $headers)) {
            echo '<p>Thank you for contacting us. You will get a reply within 24 hours.</p>';
        } else {
            echo '<p>We are sorry but the email did not go through.</p>';
        }
    } else {
        echo '<p>You entered an incorrect Captcha.</p>';
    }
    
} else {
    echo '<p>Something went wrong</p>';
}

?>

我们更新了此文件,以首先检查会话中存储的CAPTCHA值是否与用户输入的值相同。 如果他们不同,我们只是告诉访客他们输入了错误的验证码。 您可以根据项目需求来处理不同情况。

最后的想法

在本教程中,我们从头开始用PHP创建了自己的CAPTCHA,并将其与我们在较早的教程之一中构建的PHP联系人表单集成在一起。 我们还通过添加刷新按钮使CAPTCHA更加用户友好,以便用户在不可读的情况下获得具有新背景的新字符串。

您还可以使用本教程中的逻辑来创建一个CAPTCHA,该CAPTCHA依赖于求解基本数学方程式(例如加法和减法)。

如果要向网站添加CAPTCHA,则应查看CodeCanyon提供的一些表单和CAPTCHA插件。 其中一些具有CAPTCHA和许多其他功能,例如内置的文件上传器。

翻译自: https://code.tutsplus.com/tutorials/build-your-own-captcha-and-contact-form-in-php--net-5362

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值