Home  >  Article  >  Backend Development  >  How to create image verification code in API interaction

How to create image verification code in API interaction

步履不停
步履不停Original
2019-06-18 16:20:033333browse

How to create image verification code in API interaction

Preface

In the traditional Web development process, processing graphical verification codes is very simple. You only need to generate an image with a random string in the background and add the verification code content. Just put it into the Session. When the user submits the form, take out the judgment from Session[1].

But nowadays, API interaction and statelessness are increasingly respected. In the Session area, although the default configuration is not supported, there are still many ways to save the country.

Session-based implementation

In API development, we can also issue SessionID to the front end and achieve all this through PHP's built-in methods.
For example, we agreed with the previous paragraph that when the request contains X-Session-Id and is not empty, it means that this session has already registered a SessionID. Otherwise, a SessionID will be issued and returned in the Response X-Session-Id in the Header allows the previous section to record this SessionID. Let’s simply implement it below.

// code_session.php
session_start();
// 这里假设已经通过 Header 获取到了 SessionID,并保存到了 $sessionId 变量中。
// 当 SessionID 不存在,或者 为空 则创建新的 SessionID 。
if(!isset($sessionId) || empty($sessionId)){
    $sessionId = session_create_id();
    // 因为前台还没有 SessionID ,所以下发一个,通知前端保存。
    header('X-Session-Id: '.$sessionId);
}
// 设置当前会话的 SessionID 。
session_id($sessionId);
// 这里我们就可以自由的读写 Session 了。
// 生成验证码
$code = mt_rand(1e3 ,1e4-1);
// create_image 请自行实现 或者使用现有的图形验证码库生成。
$image = create_image($code);
// 存储进去 Session
$_SESSION['code'] = $code;
// 输出一张图片
$image->output();

The above basically implements the generation of images. The front end only needs to add X-Session-ID to the headers when submitting the form.

// code_session_validate.php

session_start();
// 这里假设已经通过 Header 获取到了 SessionID,并保存到了 $sessionId 变量中。
// 当 SessionID 不存在,或者 为空 则创建新的 SessionID 。
if(
  !isset($sessionId) 
|| empty($sessionId) 
|| !isset($_POST['code']) 
|| empty($_POST['code'])
){
    // 因为没有提交 SessionID 过来 这个肯定就是不成立的了,所以直接终止即可。
    exit;
}
// 设置当前会话的 SessionID 。
session_id($sessionId);
if($_POST['code']!=$_SESSION['code']){
    // 验证码错误啦
    exit;
}
// 验证通过了就删掉 code,
unset($_SESSION['code']);

Using Session above, we have basically implemented a simple verification, which is based on API interaction and does not rely on browser cookies. When we need something complex, such as sharing Session, these are beyond the scope of this article (in fact, it is now beyond the scope)

Active signing based on the client

The next method is none Stateful, but requires the use of Redis. This is handled using the PHPRedis extension.

In most cases, we do not need to create too many Sessions like using Session above, resulting in some waste of resources. Of course, Session can do more than that. Let’s use Redis to do it below. A client actively issues 's image verification code.

Theoretical Principle

The client generates a random string locally, and then splices it behind the address to obtain the verification code. The backend intercepts the random string generated by the client and uses it as a verification certificate. Enter Redis, and when submitting it to the client, you need to bring the previously generated random string for verification.

// code_client.php
$salt = 'wertyujkdbaskndasda';
if(!isset($_GET['sign'])){
    // 客户端没有提供签名,停止执行
    exit;
}
// 用户传来的一切数据都是不可靠的,我们需要对其加盐后执行 md5
$sign = md5($_GET['sign'].$salt);
// 拼接上签名作为 Redis 的 key
$key = 'code:'.$sign;
// 连接 Redis 
$cache = new \Redis();
// 生成验证码
$code = mt_rand(1e3,1e4-1);
// 保存验证码到 Redis 并设置2分钟的有效期。
if($cache->exists($key)){
    // 这个 Key 已经被占用了,这里先停止。
    exit;
}
$cache->set($key,$code,60*2);
// 创建图片并返回
$image = create_image($code);
$image->output();

Okay, let’s verify it.

// code_client_validate.php
$salt = 'wertyujkdbaskndasda';
if(
!isset($_POST['sign'])
|| !isset($_POST['code']) // 没有提交验证码过来。
|| !empty($_POST['code'])
){
    // 客户端没有提供签名,停止执行
    exit;
}
// 用户传来的一切数据都是不可靠的,我们需要对其加盐后执行 md5
$sign = md5($_POST['sign'].$salt);
// 拼接上签名作为 Redis 的 key
$key = 'code:'.$sign;
// 连接 Redis 
$cache = new \Redis();

if(!$cache->exists($key)){
    // 根本没有这个 key
    eixt;
}

if($cache->get($key)!=$_POST['code']){
    // 验证码错误
}

// 验证通过了就删除

$cache->del($key);

It looks like it is a little more complicated, and even Redis is used. Although it doesn’t look good, it also achieves what we want, but this is not a very good solution. Moreover, we also need to consider that the client string is not random enough. Next, we change the direction and switch to server-side issuance.

Based on server-side issuance

What I just described is based on the implementation of client-side issuance. Here is another idea, but in general, this is almost the same.

Theoretical Principle

The same is true for signing a Sign, but this time it is signed by the server, and then the Sign is sent to the client through the Header. The client needs to get the image resource# first. ##, note that what is returned here should be a legal binary stream, then take out the Sign from the header and display it to the user.

// code_server.php
$cache = new \Redis();
$salt = 'wertyujkdbaskndasda';
function generateSign(){
    global $cache,$salt;
    $sign = md5(mt_rand().$salt);
    // 拼接上签名作为 Redis 的 key
    $key = 'code:'.$sign;
    if($cache->exists($key)){
        // 是的 你么有看错,就是如果生成的 Sign 已存在,就进行递归,直到生成出一个不存在的。
        return generateSign();
    }
    return $key;
}
// 连接 Redis 
$key = generateSign();
// 生成验证码
$code = mt_rand(1e3,1e4-1);
// 保存验证码到 Redis 并设置2分钟的有效期。
$cache->set($key,$code,60*2);
// 创建图片并返回
$image = create_image($code);
// 哈哈 要剃掉前缀哟
header('X-Captcha-Sign: ' . str_replace('code:','',$key));
$image->output();
It seems that there is almost no change, except that the way of generating Sign has changed. However, if this is done, the front-end students may be upset. They must first obtain this resource and

X- in the headers. Captcha-Sign Then show it on the interface. Of course, you can directly base64 the result or directly use the binary stream to generate a bitmap display. We just need to be able to verify it. The verification method can be directly used above.

Special attention

When you use ajax to obtain this resource, if your business involves cross-domain, you also need to set

Access-Control-Expose-Headers in the response header - HTTP | MDN, otherwise ajax cannot obtain the customized response header. .

header('Access-Control-Expose-Headers: X-Captcha-Sign');
Summary

After looking at these three solutions, they can basically meet our needs. Someone may have thought of another solution. Provide a json interface name, generate the image in the background and save it, return the url and sign to the front end, this is fine, but in this way, our resources are not very controllable, and it will cause a certain waste of resources. I have no idea here. Consider this option.

Some of the knowledge mentioned in the article is the application of some basic knowledge. The code in the article was typed directly when writing the article. If there are typographical errors or logical errors, please feel free to enlighten me.

The Redis used in this article is the PHPRedis extension. As for the verification code image generation, you can use

gregwar/captcha - Packagist.

The above are just some of my personal understandings. If you have a better solution, please share it.

Reference

PHP: Sessions - Manual

[Note 1] The Session mentioned in this article is a technical standard and has a certain concept but is different from what we often call the automatic transfer of Cookies through the browser. Here I just manually implement the transfer of SessionID. , but always maintain the literal translation semantics of Session "session".

For more PHP related technical articles, please visit the PHP Tutorial column to learn!

The above is the detailed content of How to create image verification code in API interaction. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn