mirror of
https://github.com/dromara/tianai-captcha.git
synced 2026-05-07 06:04:34 +08:00
feat(captcha): 优化点选验证码逻辑
- 修改 AbstractClickImageCaptchaGenerator 中的 getClickImg 方法,增加 randomColor 参数 - 更新 MultiImageCaptchaGenerator 中的 StandardWordClickImageCaptchaGenerator 实例创建方式 - 新增 ParamKeyEnum 类,用于定义点选验证码的参数键 - 更新 StandardWordClickImageCaptchaGenerator 中的随机字体选择逻辑 -调整 filterAndSortClickImageCheckDefinition 方法,支持自定义校验数量
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>cloud.tianai.captcha</groupId>
|
<groupId>cloud.tianai.captcha</groupId>
|
||||||
<artifactId>tianai-captcha</artifactId>
|
<artifactId>tianai-captcha</artifactId>
|
||||||
<version>1.5.1</version>
|
<version>1.5.2</version>
|
||||||
|
|
||||||
<name>tianai-captcha</name>
|
<name>tianai-captcha</name>
|
||||||
<description>行为验证码</description>
|
<description>行为验证码</description>
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package cloud.tianai.captcha.generator.common.model.dto;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ParamKeyEnum<T> implements ParamKey<T> {
|
||||||
|
|
||||||
|
|
||||||
|
/** 点选验证码参与校验的数量. 值为Integer */
|
||||||
|
public static final ParamKey<Integer> CLICK_CHECK_CLICK_COUNT = new ParamKeyEnum<>("checkClickCount");
|
||||||
|
/** 点选验证码干扰数量. 值为Integer */
|
||||||
|
public static final ParamKey<Integer> CLICK_INTERFERENCE_COUNT = new ParamKeyEnum<>("interferenceCount");
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
}
|
||||||
+4
-4
@@ -51,7 +51,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < allImages; i++) {
|
for (int i = 0; i < allImages; i++) {
|
||||||
// 随机获取点击图片
|
// 随机获取点击图片
|
||||||
ImgWrapper imgWrapper = getClickImg(imgTips.get(i));
|
ImgWrapper imgWrapper = getClickImg(imgTips.get(i),null);
|
||||||
BufferedImage image = imgWrapper.getImage();
|
BufferedImage image = imgWrapper.getImage();
|
||||||
int clickImgWidth = image.getWidth();
|
int clickImgWidth = image.getWidth();
|
||||||
int clickImgHeight = image.getHeight();
|
int clickImgHeight = image.getHeight();
|
||||||
@@ -75,7 +75,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
|||||||
clickImageCheckDefinition.setImageColor(imgWrapper.getImageColor());
|
clickImageCheckDefinition.setImageColor(imgWrapper.getImageColor());
|
||||||
clickImageCheckDefinitionList.add(clickImageCheckDefinition);
|
clickImageCheckDefinitionList.add(clickImageCheckDefinition);
|
||||||
}
|
}
|
||||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = filterAndSortClickImageCheckDefinition(clickImageCheckDefinitionList);
|
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = filterAndSortClickImageCheckDefinition(captchaExchange,clickImageCheckDefinitionList);
|
||||||
captchaExchange.setBackgroundImage(bgImage);
|
captchaExchange.setBackgroundImage(bgImage);
|
||||||
captchaExchange.setTransferData(checkClickImageCheckDefinitionList);
|
captchaExchange.setTransferData(checkClickImageCheckDefinitionList);
|
||||||
captchaExchange.setResourceImage(resourceImage);
|
captchaExchange.setResourceImage(resourceImage);
|
||||||
@@ -94,7 +94,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
|||||||
* @param allCheckDefinitionList 总的点选图片
|
* @param allCheckDefinitionList 总的点选图片
|
||||||
* @return List<ClickImageCheckDefinition>
|
* @return List<ClickImageCheckDefinition>
|
||||||
*/
|
*/
|
||||||
protected abstract List<ClickImageCheckDefinition> filterAndSortClickImageCheckDefinition(List<ClickImageCheckDefinition> allCheckDefinitionList);
|
protected abstract List<ClickImageCheckDefinition> filterAndSortClickImageCheckDefinition(CaptchaExchange captchaExchange,List<ClickImageCheckDefinition> allCheckDefinitionList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 随机获取一组数据用于生成随机图
|
* 随机获取一组数据用于生成随机图
|
||||||
@@ -109,7 +109,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
|||||||
* @param tip 提示数据,根据改数据生成图片
|
* @param tip 提示数据,根据改数据生成图片
|
||||||
* @return ImgWrapper
|
* @return ImgWrapper
|
||||||
*/
|
*/
|
||||||
public abstract ImgWrapper getClickImg(Resource tip);
|
public abstract ImgWrapper getClickImg(Resource tip, Color randomColor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author: 天爱有情
|
* @Author: 天爱有情
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
|
|||||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||||
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
||||||
import cloud.tianai.captcha.generator.ImageTransform;
|
import cloud.tianai.captcha.generator.ImageTransform;
|
||||||
import cloud.tianai.captcha.generator.common.FontWrapper;
|
|
||||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
|
import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
|
||||||
import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
|
import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
|
||||||
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
||||||
@@ -15,7 +14,6 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@@ -31,9 +29,9 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
|||||||
protected Map<String, ImageCaptchaGenerator> imageCaptchaGeneratorMap = new ConcurrentHashMap<>(4);
|
protected Map<String, ImageCaptchaGenerator> imageCaptchaGeneratorMap = new ConcurrentHashMap<>(4);
|
||||||
protected Map<String, ImageCaptchaGeneratorProvider> imageCaptchaGeneratorProviderMap = new HashMap<>(4);
|
protected Map<String, ImageCaptchaGeneratorProvider> imageCaptchaGeneratorProviderMap = new HashMap<>(4);
|
||||||
// 点选类验证码字体
|
// 点选类验证码字体
|
||||||
@Setter
|
// @Setter
|
||||||
@Getter
|
// @Getter
|
||||||
protected List<FontWrapper> fontWrappers;
|
// protected List<FontWrapper> fontWrappers;
|
||||||
@Setter
|
@Setter
|
||||||
@Getter
|
@Getter
|
||||||
private String defaultCaptcha = SLIDER;
|
private String defaultCaptcha = SLIDER;
|
||||||
@@ -56,8 +54,7 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
|||||||
// 拼接验证码
|
// 拼接验证码
|
||||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(CONCAT, StandardConcatImageCaptchaGenerator::new));
|
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(CONCAT, StandardConcatImageCaptchaGenerator::new));
|
||||||
// 点选文字验证码
|
// 点选文字验证码
|
||||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(WORD_IMAGE_CLICK, (r, t, i) ->
|
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(WORD_IMAGE_CLICK, StandardWordClickImageCaptchaGenerator::new));
|
||||||
new StandardWordClickImageCaptchaGenerator(r, t, i, fontWrappers)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addImageCaptchaGeneratorProvider(ImageCaptchaGeneratorProvider provider) {
|
public void addImageCaptchaGeneratorProvider(ImageCaptchaGeneratorProvider provider) {
|
||||||
|
|||||||
+39
-25
@@ -1,14 +1,15 @@
|
|||||||
package cloud.tianai.captcha.generator.impl;
|
package cloud.tianai.captcha.generator.impl;
|
||||||
|
|
||||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||||
|
import cloud.tianai.captcha.common.constant.CommonConstant;
|
||||||
import cloud.tianai.captcha.common.exception.ImageCaptchaException;
|
import cloud.tianai.captcha.common.exception.ImageCaptchaException;
|
||||||
import cloud.tianai.captcha.common.util.CollectionUtils;
|
|
||||||
import cloud.tianai.captcha.common.util.FontUtils;
|
import cloud.tianai.captcha.common.util.FontUtils;
|
||||||
import cloud.tianai.captcha.generator.ImageTransform;
|
import cloud.tianai.captcha.generator.ImageTransform;
|
||||||
import cloud.tianai.captcha.generator.common.FontWrapper;
|
import cloud.tianai.captcha.generator.common.FontWrapper;
|
||||||
import cloud.tianai.captcha.generator.common.model.dto.*;
|
import cloud.tianai.captcha.generator.common.model.dto.*;
|
||||||
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
|
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
|
||||||
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
|
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
|
||||||
|
import cloud.tianai.captcha.resource.FontCache;
|
||||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -30,9 +31,9 @@ import java.util.stream.Collectors;
|
|||||||
public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCaptchaGenerator {
|
public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCaptchaGenerator {
|
||||||
|
|
||||||
/** 字体包. */
|
/** 字体包. */
|
||||||
@Getter
|
// @Getter
|
||||||
@Setter
|
// @Setter
|
||||||
protected List<FontWrapper> fonts = new ArrayList<>();
|
// protected List<FontWrapper> fonts = new ArrayList<>();
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
protected Integer clickImgWidth = 100;
|
protected Integer clickImgWidth = 100;
|
||||||
@@ -64,12 +65,7 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
|||||||
//
|
//
|
||||||
// protected float currentFontTopCoef = 0.0f;
|
// protected float currentFontTopCoef = 0.0f;
|
||||||
public StandardWordClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
|
public StandardWordClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
|
||||||
super(imageCaptchaResourceManager);
|
this(imageCaptchaResourceManager, null, null);
|
||||||
}
|
|
||||||
|
|
||||||
public StandardWordClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, ImageTransform imageTransform) {
|
|
||||||
super(imageCaptchaResourceManager);
|
|
||||||
setImageTransform(imageTransform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -79,16 +75,11 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
|||||||
setInterceptor(interceptor);
|
setInterceptor(interceptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StandardWordClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, ImageTransform imageTransform, CaptchaInterceptor interceptor, List<FontWrapper> fonts) {
|
|
||||||
super(imageCaptchaResourceManager);
|
|
||||||
setImageTransform(imageTransform);
|
|
||||||
setInterceptor(interceptor);
|
|
||||||
this.fonts = fonts;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Resource> randomGetClickImgTips(GenerateParam param) {
|
protected List<Resource> randomGetClickImgTips(GenerateParam param) {
|
||||||
|
Integer checkClickCount = param.getOrDefault(ParamKeyEnum.CLICK_CHECK_CLICK_COUNT, getCheckClickCount());
|
||||||
|
Integer interferenceCount = param.getOrDefault(ParamKeyEnum.CLICK_INTERFERENCE_COUNT, getInterferenceCount());
|
||||||
int tipSize = interferenceCount + checkClickCount;
|
int tipSize = interferenceCount + checkClickCount;
|
||||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||||
List<Resource> tipList = new ArrayList<>(tipSize);
|
List<Resource> tipList = new ArrayList<>(tipSize);
|
||||||
@@ -102,14 +93,25 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doInit() {
|
protected void doInit() {
|
||||||
if (CollectionUtils.isEmpty(fonts)) {
|
// if (CollectionUtils.isEmpty(fonts)) {
|
||||||
throw new ImageCaptchaException("初始化文字点选验证码失败,请设置字体包后再调用init()");
|
// throw new ImageCaptchaException("初始化文字点选验证码失败,请设置字体包后再调用init()");
|
||||||
|
// }
|
||||||
|
// ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
|
||||||
|
// // 添加一些系统的资源文件
|
||||||
|
// resourceStore.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FontWrapper randomFont() {
|
||||||
|
Resource resource = requiredRandomGetResource(FontCache.FONT_TYPE, CommonConstant.DEFAULT_TAG);
|
||||||
|
Object extra = resource.getExtra();
|
||||||
|
if (extra instanceof FontWrapper) {
|
||||||
|
return (FontWrapper) extra;
|
||||||
|
}
|
||||||
|
throw new ImageCaptchaException("随机获取字体失败, resource中没有读到字体包, resource=" + resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ImgWrapper genTipImage(List<ClickImageCheckDefinition> imageCheckDefinitions) {
|
public ImgWrapper genTipImage(List<ClickImageCheckDefinition> imageCheckDefinitions) {
|
||||||
FontWrapper fontWrapper = fonts.get(randomInt(fonts.size()));
|
FontWrapper fontWrapper = randomFont();
|
||||||
Font font = fontWrapper.getFont();
|
Font font = fontWrapper.getFont();
|
||||||
float currentFontTopCoef = fontWrapper.getCurrentFontTopCoef();
|
float currentFontTopCoef = fontWrapper.getCurrentFontTopCoef();
|
||||||
String tips = imageCheckDefinitions.stream().map(c -> c.getTip().getData()).collect(Collectors.joining());
|
String tips = imageCheckDefinitions.stream().map(c -> c.getTip().getData()).collect(Collectors.joining());
|
||||||
@@ -124,14 +126,24 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
|||||||
return new ImgWrapper(bufferedImage, new Resource(null, tips), null);
|
return new ImgWrapper(bufferedImage, new Resource(null, tips), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public ImgWrapper getClickImg(Resource tip) {
|
||||||
|
// ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||||
|
// // 随机颜色
|
||||||
|
// Color randomColor = CaptchaImageUtils.getRandomColor(random);
|
||||||
|
// return getClickImg(tip, randomColor);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImgWrapper getClickImg(Resource tip) {
|
public ImgWrapper getClickImg(Resource tip, Color randomColor) {
|
||||||
|
if (randomColor == null) {
|
||||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||||
// 随机颜色
|
randomColor = CaptchaImageUtils.getRandomColor(random);
|
||||||
Color randomColor = CaptchaImageUtils.getRandomColor(random);
|
}
|
||||||
// 随机角度
|
// 随机角度
|
||||||
int randomDeg = randomInt(0, 85);
|
int randomDeg = randomInt(0, 85);
|
||||||
FontWrapper fontWrapper = fonts.get(randomInt(fonts.size()));
|
FontWrapper fontWrapper = randomFont();
|
||||||
Font font = fontWrapper.getFont();
|
Font font = fontWrapper.getFont();
|
||||||
float currentFontTopCoef = fontWrapper.getCurrentFontTopCoef();
|
float currentFontTopCoef = fontWrapper.getCurrentFontTopCoef();
|
||||||
BufferedImage fontImage = CaptchaImageUtils.drawWordImg(randomColor,
|
BufferedImage fontImage = CaptchaImageUtils.drawWordImg(randomColor,
|
||||||
@@ -145,7 +157,9 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<ClickImageCheckDefinition> filterAndSortClickImageCheckDefinition(List<ClickImageCheckDefinition> allCheckDefinitionList) {
|
protected List<ClickImageCheckDefinition> filterAndSortClickImageCheckDefinition(CaptchaExchange captchaExchange,List<ClickImageCheckDefinition> allCheckDefinitionList) {
|
||||||
|
GenerateParam param = captchaExchange.getParam();
|
||||||
|
Integer checkClickCount = param.getOrDefault(ParamKeyEnum.CLICK_CHECK_CLICK_COUNT, getCheckClickCount());
|
||||||
// 打乱
|
// 打乱
|
||||||
Collections.shuffle(allCheckDefinitionList);
|
Collections.shuffle(allCheckDefinitionList);
|
||||||
// 拿出参与校验的数据
|
// 拿出参与校验的数据
|
||||||
|
|||||||
Reference in New Issue
Block a user