0

0

API 交互中怎么做好图片验证码

步履不停

步履不停

发布时间:2019-06-18 16:20:03

|

3633人浏览过

|

来源于php中文网

原创

API 交互中怎么做好图片验证码

前言

在传统的 Web 开发过程中,处理图形验证码很简单,只需要在后台用随机字符串生成一个图片,将验证码内容放进 Session 即可,用户提交表单时从 Session[1] 取出判断即可。

但是现如今,越来越推崇 API 交互,无状态,在 Session 这一块,虽然默认配置是不支持了,但是还是有很多曲线救国的方法。

基于 Session 实现

在 API 开发中,我们也可以给前端签发 SessionID ,并且通过 PHP 的内置方法,来实现这一切。
比如 我们与前段约定,当在请求中包含有 X-Session-Id ,且不为空时,表示这个会话已经注册过 SessionID ,否则就颁布一个 SessionID 并返回在 Response Header 中的 X-Session-Id 让前段记录这个 SessionID ,下面简单实现一下。

// 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();

上面基本实现了生成图片,前端需要根据 只需要再提交表单时,在 headers 中带上 X-Session-ID 即可。

// 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']);

上面使用 Session ,我们基本就实现了一个简单的验证,而且是基于 API 交互的,不依赖浏览器 cookie 。当我们需要一些复杂的比如共享  Session ,这些就不在本文的讨论范围了(其实现在也已经超纲了)

基于客户端主动签发

接下来的方法是无状态的,但是需要用到 Redis 。这里使用 PHPRedis 这个扩展来处理。

在大多数情况下,我们并不需要像上面使用 Session 那样来创建过多的 Session ,造成有一些资源浪费,当然,Session 可以做的不止这些,下面我们就用 Redis 来做一个客户端主动签发图片验证码

理论原理

由客户端本地生成随机字符串,然后拼接在获取验证码地址的后面,后端截取客户端生成的随机字符串,用此作为验证凭证放入 Redis 中去,再客户端提交时需要带上先前生成的随机字符串一同进项验证。

// 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();

好了,接下来验证一下。

// 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);

看着是不是要复杂点儿,甚至还用上了 Redis ,虽然看着不咋地,但是他也实现了我们想要的,不过这个也不算是太好的方案,而且,还要考虑客户端字符串不够随机的情况,接下来我们改变一下方向,换成服务端签发。

基于服务端签发

刚刚的是基于客户端签发的实现,下面来提供另一种思路,但是大体上,这个是差不多的哈都。

OmniAudio
OmniAudio

OmniAudio 是一款通过 AI 支持将网页、Word 文档、Gmail 内容、文本片段、视频音频文件都转换为音频播客,并生成可在常见 Podcast ap

下载

理论原理

同样是签发 Sign ,只不过这次由服务端来签发,然后将 Sign 通过 Header 发送给客户端,客户端需要先取到图片资源,注意这里返回的应该是一个合法的二进制流,然后从 header 中取出 Sign ,同时展示给用户。

// 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();

看起来几乎没有变化,只是生成 Sign 的方式变了一下,但是,这样搞的话,前端同学可能就不爽了,他们要先获取这个资源和 headers 中的 X-Captcha-Sign 再 show 到界面上,当然 可以直接将结果 base64 或者 直接用用二进制流生成位图显示都是可以的,我们只是需要可以验证,验证方法直接使用上面的即可。

特别注意

当你使用 ajax 获取这个资源是,如果你的业务涉及到了跨域,你还需要在响应头设置 Access-Control-Expose-Headers - HTTP | MDN,否则 ajax 无法获取自定义的响应头。。

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

总结

看了这三种解决方案,基本都能满足我们的需求,可能还有人想到了另一种方案。提供一个 json 接口名,在后台生成图片然后保存起来,返回 url 和 sign  给前端,这样就好了,但是这样做,我们的资源并不太可控,会造成一定的资源浪费,这里我并没有考虑 这种方案。

文中所提到的一些知识都是对一些基础知识的应用,文章中的代码是写文章直接敲的,如果有排版错误或者逻辑错误,请不吝赐教。

文中所用到的 Redis 为 PHPRedis 扩展。至于验证码图片生成可以用 gregwar/captcha - Packagist 来做哟。

以上只是我个人的一些理解,如果你有更好的方案,不妨一起分享。

参考

PHP: Sessions - Manual

[注1] 本文中所提到的 Session 为一种技术标准和和我们常说的通过浏览器自动传递 Cookie 交互中的 Session 有一定概念却别,这里只是自己手动实现了 SessionID的传递 ,但是始终保持 Session 的直译语义 “会话”。

更多PHP相关技术文章,请访问PHP教程栏目进行学习!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

457

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

549

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

337

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

82

2025.09.10

ajax教程
ajax教程

php中文网为大家带来ajax教程合集,Ajax是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。php中文网还为大家带来ajax的相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

166

2023.06.14

ajax中文乱码解决方法
ajax中文乱码解决方法

ajax中文乱码解决方法有设置请求头部的字符编码、在服务器端设置响应头部的字符编码和使用encodeURIComponent对中文进行编码。本专题为大家提供ajax中文乱码相关的文章、下载、课程内容,供大家免费下载体验。

170

2023.08.31

ajax传递中文乱码怎么办
ajax传递中文乱码怎么办

ajax传递中文乱码的解决办法:1、设置统一的编码方式;2、服务器端编码;3、客户端解码;4、设置HTTP响应头;5、使用JSON格式。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

124

2023.11.15

ajax网站有哪些
ajax网站有哪些

使用ajax的网站有谷歌、维基百科、脸书、纽约时报、亚马逊、stackoverflow、twitter、hacker news、shopify和basecamp等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

260

2024.09.24

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.9万人学习

微信小程序开发之API篇
微信小程序开发之API篇

共15课时 | 1.3万人学习

Laravel---API接口
Laravel---API接口

共7课时 | 0.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号