mirror of
https://github.com/dromara/tianai-captcha.git
synced 2026-05-06 21:53:10 +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>
|
||||
<groupId>cloud.tianai.captcha</groupId>
|
||||
<artifactId>tianai-captcha</artifactId>
|
||||
<version>1.5.1</version>
|
||||
<version>1.5.2</version>
|
||||
|
||||
<name>tianai-captcha</name>
|
||||
<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++) {
|
||||
// 随机获取点击图片
|
||||
ImgWrapper imgWrapper = getClickImg(imgTips.get(i));
|
||||
ImgWrapper imgWrapper = getClickImg(imgTips.get(i),null);
|
||||
BufferedImage image = imgWrapper.getImage();
|
||||
int clickImgWidth = image.getWidth();
|
||||
int clickImgHeight = image.getHeight();
|
||||
@@ -75,7 +75,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
clickImageCheckDefinition.setImageColor(imgWrapper.getImageColor());
|
||||
clickImageCheckDefinitionList.add(clickImageCheckDefinition);
|
||||
}
|
||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = filterAndSortClickImageCheckDefinition(clickImageCheckDefinitionList);
|
||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = filterAndSortClickImageCheckDefinition(captchaExchange,clickImageCheckDefinitionList);
|
||||
captchaExchange.setBackgroundImage(bgImage);
|
||||
captchaExchange.setTransferData(checkClickImageCheckDefinitionList);
|
||||
captchaExchange.setResourceImage(resourceImage);
|
||||
@@ -94,7 +94,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
* @param allCheckDefinitionList 总的点选图片
|
||||
* @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 提示数据,根据改数据生成图片
|
||||
* @return ImgWrapper
|
||||
*/
|
||||
public abstract ImgWrapper getClickImg(Resource tip);
|
||||
public abstract ImgWrapper getClickImg(Resource tip, Color randomColor);
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
|
||||
@@ -5,7 +5,6 @@ import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
||||
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.GenerateParam;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
||||
@@ -15,7 +14,6 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
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, ImageCaptchaGeneratorProvider> imageCaptchaGeneratorProviderMap = new HashMap<>(4);
|
||||
// 点选类验证码字体
|
||||
@Setter
|
||||
@Getter
|
||||
protected List<FontWrapper> fontWrappers;
|
||||
// @Setter
|
||||
// @Getter
|
||||
// protected List<FontWrapper> fontWrappers;
|
||||
@Setter
|
||||
@Getter
|
||||
private String defaultCaptcha = SLIDER;
|
||||
@@ -56,8 +54,7 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
// 拼接验证码
|
||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(CONCAT, StandardConcatImageCaptchaGenerator::new));
|
||||
// 点选文字验证码
|
||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(WORD_IMAGE_CLICK, (r, t, i) ->
|
||||
new StandardWordClickImageCaptchaGenerator(r, t, i, fontWrappers)));
|
||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(WORD_IMAGE_CLICK, StandardWordClickImageCaptchaGenerator::new));
|
||||
}
|
||||
|
||||
public void addImageCaptchaGeneratorProvider(ImageCaptchaGeneratorProvider provider) {
|
||||
|
||||
+39
-25
@@ -1,14 +1,15 @@
|
||||
package cloud.tianai.captcha.generator.impl;
|
||||
|
||||
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.util.CollectionUtils;
|
||||
import cloud.tianai.captcha.common.util.FontUtils;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.common.FontWrapper;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.*;
|
||||
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
|
||||
import cloud.tianai.captcha.resource.FontCache;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import lombok.Getter;
|
||||
@@ -30,9 +31,9 @@ import java.util.stream.Collectors;
|
||||
public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCaptchaGenerator {
|
||||
|
||||
/** 字体包. */
|
||||
@Getter
|
||||
@Setter
|
||||
protected List<FontWrapper> fonts = new ArrayList<>();
|
||||
// @Getter
|
||||
// @Setter
|
||||
// protected List<FontWrapper> fonts = new ArrayList<>();
|
||||
@Getter
|
||||
@Setter
|
||||
protected Integer clickImgWidth = 100;
|
||||
@@ -64,12 +65,7 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
//
|
||||
// protected float currentFontTopCoef = 0.0f;
|
||||
public StandardWordClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
|
||||
super(imageCaptchaResourceManager);
|
||||
}
|
||||
|
||||
public StandardWordClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, ImageTransform imageTransform) {
|
||||
super(imageCaptchaResourceManager);
|
||||
setImageTransform(imageTransform);
|
||||
this(imageCaptchaResourceManager, null, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,16 +75,11 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
setInterceptor(interceptor);
|
||||
}
|
||||
|
||||
public StandardWordClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, ImageTransform imageTransform, CaptchaInterceptor interceptor, List<FontWrapper> fonts) {
|
||||
super(imageCaptchaResourceManager);
|
||||
setImageTransform(imageTransform);
|
||||
setInterceptor(interceptor);
|
||||
this.fonts = fonts;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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;
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
List<Resource> tipList = new ArrayList<>(tipSize);
|
||||
@@ -102,14 +93,25 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
if (CollectionUtils.isEmpty(fonts)) {
|
||||
throw new ImageCaptchaException("初始化文字点选验证码失败,请设置字体包后再调用init()");
|
||||
// if (CollectionUtils.isEmpty(fonts)) {
|
||||
// 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) {
|
||||
FontWrapper fontWrapper = fonts.get(randomInt(fonts.size()));
|
||||
FontWrapper fontWrapper = randomFont();
|
||||
Font font = fontWrapper.getFont();
|
||||
float currentFontTopCoef = fontWrapper.getCurrentFontTopCoef();
|
||||
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);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public ImgWrapper getClickImg(Resource tip) {
|
||||
// ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
// // 随机颜色
|
||||
// Color randomColor = CaptchaImageUtils.getRandomColor(random);
|
||||
// return getClickImg(tip, randomColor);
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public ImgWrapper getClickImg(Resource tip) {
|
||||
public ImgWrapper getClickImg(Resource tip, Color randomColor) {
|
||||
if (randomColor == null) {
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
// 随机颜色
|
||||
Color randomColor = CaptchaImageUtils.getRandomColor(random);
|
||||
randomColor = CaptchaImageUtils.getRandomColor(random);
|
||||
}
|
||||
// 随机角度
|
||||
int randomDeg = randomInt(0, 85);
|
||||
FontWrapper fontWrapper = fonts.get(randomInt(fonts.size()));
|
||||
FontWrapper fontWrapper = randomFont();
|
||||
Font font = fontWrapper.getFont();
|
||||
float currentFontTopCoef = fontWrapper.getCurrentFontTopCoef();
|
||||
BufferedImage fontImage = CaptchaImageUtils.drawWordImg(randomColor,
|
||||
@@ -145,7 +157,9 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
}
|
||||
|
||||
@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);
|
||||
// 拿出参与校验的数据
|
||||
|
||||
Reference in New Issue
Block a user