SpringBoot整合kaptcha(谷歌验证码工具)实现验证码功能
0.Maven
<dependency>
<groupId>com.google.code</groupId>
<artifactId>kaptcha</artifactId>
<version>2.3.2</version>
</dependency>
1.验证码文本生成器(算术验证码的时候需要)
KaptchaTextCreator 类
package com.safesoft.web.kevin.cacheTest;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
import java.util.Random;
/**
* 验证码文本生成器
*
* @author 592211009@qq.com
*/
public class KaptchaTextCreator extends DefaultTextCreator
{
private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
@Override
public String getText()
{
Integer result = 0;
Random random = new Random();
int x = random.nextInt(10);
int y = random.nextInt(10);
StringBuilder suChinese = new StringBuilder();
int randomoperands = (int) Math.round(Math.random() * 2);
if (randomoperands == 0)
{
result = x * y;
suChinese.append(CNUMBERS[x]);
suChinese.append("*");
suChinese.append(CNUMBERS[y]);
}
else if (randomoperands == 1)
{
if (!(x == 0) && y % x == 0)
{
result = y / x;
suChinese.append(CNUMBERS[y]);
suChinese.append("/");
suChinese.append(CNUMBERS[x]);
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
}
else if (randomoperands == 2)
{
if (x >= y)
{
result = x - y;
suChinese.append(CNUMBERS[x]);
suChinese.append("-");
suChinese.append(CNUMBERS[y]);
}
else
{
result = y - x;
suChinese.append(CNUMBERS[y]);
suChinese.append("-");
suChinese.append(CNUMBERS[x]);
}
}
else
{
result = x + y;
suChinese.append(CNUMBERS[x]);
suChinese.append("+");
suChinese.append(CNUMBERS[y]);
}
suChinese.append("=?@" + result);
return suChinese.toString();
}
}
2.验证码配置
package com.safesoft.web.kevin.cacheTest;
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;
import static com.google.code.kaptcha.Constants.*;
import static com.google.code.kaptcha.Constants.KAPTCHA_BORDER;
import static com.google.code.kaptcha.Constants.KAPTCHA_BORDER_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_IMAGE_HEIGHT;
import static com.google.code.kaptcha.Constants.KAPTCHA_IMAGE_WIDTH;
import static com.google.code.kaptcha.Constants.KAPTCHA_NOISE_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_NOISE_IMPL;
import static com.google.code.kaptcha.Constants.KAPTCHA_OBSCURIFICATOR_IMPL;
import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_CONFIG_KEY;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_IMPL;
/**
* 验证码配置
*
* @author 592211009@qq.com
*/
@Configuration
public class CaptchaConfig
{
@Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yes,no
properties.setProperty(KAPTCHA_BORDER, "yes");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
@Bean(name = "captchaProducerMath")
public DefaultKaptcha getKaptchaBeanMath()
{
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yes,no
properties.setProperty(KAPTCHA_BORDER, "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.safesoft.web.kevin.cacheTest.KaptchaTextCreator");
// 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
3.Kaptcha详细配置表
Kaptcha详细配置表
序号 属性名 描述 示例
1 kaptcha.width 验证码宽度 200
2 kaptcha.height 验证码高度 50
3 kaptcha.border.enabled 是否显示边框 false
4 kaptcha.border.color 边框颜色 black
5 kaptcha.border.thickness 边框厚度 2
6 kaptcha.content.length 验证码文本长度 5
7 kaptcha.content.source 文本源 abcde2345678gfynmnpwx
8 kaptcha.content.space 文本间隔 2
9 kaptcha.font.name 字体名称 Arial
10 kaptcha.font.size 字体大小 40
11 kaptcha.font.color 字体颜色 black
12 kaptcha.background-color.from 背景颜色(开始渐变色) lightGray
13 kaptcha.background-color.to 背景颜色(结束渐变色 white
4.就可以使用了-举个例子(控制层)
eg:
/**
* [验证码控制层]
*
* @author Kevin.Wan
* @date 2023/6/16
**/
@RestController
public class CaptchaController {
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
/**
* 生成验证码
*/
@GetMapping("/captchaImage")
public Rest<ValidateCodeVO> getCode(HttpServletResponse response) throws IOException
{
ValidateCodeVO validateCodeVO = new ValidateCodeVO();
//这一步获取是否开启了验证码功能
boolean captchaOnOff = true;
if (!captchaOnOff)
{
return RestBody.okData(validateCodeVO);
}
// 保存验证码信息
String uuid = UUID.randomUUID().toString();
//用于缓存的key
String verifyKey = "captcha_codes:"+ uuid;
String capStr = null, code = null;
BufferedImage image = null;
// 生成验证码
//先获取验证码类型 在配置文件中获取 这里先直接定义了
String captchaType = "char"; //math 数组计算(几加几等于几) char 字符验证(就是认字母)
if ("math".equals(captchaType))
{
String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr);
}
else if ("char".equals(captchaType))
{
capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr);
}
//redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
ImageIO.write(image, "jpg", os);
}
catch (IOException e)
{
return (Rest<ValidateCodeVO>) RestBody.failure(8888,e.getMessage());
}
validateCodeVO.setUuid(uuid);
validateCodeVO.setDataBase64(Base64.encode(os.toByteArray()));
return RestBody.okData(validateCodeVO);
}
}
5.返回的信息
{
"code": 200,
"data": {
"uuid": "31450b4a-5600-4434-a9e5-8b64fa7280b4",
"dataBase64": "/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc0ZYLy3kt5GjhlDBXUqSMyEZwfQ0Af/Z******************************"
},
"msg": "ok",
"identifier": "success"
}
6.前端展示
vue2:
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img"/>
</div>
这里展示的url 一定一定要加 data:image/gif;base64,
methods: {
getCode() {
this.$axios({
method:'GET',
url:"/captchaImage",
headers: {
"Content-Type": "application/json"
}
}).then(res=>{
this.codeUrl = "data:image/gif;base64," + res.data.img;
})
},
vue3:
<div class="propName">验证码</div>
<el-form-item prop="validateCode">
<div class="verification">
<div class="show-box" @click="getValid2">
<el-image style="width: 100%; height: 100%" fit="none" :src="validCodeBase64Img" />
</div>
<el-input v-model="form.validateCode" :maxlength="10" :prefix-icon="ElementPlus" class="input_box" />
</div>
</el-form-item>
带校验了这个
最主要:
const getValid2 = () => {
getValidCode2().then((res) => {
form.uuid = res.data.uuid;
validCodeBase64Img.value = "data:image/gif;base64,"+res.data.dataBase64;
});
};
getValid2() //系统进来就触发这个方法
// 验证码接口
export const getValidCode2 = (): Promise<any> => {
return AxiosRequest({
method: 'get',
url: '/captchaImage',
})
}
7.效果
Valid2 = () => {
getValidCode2().then((res) => {
form.uuid = res.data.uuid;
validCodeBase64Img.value = “data:image/gif;base64,”+res.data.dataBase64;
});
};
getValid2() //系统进来就触发这个方法
```js
// 验证码接口
export const getValidCode2 = (): Promise<any> => {
return AxiosRequest({
method: 'get',
url: '/captchaImage',
})
}
7.效果
当String captchaType = “math”;
当String captchaType = “char”;