您好,登录后才能下订单哦!
本篇文章给大家分享的是有关怎么在SpringBoot中利用Captcha生成验证码,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
springboot一种全新的编程规范,其设计目的是用来简化新Spring应用的初始搭建以及开发过程,SpringBoot也是一个服务于框架的框架,服务范围是简化配置文件。
使用Captcha生成验证码, 利用Redis存储验证码
Redis中的结构为, Key是32位的UUID, Value为Captcha的4位随机字母以及数字的集合
设定Redis过期时间为1min, 即可实现过期验证码的自动失效
基本的依赖这里不再叙述, 主要说一下要导入Captcha的依赖
<!--Kaptcha--> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
所有的依赖如下
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.wang</groupId> <artifactId>spring_security_framework</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring_security_framework</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!--Redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--JDBC--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--SpringSecurity--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!--Thymeleaf--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!--Validation--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!--SpringBoot Web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--Mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <!--SpringSecurity with thymeleaf--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> <!--MySQL connector--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!--Lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--Test--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <!--Druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.2</version> </dependency> <!--FastJSON--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.74</version> </dependency> <!--log4j--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!--Swagger2--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> <!--HuTool--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.4.7</version> </dependency> <!--Kaptcha--> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
配置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,这里就不再赘述
我们可以通过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;
}
}使用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<String, Object> 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<String, Object> token = captchaService.createToken(text);
token.put("img", encoder.encode(outputStream.toByteArray()));
return token;
}
}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<String, Object> createToken(String captcha);
//生成captcha验证码
Map<String, Object> 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<String, Object> 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<String, Object> createToken(String captcha) {
//生成一个token
String key = uuidUtil.getUUID32();
//生成验证码对应的token 以token为key 验证码为value存在redis中
ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
valueOperations.set(key, captcha);
//设置验证码过期时间
redisTemplate.expire(key, timeout, TimeUnit.MINUTES);
Map<String, Object> map = new HashMap<>();
map.put("token", key);
map.put("expire", timeout);
return map;
}
//生成captcha验证码
@Override
public Map<String, Object> captchaCreator() throws IOException {
return captchaUtil.catchaImgCreator();
}
//验证输入的验证码是否正确
@Override
public String versifyCaptcha(String token, String inputCode) {
//根据前端传回的token在redis中找对应的value
ValueOperations<String, Object> 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中匹配, 返回了字符串
真实的验证中, 我们还要在逻辑中添加用户名和密码的考虑
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<String, Object> 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方法, 这样安全性更高
前端结构如图, 实现了一个简单的验证码

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>登录</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> </head> <body> <div> <div> <form th:action="@{/login1}" method="get"> <input type="text" id="userName" placeholder="请输入用户名" name="userName"> <br> <input type="password" id="password" placeholder="请输入密码" name="password"> <br> <input type="text" id="inputCode" placeholder="请输入验证码" maxlength="4" name="inputCode"> <!--通过隐藏域传递值, 在下面的验证码点击事件中, 将值绑定过来, 这样就可以获得最新的验证码对应的值了!--> <input id="token" value="" type="hidden" name="token"> <input type="submit" value="登录"> </form> </div> <div> <!-- 当用户链接时,void(0)计算为0,用户点击不会发生任何效果 --> <a href="javascript:void(0);" rel="external nofollow" title="点击更换验证码"> <!--this参数, 返回当前的DOM元素--> <img src="" alt="更换验证码" id="imgVerify" onclick="getVerify(this)"> </a> </div> </div> <script> //获得img对象 let imgVerify = $("#imgVerify").get(0); //$(function())等同于$(document).ready(function()) ==> 页面加载完毕之后, 才执行函数 $(function () { getVerify(imgVerify); }); //onclick时间绑定的getVerify函数 function getVerify(obj) { $.ajax({ type: "GET", url: "/captcha", success: function (result) { obj.src = "data:image/jpeg;base64," + result.img; $("#token").val(result.token); } }); } </script> </body> </html>
用一个 a 标签包围 img 标签, 这样如果图片没有加载出来也有一个超链接, 不过点了以后没有效果
(function())等同于(function())等同于(document).ready(function()) ==> 页面加载完毕之后, 才执行函数, 这里必须要写这个函数, 否则第一次加载不会调用 onclick 方法, 也就不会生成验证码!
我们利用隐藏域将验证码的key传递到表单中, 我们在 img 的点击事件对应的函数的ajax回调函数中可以利用jQuery操作DOM, 顺带取出key值放到我们的隐藏域中, 这样提交的时候就会提交 key 和用户输入的 value 了

验证通过

以上就是怎么在SpringBoot中利用Captcha生成验证码,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。