SpringBoot实现图形验证码
写在前面
在实际生活中,我们经常会遇到在登陆的时候,需要输入图形验证码这样的场景,验证码不仅可以防止爬虫的抓取,还可以限制接口短时间内被访问的次数,可以说也是一种限流措施。本篇来学习如何在前后端分离架构下,基于SpringBoot实现图形验证码这一功能。
实战
项目初始化
第一步,新建一个名为verify-code的SpringBoot项目,并在其POM文件中添加如下依赖:
1 | <dependencies> |
创建状态枚举类
第二步,新建一个enums包,并在该包内新建一个名为RespCode的响应状态枚举类:
1 | public enum RespCode { |
创建响应状态类
第三步,新建entity包,并在该包内新建一个名为RespBean的响应状态类:
1 | public class RespBean<T> implements Serializable { |
Redis工具类
第四步,新建redis包,并在该包内新建一个名为RedisCache的工具类,该类封装了Redis对字符串类型的操作,即设置值和获取值:
1 | @Component |
第五步,在redis包内新建一个名为RedisConfig的配置类,该类用于重写Redis的序列化方式。一般来说我们更倾向于在SpringBoot中使用 Spring Data Redis来操作Redis,但是随着而来的则是它的序列化问题,默认使用的是JdkSerializationRedisSerializer,采用的是二进制方式,且会自动的给存入的key和value添加一些前缀,导致实际情况与开发者预想的不一致。针对这种情况我们可以使用Jackson2JsonRedisSerializer这一序列化方式,不建议使用StringRedisTemplate来替代RedisTemplate,因为它提供的数据类型和操作都有限,无法满足日常需要。
定义一个名为RedisConfig的类,该类用于重写RedisTempplate的序列化逻辑,使用Jackson2JsonRedisSerializer取代默认的JdkSerializationRedisSerializer,这样利于后续开发和使用:
1 | @Configuration |
修改配置文件
第六步,定义一个名为application.yml的配置文件,在里面定义Redis连接信息,同时自定义验证码的一些参数,如缓存中key前缀、验证码过期时间和验证码格式等信息:
1 | spring: |
读取配置文件
第七步,新建config包,并在该包内新建一个名为VerifyCodeConfig的属性配置类,该类用于将用户在application.yml配置文件中定义的配置项与VerifyCodeConfig这一属性POJO类进行映射:
1 | @Component |
创建验证码工具类
第八步,新建utils包,并在该包内新建一个名为CodeUtils的工具类,该类用于生成验证码及图片:
1 | public class CodeUtils { |
定义业务处理类
第九步,新建service包,并在该包内新建一个名为VerifyCodeService的业务类,该类用于生成验证码及校验用户输入的验证码是否准确:
1 | @Service |
简单解释一下上述代码的含义:
(1)定义generateVerifyCode()方法用于生成图形验证码,然后构建一个返回Map对象,接着构造图片key对象,这个需要在用户请求成功并返回验证码的时候一并携带过去,目的就是后续可以构造缓存key进而从缓存中取出生成的验证码并与用户输入提交的验证码进行对比,进而判断用户验证码是否输入正确;
(2)图片key对象这里比较简单,直接采用了时间戳,开发者还可以采用UUID或者其他分布式环境下能唯一标识请求的信息;
(3)然后调用mageIO.write()方法通过IO流形式将图片写入到ByteArrayOutputStream 中,并将其转成一个Base64字符串添加到返回Map对象中。当然如果你不是前后端分离的架构,可以将其存入Session中,然后从Session中通过session.getAttribute()方法来获取验证码字符串,而图片直接可通过前端显示在页面上;
(4)checkVerifyCode()方法就是从缓存中取出返给前端的图形验证码中的验证码字符串,然后与用户输入提交的字符串进行对比,如果校验通过,则说明验证码匹配成功,反之匹配失败。
定义业务控制器类
第十步,新建controller包,并在该包内新建一个名为VerifyCodeController的控制器类,该类用于提供生成验证码及校验用户输入验证码是否准确的API:
1 | @RestController |
运行项目进行测试
第十一步,启动项目,开始进行测试。打开Postman,按照图示进行操作:

可以看到接口返回了成功信息,但是用户无法直接看到生成的图形验证码,只能看到Base64字符串:
1 | { |
其实我们可以在Postman的Tests模块,从接口中取出返回的Base64字符串,然后构建HTML字符串模板,由于我们返回的Base64字符串中不包含data:image/jpg;base64,这段标志,因此需要在前面补上,最后将得到的信息设置到visualizer中:
1 | //1、将接口返回数据赋值 |
注意代码的添加位置,然后再次请求一下生成图形验证码的接口,点击右侧Body区域的Visualizer,可以看到图形验证码已经出现了:

接着按照图示操作来校验图形验证码,在Body区域选择raw,然后以JSON形式传入之前返回的codeKey以及用户输入的inputCode:

可以看到请求返回成功,并显示验证码匹配成功。
小结
本篇基于SpringBoot+Redis实现了生成和校验图形验证码的功能,原理就是先生成图形验证码及验证码字符串,然后将验证码字符串存入缓存中,接着将图形验证码及字符串key返回给用户,后续用户在提交验证码时,根据字符串key及输入的验证码,从缓存中取出验证码字符串,并与用户输入提交的验证码进行对比,进而判断是否匹配成功。
在了解这种原理之后,你就可以举一反三,利用SpringBoot+Redis这一组合拳实现发送和校验短信验证码,接口防刷、防重复提交等功能。
