php gd 验证码_使用PHP和GD的简单验证码

php gd 验证码

sample image

By now, we’ve all encountered captcha images in online forms. Captchas are a necessary evil, and this article will teach you how they’re made.

到目前为止,我们都已经遇到了在线形式的验证码图像。 验证码是必不可少的恶魔,本文将教您如何制作。

Please note that while there are better, automatic third party solutions for captchas out there such as ReCaptcha, this tutorial aims merely to explain and demonstrate how such technology actually works. We won’t be explaining what captchas actually are, as it’s assumed to be common knowledge and already covered in greater detail elsewhere.

请注意,尽管目前有更好的,自动的验证码第三方解决方案,例如ReCaptcha,但本教程仅旨在说明和演示此类技术的实际工作原理。 我们不会解释验证码的实际含义,因为它是众所周知的常识,并且已经在其他地方进行了详细介绍。

绘制验证码 (Drawing captchas)

You must have the GD(Graphics Draw) library installed before proceeding. This library enables drawing of graphics and images through built-in PHP functions. To install it, run sudo apt-get install php5-gd or if on non-Ubuntu-based operating systems, follow instructions.

您必须先安装GD(图形绘制)库,然后再继续。 该库允许通过内置PHP函数绘制图形和图像。 要安装它,请运行sudo apt-get install php5-gd如果在非基于Ubuntu的操作系统上,请按照说明进行操作

Captchas are usually made up of 3 things – shape, distortion, and the text. We’ll follow the steps mentioned below:

验证码通常由三部分组成- 形状,变形和文本 。 我们将遵循以下提到的步骤:

  1. Display an empty image on the browser.

    在浏览器上显示空白图像。
  2. Create a shape.

    创建一个形状。
  3. Generate random lines.

    生成随机线。
  4. Generate random dots.

    生成随机点。
  5. Generate random text.

    生成随机文本。

The procedural style used in this article is present only because this is a proof of concept, and to keep the final file as simple as possible. In a real project, you would go OOP.

出现本文中使用的过程样式仅是因为这是一种概念证明,并且可以使最终文件尽可能简单。 在实际的项目中,您将进行OOP。

显示空白图片 (Display an empty image)

The image will be treated by HTML as if an external image is being displayed using the “img” tag. Two functions are used – one for creating the image and another for displaying.

HTML将对图像进行处理,就像使用“ img”标签显示外部图像一样。 使用了两种功能-一种用于创建图像,另一种用于显示。

<?php
session_start();
?>

    <title>demo.php</title>
    <body style="background-color:#ddd; ">

    <?php
    create_image();
    display();
    /***** definition of functions *****/
    function display()
    {
        ?>

        <div style="text-align:center;">
            <h3>TYPE THE TEXT YOU SEE IN THE IMAGE</h3>
            <b>This is just to check if you are a robot</b>

            <div style="display:block;margin-bottom:20px;margin-top:20px;">
                <img src="image.png">
            </div>
            //div1 ends
        </div>                          //div2 ends

    <?php
    }

    function  create_image()
    {
        $image = imagecreatetruecolor(200, 50);
        imagepng($image, "image.png");
    }

    ?>
    </body>
<?php
?>

The first line indicates the start of the user’s session on our page.

第一行表示我们页面上用户会话的开始。

The display() function has nothing other than a normal HTML code that displays an image in the browser. Other than that, only styling is done for the output to look presentable.

display()函数只不过是在浏览器中显示图像的普通HTML代码而已。 除此之外,仅对输出进行了样式设置,以使其看起来很美观。

Inside the create_image() function, a variable is used to refer the image returned by the imagecreatetruecolor() function which takes the width and length of the image as its arguments. imagepng() creates a png image of the specified name and path (in the same directory).

create_image()函数内部,使用变量来引用由imagecreatetruecolor()函数返回的图像,该函数将图像的宽度和长度作为其参数。 imagepng()创建具有指定名称和路径(在同一目录中)的png图像。

A black image will be the output after our first step.

第一步后,将输出黑色图像。

scrn1

Note that the function imagepng() will be the last line of our function and all the following steps are to be inserted in the create_image() function before this function call only, else they would not take effect.

请注意,函数imagepng()将是函数的最后一行,并且以下所有步骤仅在此函数调用之前插入到create_image()函数中,否则它们不会生效。

创建形状 (Create a shape)

Any shape can be chosen for the captcha. We’ll choose a rectangle by using the function imagefilledrectangle(). It takes five arguments – image reference, starting x-pos, starting y-pos, ending x-pos, ending y-pos, and the background color. You may use the corresponding function for an ellipse for generating elliptical captcha.

验证码可以选择任何形状。 我们将使用imagefilledrectangle()函数选择一个矩形。 它包含五个参数-图像参考,开始x-pos,开始y-pos,结束x-pos,结束y-pos和背景颜色。 您可以对椭圆使用相应的函数来生成椭圆验证码。

The imagecolorallocate() function allocates a color to a variable as it takes the RGB combination of the color as arguments. The following code is to be appended in the create() function.

imagecolorallocate()函数将颜色分配给变量,因为它将颜色的RGB组合作为参数。 以下代码将添加到create()函数中。

$background_color = imagecolorallocate($image, 255, 255, 255);  
imagefilledrectangle($image,0,0,200,50,$background_color);

The previous image will be white after this step.

在此步骤之后,先前的图像将为白色。

sample image

生成随机线。 (Generate random lines.)

Now, we actually start with making the distortion part of the captcha. In PHP, the lines are generated from the starting point(x1,y1) to the end point(x2,y2). Now as we want our lines to touch both ends of the box, we will keep the <x1,x2> coordinates as <0,200> i.e., the complete width of our box. The <y1,y2> coordinates will be randomly generated. This will create just one random line. We will generate multiple lines by putting this functionality inside a for loop.

现在,我们实际上开始使失真验证码的一部分。 在PHP中,从起点(x1,y1)到终点(x2,y2)生成线。 现在,当我们希望线条触及框的两端时,我们将<x1,x2>坐标保持为<0,200>即框的完整宽度。 <y1,y2>坐标将随机生成。 这将只创建一条随机线。 通过将此功能放在for循环中,我们将生成多行。

$line_color = imagecolorallocate($image, 64,64,64); 
for($i=0;$i<10;$i++) {
    imageline($image,0,rand()%50,200,rand()%50,$line_color);
}

The imageline() function takes the x1,x2,y1,y2 coordinates as arguments in that order apart from the image reference and color of the line. The line color has been allocated just as the background color had been allocated in the previous step.

imageline()函数以x1,x2,y1,y2坐标为参数,其顺序不同于图像参考和线条的颜色。 线条颜色的分配与上一步中分配的背景颜色一样。

The y-coordinate is given as rand()*%50 because this is the height of our box and will always return a value under 50. You may alternatively use rand(0,50). They will yield the same output range.

y坐标指定为rand()*%50因为这是我们盒子的高度,并且总是返回小于50的值。您也可以使用rand(0,50) 。 它们将产生相同的输出范围。

sample image

生成随机点。 (Generate random dots.)

Random dots will be generated in the same way as random lines. The function used is imagesetpixel(). This function takes the value of coordinates where the dot will be placed in the box.

随机点的生成方式与随机线相同。 使用的函数是imagesetpixel() 。 此函数获取将在框中放置点的坐标值。

$pixel_color = imagecolorallocate($image, 0,0,255);
for($i=0;$i<1000;$i++) {
    imagesetpixel($image,rand()%200,rand()%50,$pixel_color);
}

The x-coordinate is randomly generated by using rand()*%200 as this is the width of our box and this will always return a value under 200. You may alternatively use rand(0,200). They will yield the same output range. The y coordinate is generated as in the lines step.

x坐标是使用rand()*%200随机生成的,因为这是我们盒子的宽度,它将始终返回小于200的值。您也可以使用rand(0,200) 。 它们将产生相同的输出范围。 y坐标与line步骤中一样生成。

sample image

产生随机文字 (Generate random text)

We will randomly point to a position in the string (which contains the alphabet in both lower and upper case) and assign it to the variable $letter

我们将随机指向字符串中的某个位置(包含大小写字母),并将其分配给变量$letter

$letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$len = strlen($letters);
$letter = $letters[rand(0, $len-1)];

$text_color = imagecolorallocate($image, 0,0,0);

When put inside a loop, it looks like this-

当放入循环中时,它看起来像这样-

for ($i = 0; $i< 6;$i++) {
    $letter = $letters[rand(0, $len-1)];
    imagestring($image, 5,  5+($i*30), 20, $letter, $text_color);
    $word.=$letter;
}
$_SESSION['captcha_string'] = $word;

We will explain the lines

我们将解释线

$word.=$letter;
$_SESSION['captcha_string'] = $word;

in the next section.

在下一节中。

The function imagestring() writes the text in our image. It has 6 arguments:

函数imagestring()将文本写入我们的图像中。 它有6个参数:

  1. Image reference.

    图片参考。
  2. Font-size of the text (it can be 5 at most).

    文本的字体大小(最多可以为5)。
  3. x-coordinate (changing proportionally for every alphabet).

    x坐标(每个字母成比例地变化)。
  4. y-coordinate (kept the same, although we could change this randomly too).

    y坐标(保持不变,尽管我们也可以随机更改)。
  5. Actual string to be written.

    实际要写入的字符串。
  6. Font-color of the text.

    文本的字体颜色。

You can also use the function imagettftext() if you wish to have a bigger font and different font style. It takes 2 additional arguments for angle and font style of the text.

如果希望更大的字体和不同的字体样式,也可以使用函数imagettftext() 。 对于文本的角度和字体样式,它需要两个附加参数。

Calculation of x-coordinate is done by inspection. Roughly, the letters are spaced about 35 pixels (5+($i*30)) where $i=0,1,2,3,4,5,6. This is because if we had kept this value around 15-20px, there would have been a possibility of two letters overlapping. If the value had been more than 40px, the letters altogether would have not fit into the box.

x坐标的计算是通过检查完成的。 大致来说,字母间隔约35个像素(5+($i*30)) ,其中$i=0,1,2,3,4,5,6 。 这是因为,如果我们将此值保持在15-20px左右,则可能会有两个字母重叠。 如果该值大于40px,则字母将完全不适合该框。

This will generate a 6 alphabet captcha text. We can always create more randomness by changing the aspects that have been kept constant due to simplicity, like color, y-coordinates etc.

这将生成一个6个字母的验证码文本。 我们总是可以通过更改由于简单性而保持不变的方面(例如颜色,y坐标等)来创建更多的随机性。

The final captcha will look like this

最终的验证码将如下所示

sample image

The text written in the captcha will change every time you refresh the page. More randomness can be achieved by creating designs with the pixels or by changing the color or size.

每次刷新页面时,验证码中写入的文本都会更改。 通过使用像素创建设计或更改颜色或大小,可以实现更大的随机性。

证实 (Validating)

It is here that the user’s response is taken and after processing it, he/she receives a reply. At first, a simple form is made with an input textbox and a submit button. There can be many ways of processing a captcha as per the requirements of complex web applications. But keeping it simple for the sake of this example, we’ll process it on the same page.

在这里,接受用户的响应,并且在处理用户响应后,他/她将收到回复。 首先,使用输入文本框和提交按钮制作一个简单的表单。 根据复杂的Web应用程序的要求,可以有多种处理验证码的方法。 但是为了简单起见,为了简单起见,我们将在同一页面上对其进行处理。

The two lines left unexplained in the previous code snippets come into play now:

以前的代码片段中未解释的两行现在开始起作用:

  1. $word.=$letter; – the concatenation operator . is used to append all the individual letters one after another, generating the 6-letter word.

    $word.=$letter; –串联运算符. 用于一个接一个地附加所有单个字母,生成6个字母的单词。

  2. $_SESSION['captcha_string'] = $word; Our captcha string is stored in a session variable which will be used for validation purposes.

    $_SESSION['captcha_string'] = $word; 我们的验证码字符串存储在会话变量中,该变量将用于验证目的。

We’ll change the definition of display() to add a form-like structure.

我们将更改display()的定义以添加类似表单的结构。

Two submit buttons will be used, one to submit the string and another other to refresh the page.

将使用两个提交按钮,一个用于提交字符串,另一个用于刷新页面。

The following lines will be added in between the two closing div tags (see comments in the previous display() function)

以下行将添加在两个结束div标签之间(请参见上一个display()函数中的注释)

function display()
{
    ?>

    <div style="text-align:center;">
        <h3>TYPE THE TEXT YOU SEE IN THE IMAGE</h3>
        <b>This is just to check if you are a robot</b>

        <div style="display:block;margin-bottom:20px;margin-top:20px;">
            <img src="image<?php echo $_SESSION['count'] ?>.png">
        </div>
        <form action=" <?php echo $_SERVER['PHP_SELF']; ?>" method="POST"
        / >
        <input type="text" name="input"/>
        <input type="hidden" name="flag" value="1"/>
        <input type="submit" value="submit" name="submit"/>
        </form>

        <form action=" <?php echo $_SERVER['PHP_SELF']; ?>" method="POST">
            <input type="submit" value="refresh the page">
        </form>
    </div>

<?php
}

Before moving further we must know when to display and when not to display the input box. It will be displayed only

在继续之前,我们必须知道何时显示和何时不显示输入框。 仅显示

  1. if the page has just loaded.

    如果页面刚刚加载。
  2. if the user’s answer was incorrect.

    如果用户的答案不正确。

The first condition is met by using a $flag which is set to ‘1’ each time the submit button is clicked. Initially, it has been set to any other value. The second condition is achieved by checking if the value stored in our session variable is the same as user input (see the code below).

通过使用$flag满足第一个条件,该$flag每次单击提交按钮时都设置为“ 1”。 最初,它已设置为任何其他值。 通过检查存储在我们的会话变量中的值是否与用户输入相同(请参见下面的代码)来实现第二个条件。

To achieve this, we will replace the following lines of our starting step at the beginning of the article:

为此,我们将在本文开头替换开始步骤的以下几行:

create_image();
    display();

with:

与:

$flag = 5;

if (isset($_POST["flag"])) //  check that POST variable is not empty
{
    $input = $_POST["input"];
    $flag = $_POST["flag"];
}

if ($flag == 1) // submit has been clicked
{
    if (isset($_SESSION['captcha_string']) && $input == $_SESSION['captcha_string']) // user input and captcha string are same
    {

        ?>

        <div style="text-align:center;">
            <h1>Your answer is correct!</h1>

            <form action=" <?php echo $_SERVER['PHP_SELF']; ?>" method="POST"> // refresh the page
                <input type="submit" value="refresh the page">
            </form>
        </div>

    <?php

    } else // incorrect answer, captcha shown again
    {

        ?>
        <div style="text-align:center;">
            <h1>Your answer is incorrect!<br>please try again </h1>
        </div>
        <?php
        create_image();
        display();
    }

} else // page has just been loaded
{
    create_image();
    display();
}

Note that the functions create_image() and display() are called only as per the 2 conditions discussed above.

请注意,仅根据上述两个条件调用函数create_image()display()

We’ll need the session variable from the previous page, so the session is not destroyed here. The session will be automatically destroyed once the browser window is closed.

我们需要上一页中的session变量,因此此处的session不被破坏。 一旦关闭浏览器窗口,会话将被自动销毁。

The captcha will look like this-

验证码看起来像这样-

sample image

If the input is incorrect, only then user will be prompted again.

如果输入不正确,则仅会再次提示用户。

sample image

If the input is correct, user will be shown a message.

如果输入正确,将向用户显示一条消息。

sample image

There is a minor caveat – when the user presses the back button, any image already present in the cache of the browser will not reload, while the page does. In a POST request, browser back button will show a “document expired” page, but when the request is GET, the image does not regenerate.

需要注意的是,当用户按下“后退”按钮时,浏览器缓存中已经存在的任何图像都不会重新加载,而页面却会重新加载。 在POST请求中,浏览器后退按钮将显示“文档已过期”页面,但是当请求为GET时,图像不会重新生成。

The solution is simple – creating unique names of images every time, so that the browser doesn’t find them in cache. We will append a unique string returned to us by the built-in time() function to the image name while creating and while displaying in the browser.

解决方案很简单–每次创建唯一的图像名称,这样浏览器就不会在缓存中找到它们。 在创建和在浏览器中显示时,我们会将由内置time()函数返回的唯一字符串附加到图像名称。

Add this line just below where you started your session:

在开始会话的位置下方添加以下行:

$_SESSION['count']=time(); // unique string stored

Replace the img src tag in the display() function with

display()函数中的img src标记替换为

<img src="image<?php echo $_SESSION['count']?>.png">

And the part where we created the png image in create_image() function will also be replaced with

我们在create_image()函数中创建png图像的部分也将替换为

imagepng($image,"image".$_SESSION['count'].".png");

The images will now be called something like image39342015.png. This procedure will create images as many times as the page is refreshed which can waste huge amounts of disk space, so we’ll make sure that before creating an image, all other images of the png extension are deleted. Add the following just before the imagepng() function is called.

这些图像现在称为image39342015.png 。 此过程将在刷新页面时创建图像,这会浪费大量磁盘空间,因此,我们将确保在创建图像之前,删除所有其他具有png扩展名的图像。 在imagepng()函数之前添加以下内容。

$images = glob("*.png");
foreach($images as $image_to_delete)
{
    unlink($image_to_delete);      
}

In a production app, just make sure that you isolate the folder where captcha images are being stored else other useful images may get deleted too.

在生产应用中,只需确保隔离存储验证码图像的文件夹,否则其他有用的图像也可能会被删除。

Download the full code here.

此处下载完整代码。

结论 (Conclusion)

Making various types of captchas in PHP is very easy. This article covered the three basic things used for creating a standard captcha – shape, distortion, and text. This article was a proof of concept, and the code presented herein should not be used in production – especially since excellent alternatives such as ReCaptcha exist, which also supports sound output to help people with hearing impairments. We hope you found this article interesting. Leave your comments and feedback below!

在PHP中制作各种类型的验证码非常容易。 本文介绍了用于创建标准验证码的三个基本内容- 形状,变形和文本 。 本文是概念的证明,此处提供的代码不应在生产中使用-尤其是因为存在诸如ReCaptcha之类的出色替代产品,该产品还支持声音​​输出以帮助听力障碍的人。 我们希望您觉得这篇文章有趣。 在下面留下您的评论和反馈!

翻译自: https://www.sitepoint.com/simple-captchas-php-gd/

php gd 验证码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值