1. 基本结构
使用captcha生成验证码, 利用redis存储验证码
redis中的结构为, key是32位的uuid, value为captcha的4位随机字母以及数字的集合
设定redis过期时间为1min, 即可实现过期验证码的自动失效
2. kaptcha的依赖
基本的依赖这里不再叙述, 主要说一下要导入captcha的依赖
com.github.penggle kaptcha 2.3.2
所有的依赖如下
4.0.0 org.springframework.boot spring-boot-starter-parent 2.4.0 com.wang spring_security_framework 0.0.1-snapshot spring_security_framework demo project for spring boot 1.8 org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-jdbc org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-thymeleaf org.springframework.boot spring-boot-starter-validation org.springframework.boot spring-boot-starter-web org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.4 org.thymeleaf.extras thymeleaf-extras-springsecurity5 mysql mysql-connector-java runtime org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.springframework.security spring-security-test test com.alibaba druid-spring-boot-starter 1.2.2 com.alibaba fastjson 1.2.74 log4j log4j 1.2.17 io.springfox springfox-boot-starter 3.0.0 cn.hutool hutool-all 5.4.7 com.github.penggle kaptcha 2.3.2 org.springframework.boot spring-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生成验证码的详细内容,更多关于springboot生成验证码的资料请关注其它相关文章!
晨曦西