技术:Java-Web基础|生成图片验证码(一)

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类


1 验证码


1.1 什么是验证码?

我搜索百度,从百度百科中拿出来一段话:

验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类。


1.2 验证码的历史

验证码这个词最早是在2002年出现在卡内基梅隆大学。


1.3 验证码的作用

防止恶意破解密码、刷票、论坛灌水、刷页


1.4 验证码的分类

验证码整体来说分为五类,他们分别是

  • 静态图片内容验证码:一般都是输入一些随机码,形式上还可以有计算
  • Gif动画验证码:动态展示一些随机码,形式上还可以有计算
  • 手机短信验证码:发送短信随机验证码
  • 手机语音验证码:语音验证码,也可以让你读出一些随机码或计算结果
  • 视频验证码:点击视频中的一些随机码,计算结果

了解了验证码之后,我们开始手工实现一些验证码,当然你也可以使用一些已经封装好的工具来实现这个功能,例如Hutool、Google、Baidu、阿里等大佬们封装好的一些工具类直接实现验证码。


2 实现一个验证码

如果我们想要实现一个验证码,那么就得先要了解下验证码的实现原理以及代码实现。


2.1 验证码的原理

网页之间实现验证码大体上有如下步骤:

1)生成一个随机数

2)将随机数写入图片

3)将图片返回到网页

4)用户获取到图片信息,输入图片内容

5)用户提交内容,服务端验证内容的准确性


整体的流程,使用一张图可能会更形象些,大家可以在这图里面体会下。

image.png

这里简单使用“静态图片内容验证码”来作为一个实验例子,来实现我们需要的验证码功能。


2.1 生成一个随机码

生成一个随机码的步骤大体如下:

1)创建一个类RandImagesVerifCode

2)编写一个名叫randomString(String baseString, int length)的方法

3)测试实验


完整的代码如下:

packagecom.liuyc.tooljdk.image;
importjava.util.concurrent.ThreadLocalRandom;
/*** <p> Picture Verification Code </p>** @author Aion.Liu* @version v1.0.0* @description TODO* @since 2022/9/1 22:24*/publicclassRandImagesVerifCode {
publicstaticfinalStringBASE_NUMBER="0123456789";
publicstaticvoidmain(String[] args) {
StringresultCode=RandImagesVerifCode.randomString(BASE_NUMBER, 4);
System.out.println(resultCode);
    }
/*** 生成一个随机数* @param baseString 指定的源中获取随机数* @param length 获取随机数的个数* @return*/publicstaticStringrandomString(StringbaseString, intlength) {
if (baseString==null||baseString=="") {
return"";
        } else {
StringBuildersb=newStringBuilder(length);
if (length<1) {
length=1;
            }
intbaseLength=baseString.length();
for (inti=0; i<length; ++i) {
intnumber=ThreadLocalRandom.current().nextInt(baseLength);
sb.append(baseString.charAt(number));
            }
returnsb.toString();
        }
    }
// 将验证码写入到redispublicbooleanset(Stringkey, Objectvalue, longtime) {
try {
if (time>0L) {
// this.redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);            } else {
// this.set(key, value);            }
returntrue;
        } catch (Exceptionvar6) {
var6.printStackTrace();
returnfalse;
        }
    }
}

分步骤解析:

1、public static final String BASE_NUMBER = "0123456789";

这里是指定一个数据源头,也就是从这里面随机多少个数字出来。关于数据源头,这里可以任意指定。例如我们也可以指定字母数字组合

public static final String BASE_CHAR_NUMBER = "abcdefghijklmnopqrstuvwxyz0123456789";


2、public static String randomString(String baseString, int length)

这里是生成随机数的方法,有两个参数。参数的用途已经写在了代码中。长度我们一般使用4~5位,其他少了也不好,多了又太过于麻烦。


3、public boolean set(String key, Object value, long time)

将验证码写入到redis,这是redis的key以及值,当然,还需要设置这个验证码的时效,过期之后这个验证码就不可以再使用,需要我们重新获取。


2.2 将验证码写入一张图片

这个步骤比较简单

1)生成一张图片,将验证码写入图片

2)将图片写入到流中并返回

publicstaticvoidmain(String[] args) throwsIOException {
StringresultCode=RandImagesVerifCode.randomString(BASE_NUMBER, 4);
System.out.println(resultCode);
Stringbase64=RandImagesVerifCode.produceImage(resultCode);
System.out.println(base64);
    }
publicstaticStringproduceImage(StringresultCode) throwsIOException {
/*** 定义图形大小*/finalintWIDTH=105;
/*** 定义图形大小*/finalintHEIGHT=35;
/*** 定义干扰线数量*/finalintCOUNT=200;
/*** 干扰线的长度=1.414*lineWidth*/finalintLINE_WIDTH=2;
/*** 生成一张图片,将结果写入到图片*/// 在内存中创建图象finalBufferedImageimage=newBufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 获取图形上下文finalGraphics2Dgraphics= (Graphics2D) image.getGraphics();
// 设定背景颜色graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, WIDTH, HEIGHT);
// 设定边框颜色graphics.drawRect(0, 0, WIDTH-1, HEIGHT-1);
finalRandomrandom=newRandom();
// 随机产生干扰线,使图象中的认证码不易被其它程序探测到for (inti=0; i<COUNT; i++) {
finalRandomrandomColor=newRandom();
finalintr=150+randomColor.nextInt(50);
finalintg=150+randomColor.nextInt(50);
finalintb=150+randomColor.nextInt(50);
graphics.setColor(newColor(r, g, b));
// 保证画在边框之内finalintx=random.nextInt(WIDTH-LINE_WIDTH-1) +1;
finalinty=random.nextInt(HEIGHT-LINE_WIDTH-1) +1;
finalintxl=random.nextInt(LINE_WIDTH);
finalintyl=random.nextInt(LINE_WIDTH);
graphics.drawLine(x, y, x+xl, y+yl);
        }
// 取随机产生的认证码for (inti=0; i<resultCode.length(); i++) {
// 设置字体颜色graphics.setColor(Color.BLACK);
// 设置字体样式graphics.setFont(newFont("Times New Roman", Font.BOLD, 24));
// 设置字符,字符间距,上边距graphics.drawString(String.valueOf(resultCode.charAt(i)), (23*i) +8, 26);
        }
// 图象生效graphics.dispose();
/*** 将图片写图图片流中*/ByteArrayOutputStreambyteStream=newByteArrayOutputStream();
//写入流中ImageIO.write(image, "JPEG", byteStream);
//转换成字节byte[] bytes=byteStream.toByteArray();
//转换成base64串Stringbase64=Base64.getEncoder().encodeToString(bytes).trim();
//删除 \r\nbase64=base64.replaceAll("\n", "").replaceAll("\r", "");
return"data:image/jpg;base64,"+base64;
    }


执行后的结果如下:

4408


data:image/jpg;base64,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


我们可以使用任意编写一个Html,然后将返回的数据写入img标签的src中,

<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body><imgsrc="data:image/jpg;base64,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"/></body></html>


打开网页后调试下结果如下结果。

image.png

现在,我们便完成了网页验证码的开发以及回显示到网页中啦。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
安全 前端开发 Java
10:基于Servlet模拟用户登录功能的实现与解析-Java Web
10:基于Servlet模拟用户登录功能的实现与解析-Java Web
106 3
|
Java
JAVA万能:JNLP在浏览器上以WEB方式运行JAVA程序
JAVA万能:JNLP在浏览器上以WEB方式运行JAVA程序
325 0
|
前端开发 Java 应用服务中间件
Java Web 动漫小项目(未完成,希望有缘人可以继续将其完成)
Java Web 动漫小项目(未完成,希望有缘人可以继续将其完成)
92 0
Java Web 动漫小项目(未完成,希望有缘人可以继续将其完成)
|
前端开发 Java 数据库连接
Java Web 动漫小项目
Java Web 动漫小项目
97 0
Java Web 动漫小项目
|
人工智能 算法 安全
技术:Java-Web基础|生成图片验证码(二)
验证码(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类
技术:Java-Web基础|生成图片验证码(二)
|
Java
Java Web 通过session实现一次性验证码
Java Web 通过session实现一次性验证码
147 0
|
存储 JavaScript NoSQL
【Web】Java生成中文GIF动态验证码-集成SpringMVC
【Web】Java生成中文GIF动态验证码-集成SpringMVC
334 0
【Web】Java生成中文GIF动态验证码-集成SpringMVC
|
Java 数据安全/隐私保护
java验证码开发示例
java验证码开发示例
90 0
|
Java 关系型数据库 MySQL
Java Web简明教程–Servlet篇[3]–获取网页数据
上篇讲了网页可以通过get或post方式向Servlet抛出请求,有时候呢,请求是带参数的。比如网页端想查询三班所有学生姓名,那么这个请求传递给Servlet处理时候,就要携带一个“三班”的参数信息,Servlet根据"三班"来返回该班学生姓名。所以,本篇主要内容:
282 0
Java Web简明教程–Servlet篇[3]–获取网页数据
|
Web App开发 Java 应用服务中间件
Java Web简明教程–网页篇[2]–基本标签
Java Web简明教程–网页篇[2]–基本标签
251 0