SpringBoot使用Captcha生成验证码

这篇文章主要介绍了SpringBoot如何使用Captcha生成验证码,帮助大家更好的理解和学习使用SpringBoot,感兴趣的朋友可以了解下

1. 基本结构

使用Captcha生成验证码, 利用Redis存储验证码

Redis中的结构为, Key是32位的UUID, Value为Captcha的4位随机字母以及数字的集合

设定Redis过期时间为1min, 即可实现过期验证码的自动失效

2. Kaptcha的依赖

基本的依赖这里不再叙述, 主要说一下要导入Captcha的依赖

  com.github.pengglekaptcha2.3.2

所有的依赖如下

   4.0.0 org.springframework.bootspring-boot-starter-parent2.4.0com.wangspring_security_framework0.0.1-SNAPSHOTspring_security_frameworkDemo project for Spring Boot 1.8  org.springframework.bootspring-boot-starter-data-redis org.springframework.bootspring-boot-starter-jdbc org.springframework.bootspring-boot-starter-security org.springframework.bootspring-boot-starter-thymeleaf org.springframework.bootspring-boot-starter-validation org.springframework.bootspring-boot-starter-web org.mybatis.spring.bootmybatis-spring-boot-starter2.1.4 org.thymeleaf.extrasthymeleaf-extras-springsecurity5 mysqlmysql-connector-javaruntime org.projectlomboklomboktrue org.springframework.bootspring-boot-starter-testtest org.springframework.securityspring-security-testtest com.alibabadruid-spring-boot-starter1.2.2 com.alibabafastjson1.2.74 log4jlog4j1.2.17 io.springfoxspringfox-boot-starter3.0.0 cn.hutoolhutool-all5.4.7 com.github.pengglekaptcha2.3.2   org.springframework.bootspring-boot-maven-plugin

3. 配置SpringBoot

配置SpringBoot的配置文件, 这里主要关注一个session的过期时间

 #Port server: port: 80 servlet: session: timeout: 1 spring: application: name: SpringSecurityFramework #dataBase Setting datasource: username: root password: 123456 url: jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #Druid Setting druid: initial-size: 5 min-idle: 5 max-active: 20 max-wait: 60000 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 30000 validation-query: SELECT 1 FROM DUAL test-while-idle: true test-on-borrow: false test-on-return: false pool-prepared-statements: true #Setting For Druid StatView and Filter filters: stat,wall,log4j max-pool-prepared-statement-per-connection-size: 20 use-global-data-source-stat: true connection-properties: druid.stat.mergeSql=true;druid.stat.slowSql #Redis Setting redis: host: 127.0.0.1 port: 6379 #Thymeleaf thymeleaf: cache: false #Mybatis mybatis: type-aliases-package: com.wang.entity mapper-locations: classpath:Mybatis/mapper/*.xml configuration: map-underscore-to-camel-case: true 

其余的配置, 如log4j, druid, SpringSecurity, RedisTemplate,这里就不再赘述

4. 配置Captcha

我们可以通过JAVA的配置类来配置Captcha生成验证码的一些规则

 package com.wang.spring_security_framework.config; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Properties; //Kaptcha配置 @Configuration public class KaptchaConfig { @Bean public DefaultKaptcha producer() { //Properties类 Properties properties = new Properties(); // 图片边框 properties.setProperty("kaptcha.border", "yes"); // 边框颜色 properties.setProperty("kaptcha.border.color", "105,179,90"); // 字体颜色 properties.setProperty("kaptcha.textproducer.font.color", "blue"); // 图片宽 properties.setProperty("kaptcha.image.width", "110"); // 图片高 properties.setProperty("kaptcha.image.height", "40"); // 字体大小 properties.setProperty("kaptcha.textproducer.font.size", "30"); // session key properties.setProperty("kaptcha.session.key", "code"); // 验证码长度 properties.setProperty("kaptcha.textproducer.char.length", "4"); // 字体 properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); //图片干扰 properties.setProperty("kaptcha.noise.impl","com.google.code.kaptcha.impl.DefaultNoise"); //Kaptcha 使用上述配置 Config config = new Config(properties); //DefaultKaptcha对象使用上述配置, 并返回这个Bean DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); defaultKaptcha.setConfig(config); return defaultKaptcha; } } 

5. 工具类

使用UUID作为key, 同时考虑到对验证码的输出结果可能有不同的要求, 这里写两个工具类来处理它们

UUIDUtil

 package com.wang.spring_security_framework.util; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import java.util.UUID; @Component public class UUIDUtil { /** * 生成32位的随机UUID * @return 字符形式的小写UUID */ @Bean public String getUUID32() { return UUID.randomUUID().toString() .replace("-", "").toLowerCase(); } }

CaptchaUtil

 package com.wang.spring_security_framework.util; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.wang.spring_security_framework.service.CaptchaService; import io.netty.handler.codec.base64.Base64Encoder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import sun.misc.BASE64Encoder; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Map; @Component //Captcha 生成工具 public class CaptchaUtil { @Autowired private DefaultKaptcha producer; @Autowired private CaptchaService captchaService; //生成catchCreator的map public Map catchaImgCreator() throws IOException { //生成文字验证码 String text = producer.createText(); //生成文字对应的图片验证码 BufferedImage image = producer.createImage(text); //将图片写出 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ImageIO.write(image, "jpg", outputStream); //对写出的字节数组进行Base64编码 ==> 用于传递8比特字节码 BASE64Encoder encoder = new BASE64Encoder(); //生成token Map token = captchaService.createToken(text); token.put("img", encoder.encode(outputStream.toByteArray())); return token; } } 

6. 接口以及实现类

1. 接口

 package com.wang.spring_security_framework.service; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.Map; public interface CaptchaService { //生成token Map createToken(String captcha); //生成captcha验证码 Map captchaCreator() throws IOException; //验证输入的验证码是否正确 String versifyCaptcha (String token, String inputCode); } 

2. 实现类

 package com.wang.spring_security_framework.service.serviceImpl; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.wang.spring_security_framework.service.CaptchaService; import com.wang.spring_security_framework.util.CaptchaUtil; import com.wang.spring_security_framework.util.UUIDUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @Service public class CaptchaServiceImpl implements CaptchaService { @Autowired private RedisTemplate redisTemplate; @Autowired private UUIDUtil uuidUtil; @Autowired private CaptchaUtil captchaUtil; //从SpringBoot的配置文件中取出过期时间 @Value("${server.servlet.session.timeout}") private Integer timeout; //UUID为key, 验证码为Value放在Redis中 @Override public Map createToken(String captcha) { //生成一个token String key = uuidUtil.getUUID32(); //生成验证码对应的token  以token为key  验证码为value存在redis中 ValueOperations valueOperations = redisTemplate.opsForValue(); valueOperations.set(key, captcha); //设置验证码过期时间 redisTemplate.expire(key, timeout, TimeUnit.MINUTES); Map map = new HashMap<>(); map.put("token", key); map.put("expire", timeout); return map; } //生成captcha验证码 @Override public Map captchaCreator() throws IOException { return captchaUtil.catchaImgCreator(); } //验证输入的验证码是否正确 @Override public String versifyCaptcha(String token, String inputCode) { //根据前端传回的token在redis中找对应的value ValueOperations valueOperations = redisTemplate.opsForValue(); if (redisTemplate.hasKey(token)) { //验证通过, 删除对应的key if (valueOperations.get(token).equals(inputCode)) { redisTemplate.delete(token); return "true"; } else { return "false"; } } else { return "false"; } } } 
  • 这里的验证, 只是简单的验证了输入是否能从Redis中匹配, 返回了字符串
  • 真实的验证中, 我们还要在逻辑中添加用户名和密码的考虑

7. Controller

 package com.wang.spring_security_framework.controller; import com.wang.spring_security_framework.service.CaptchaService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.Map; @RestController public class LoginController { @Autowired CaptchaService captchaService; @GetMapping("/captcha") public Map captcha() throws IOException { return captchaService.captchaCreator(); } @GetMapping("/login1") public String login(@RequestParam("token") String token, @RequestParam("inputCode") String inputCode) { return captchaService.versifyCaptcha(token, inputCode); } } 
  • captcha 用于获取一个验证码
  • login1 用于接收到前端的请求后验证并返回结果
  • login1 这里为了测试简便实用了GET方法, 而实际中最好使用POST方法, 这样安全性更高

8. 前端页面的实现

前端结构如图, 实现了一个简单的验证码

   登录 
  • 用一个 a 标签包围 img 标签, 这样如果图片没有加载出来也有一个超链接, 不过点了以后没有效果
  • (function())等同于(function())等同于(document).ready(function()) ==> 页面加载完毕之后, 才执行函数, 这里必须要写这个函数, 否则第一次加载不会调用 onclick 方法, 也就不会生成验证码!
  • 我们利用隐藏域将验证码的key传递到表单中, 我们在 img 的点击事件对应的函数的ajax回调函数中可以利用jQuery操作DOM, 顺带取出key值放到我们的隐藏域中, 这样提交的时候就会提交 key 和用户输入的 value 了

示例

验证通过

以上就是SpringBoot使用Captcha生成验证码的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » Java