From db2f4097832dceecb4e0cab826d4488a5d30819e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E7=88=B1=E6=9C=89=E6=83=85?= Date: Thu, 9 Nov 2023 16:40:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=A5=E5=8F=8A=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=BE=88=E5=A4=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../common/constant/CaptchaTypeConstant.java | 15 +- .../common/constant/CommonConstant.java | 16 +- .../common/util/CaptchaTypeClassifier.java | 64 +++++++ .../captcha/common/util/CaptchaUtils.java | 44 ----- .../captcha/common/util/CollectionUtils.java | 4 +- .../tianai/captcha/common/util/FontUtils.java | 2 - .../captcha/common/util/ObjectUtils.java | 22 +-- .../AbstractImageCaptchaGenerator.java | 27 ++- .../generator/ImageCaptchaGenerator.java | 2 +- .../ImageCaptchaGeneratorProvider.java | 4 +- .../generator/ImageCaptchaPostProcessor.java | 29 +++- .../captcha/generator/ImageTransform.java | 6 +- .../captcha/generator/common/FontWrapper.java | 15 ++ .../constant/SliderCaptchaConstant.java | 18 -- ...TransferData.java => CaptchaExchange.java} | 22 ++- .../model/dto/ClickImageCheckDefinition.java | 4 + .../common/model/dto/ImageCaptchaInfo.java | 1 - .../common/util/CaptchaImageUtils.java | 156 +----------------- .../AbstractClickImageCaptchaGenerator.java | 21 ++- .../impl/MultiImageCaptchaGenerator.java | 25 ++- .../StandardConcatImageCaptchaGenerator.java | 32 ++-- .../StandardRotateImageCaptchaGenerator.java | 61 ++++--- .../StandardSliderImageCaptchaGenerator.java | 63 ++++--- ...tandardWordClickImageCaptchaGenerator.java | 33 ++-- .../StaticCaptchaPostProcessorManager.java | 18 +- ... CommonImageCaptchaGeneratorProvider.java} | 18 +- ...rdConcatImageCaptchaGeneratorProvider.java | 25 --- ...rdRotateImageCaptchaGeneratorProvider.java | 25 --- ...derImageImageCaptchaGeneratorProvider.java | 25 --- .../impl/transform/Base64ImageTransform.java | 8 +- .../captcha/resource/ResourceProvider.java | 1 - .../captcha/resource/ResourceStore.java | 2 - .../resource/common/model/dto/Resource.java | 13 +- .../DefaultImageCaptchaResourceManager.java | 7 +- ...ore.java => LocalMemoryResourceStore.java} | 80 ++++----- .../provider/ClassPathResourceProvider.java | 2 - .../impl/provider/FileResourceProvider.java | 2 - .../impl/provider/URLResourceProvider.java | 1 - .../common/model/dto/ImageCaptchaTrack.java | 26 +-- .../impl/BasicCaptchaTrackValidator.java | 21 +-- .../impl/SimpleImageCaptchaValidator.java | 47 ++++-- 42 files changed, 403 insertions(+), 606 deletions(-) create mode 100644 src/main/java/cloud/tianai/captcha/common/util/CaptchaTypeClassifier.java delete mode 100644 src/main/java/cloud/tianai/captcha/common/util/CaptchaUtils.java create mode 100644 src/main/java/cloud/tianai/captcha/generator/common/FontWrapper.java delete mode 100644 src/main/java/cloud/tianai/captcha/generator/common/constant/SliderCaptchaConstant.java rename src/main/java/cloud/tianai/captcha/generator/common/model/dto/{CaptchaTransferData.java => CaptchaExchange.java} (51%) rename src/main/java/cloud/tianai/captcha/generator/impl/provider/{StandardWordClickImageCaptchaGeneratorProvider.java => CommonImageCaptchaGeneratorProvider.java} (53%) delete mode 100644 src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardConcatImageCaptchaGeneratorProvider.java delete mode 100644 src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardRotateImageCaptchaGeneratorProvider.java delete mode 100644 src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardSliderImageImageCaptchaGeneratorProvider.java rename src/main/java/cloud/tianai/captcha/resource/impl/{DefaultResourceStore.java => LocalMemoryResourceStore.java} (50%) diff --git a/pom.xml b/pom.xml index 44efdcd..b617096 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 cloud.tianai.captcha tianai-captcha - 1.4.2 + 1.5.0 tianai-captcha 行为验证码 diff --git a/src/main/java/cloud/tianai/captcha/common/constant/CaptchaTypeConstant.java b/src/main/java/cloud/tianai/captcha/common/constant/CaptchaTypeConstant.java index ee4af2e..41bfa49 100644 --- a/src/main/java/cloud/tianai/captcha/common/constant/CaptchaTypeConstant.java +++ b/src/main/java/cloud/tianai/captcha/common/constant/CaptchaTypeConstant.java @@ -11,19 +11,8 @@ public interface CaptchaTypeConstant { String SLIDER = "SLIDER"; /** 旋转. */ String ROTATE = "ROTATE"; - /** 旋转角度.*/ - String ROTATE_DEGREE = "ROTATE_DEGREE"; - /** 拼接.*/ + /** 拼接. */ String CONCAT = "CONCAT"; - /** 拼图.*/ - String JIGSAW = "JIGSAW"; - /** 图片点选.*/ - String IMAGE_CLICK = "IMAGE_CLICK"; - /** 文字图片点选.*/ + /** 文字图片点选. */ String WORD_IMAGE_CLICK = "WORD_IMAGE_CLICK"; - /** 语序点选.*/ - String WORD_ORDER_IMAGE_CLICK = "WORD_ORDER_IMAGE_CLICK"; - - - } diff --git a/src/main/java/cloud/tianai/captcha/common/constant/CommonConstant.java b/src/main/java/cloud/tianai/captcha/common/constant/CommonConstant.java index c6ac1d7..6d7ac63 100644 --- a/src/main/java/cloud/tianai/captcha/common/constant/CommonConstant.java +++ b/src/main/java/cloud/tianai/captcha/common/constant/CommonConstant.java @@ -3,6 +3,20 @@ package cloud.tianai.captcha.common.constant; public interface CommonConstant { String DEFAULT_TAG = "default"; - /** 图标点选资源存储类型.*/ + /** 图标点选资源存储类型. */ String IMAGE_CLICK_ICON = "ICON"; + /** 蜂窝点选.*/ + String HONEYCOMB_CLICK_ICON = "HONEYCOMB_ICON"; + /** 刮刮卡图标. */ + String SCRAPE_ICON = "SCRAPE_ICON"; + + + /** + * 默认的resource资源文件路径. + */ + String DEFAULT_SLIDER_IMAGE_RESOURCE_PATH = "META-INF/cut-image/resource"; + /** + * 默认的template资源文件路径. + */ + String DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH = "META-INF/cut-image/template"; } diff --git a/src/main/java/cloud/tianai/captcha/common/util/CaptchaTypeClassifier.java b/src/main/java/cloud/tianai/captcha/common/util/CaptchaTypeClassifier.java new file mode 100644 index 0000000..d79567e --- /dev/null +++ b/src/main/java/cloud/tianai/captcha/common/util/CaptchaTypeClassifier.java @@ -0,0 +1,64 @@ +package cloud.tianai.captcha.common.util; + +import java.util.HashSet; +import java.util.Set; + +/** + * @Author: 天爱有情 + * @date 2023/11/2 9:22 + * @Description 验证码类型分类 + */ +public class CaptchaTypeClassifier { + + private static final Set SLIDER_CAPTCHA_TYPES = new HashSet<>(); + private static final Set CLICK_CAPTCHA_TYPES = new HashSet<>(); + private static final Set JIGSAW_CAPTCHA_TYPES = new HashSet<>(); + + public static void addSliderCaptchaType(String type) { + SLIDER_CAPTCHA_TYPES.add(type.toUpperCase()); + } + + public static void addClickCaptchaType(String type) { + CLICK_CAPTCHA_TYPES.add(type.toUpperCase()); + } + + public static boolean isSliderCaptcha(String type) { + return SLIDER_CAPTCHA_TYPES.contains(type.toUpperCase()); + } + + public static boolean isClickCaptcha(String type) { + return CLICK_CAPTCHA_TYPES.contains(type.toUpperCase()); + } + + public static Set getSliderCaptchaTypes() { + return SLIDER_CAPTCHA_TYPES; + } + + public static Set getClickCaptchaTypes() { + return CLICK_CAPTCHA_TYPES; + } + + public static void removeSliderCaptchaType(String type) { + SLIDER_CAPTCHA_TYPES.remove(type.toUpperCase()); + } + + public static void removeClickCaptchaType(String type) { + CLICK_CAPTCHA_TYPES.remove(type.toUpperCase()); + } + + public static boolean isJigsawCaptcha(String type) { + return JIGSAW_CAPTCHA_TYPES.contains(type.toUpperCase()); + } + + public static void addJigsawCaptchaType(String type) { + JIGSAW_CAPTCHA_TYPES.add(type.toUpperCase()); + } + + public static void removeJigsawCaptchaType(String type) { + JIGSAW_CAPTCHA_TYPES.remove(type.toUpperCase()); + } + + public static Set getJigsawCaptchaTypes() { + return JIGSAW_CAPTCHA_TYPES; + } +} diff --git a/src/main/java/cloud/tianai/captcha/common/util/CaptchaUtils.java b/src/main/java/cloud/tianai/captcha/common/util/CaptchaUtils.java deleted file mode 100644 index bdf3713..0000000 --- a/src/main/java/cloud/tianai/captcha/common/util/CaptchaUtils.java +++ /dev/null @@ -1,44 +0,0 @@ -package cloud.tianai.captcha.common.util; - -import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; -import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; - -/** - * @Author: 天爱有情 - * @date 2022/4/28 17:03 - * @Description 验证码工具包 - */ -public class CaptchaUtils { - - /** - * 是否是滑动验证码 - * - * @param type 类型 - * @return boolean - */ - public static boolean isSliderCaptcha(String type) { - return CaptchaTypeConstant.SLIDER.equals(type) - || CaptchaTypeConstant.ROTATE.equals(type) - || CaptchaTypeConstant.CONCAT.equals(type); - } - - /** - * 是否是点击验证码 - * - * @param type type - * @return boolean - */ - public static boolean isClickCaptcha(String type) { - return CaptchaTypeConstant.WORD_IMAGE_CLICK.equals(type) || CaptchaTypeConstant.IMAGE_CLICK.equals(type); - } - - /** - * 是否是拼图类验证码, 校验的值是 数字排列顺序 - * - * @param type 类型 - * @return boolean - */ - public static boolean isJigsawCaptcha(String type) { - return CaptchaTypeConstant.JIGSAW.equals(type); - } -} diff --git a/src/main/java/cloud/tianai/captcha/common/util/CollectionUtils.java b/src/main/java/cloud/tianai/captcha/common/util/CollectionUtils.java index f76b651..68d5b3d 100644 --- a/src/main/java/cloud/tianai/captcha/common/util/CollectionUtils.java +++ b/src/main/java/cloud/tianai/captcha/common/util/CollectionUtils.java @@ -268,7 +268,7 @@ public abstract class CollectionUtils { * @since 5.2.3 * @see SortedSet * @see LinkedHashMap#keySet() - * @see java.util.LinkedHashSet + * @see LinkedHashSet */ public static T firstElement(Set set) { if (isEmpty(set)) { @@ -307,7 +307,7 @@ public abstract class CollectionUtils { * @since 5.0.3 * @see SortedSet * @see LinkedHashMap#keySet() - * @see java.util.LinkedHashSet + * @see LinkedHashSet */ public static T lastElement(Set set) { if (isEmpty(set)) { diff --git a/src/main/java/cloud/tianai/captcha/common/util/FontUtils.java b/src/main/java/cloud/tianai/captcha/common/util/FontUtils.java index 14955c7..cbb43c8 100644 --- a/src/main/java/cloud/tianai/captcha/common/util/FontUtils.java +++ b/src/main/java/cloud/tianai/captcha/common/util/FontUtils.java @@ -2,9 +2,7 @@ package cloud.tianai.captcha.common.util; import lombok.SneakyThrows; -import java.awt.*; import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; /** * @Author: 天爱有情 diff --git a/src/main/java/cloud/tianai/captcha/common/util/ObjectUtils.java b/src/main/java/cloud/tianai/captcha/common/util/ObjectUtils.java index de57396..6d39aa0 100644 --- a/src/main/java/cloud/tianai/captcha/common/util/ObjectUtils.java +++ b/src/main/java/cloud/tianai/captcha/common/util/ObjectUtils.java @@ -17,11 +17,7 @@ package cloud.tianai.captcha.common.util; import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; -import java.util.Optional; -import java.util.StringJoiner; +import java.util.*; /** * 拷贝spring @@ -60,9 +56,9 @@ public abstract class ObjectUtils { * that is, neither a RuntimeException nor an Error. * @param ex the throwable to check * @return whether the throwable is a checked exception - * @see java.lang.Exception - * @see java.lang.RuntimeException - * @see java.lang.Error + * @see Exception + * @see RuntimeException + * @see Error */ public static boolean isCheckedException(Throwable ex) { return !(ex instanceof RuntimeException || ex instanceof Error); @@ -125,8 +121,8 @@ public abstract class ObjectUtils { * @since 4.2 * @see Optional#isPresent() * @see ObjectUtils#isEmpty(Object[]) - * @see CollectionUtils#isEmpty(java.util.Collection) - * @see CollectionUtils#isEmpty(java.util.Map) + * @see CollectionUtils#isEmpty(Collection) + * @see CollectionUtils#isEmpty(Map) */ @SuppressWarnings("rawtypes") public static boolean isEmpty(Object obj) { @@ -155,7 +151,7 @@ public abstract class ObjectUtils { } /** - * Unwrap the given object which is potentially a {@link java.util.Optional}. + * Unwrap the given object which is potentially a {@link Optional}. * @param obj the candidate object * @return either the value held within the {@code Optional}, {@code null} * if the {@code Optional} is empty, or simply the given object as-is @@ -308,7 +304,7 @@ public abstract class ObjectUtils { * @param o2 second Object to compare * @return whether the given objects are equal * @see Object#equals(Object) - * @see java.util.Arrays#equals + * @see Arrays#equals */ public static boolean nullSafeEquals(Object o1, Object o2) { if (o1 == o2) { @@ -333,7 +329,7 @@ public abstract class ObjectUtils { * @param o2 second array to compare * @return whether the given objects are equal * @see #nullSafeEquals(Object, Object) - * @see java.util.Arrays#equals + * @see Arrays#equals */ private static boolean arrayEquals(Object o1, Object o2) { if (o1 instanceof Object[] && o2 instanceof Object[]) { diff --git a/src/main/java/cloud/tianai/captcha/generator/AbstractImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/AbstractImageCaptchaGenerator.java index 6c37b2e..dd3c567 100644 --- a/src/main/java/cloud/tianai/captcha/generator/AbstractImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/AbstractImageCaptchaGenerator.java @@ -2,7 +2,7 @@ package cloud.tianai.captcha.generator; import cloud.tianai.captcha.common.exception.ImageCaptchaException; import cloud.tianai.captcha.common.util.CollectionUtils; -import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData; +import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange; import cloud.tianai.captcha.generator.common.model.dto.CustomData; import cloud.tianai.captcha.generator.common.model.dto.GenerateParam; import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo; @@ -20,7 +20,6 @@ import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.util.Collection; -import java.util.Map; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; @@ -102,21 +101,21 @@ public abstract class AbstractImageCaptchaGenerator implements ImageCaptchaGener public ImageCaptchaInfo generateCaptchaImage(GenerateParam param) { assertInit(); CustomData data = new CustomData(); - CaptchaTransferData transferData = CaptchaTransferData.create(data, param); - ImageCaptchaInfo imageCaptchaInfo = applyPostProcessorBeforeGenerate(transferData, this); + CaptchaExchange captchaExchange = CaptchaExchange.create(data, param); + ImageCaptchaInfo imageCaptchaInfo = applyPostProcessorBeforeGenerate(captchaExchange, this); if (imageCaptchaInfo != null) { return imageCaptchaInfo; } - doGenerateCaptchaImage(transferData); - applyPostProcessorBeforeWrapImageCaptchaInfo(transferData, this); - imageCaptchaInfo = wrapImageCaptchaInfo(transferData); - applyPostProcessorAfterGenerateCaptchaImage(transferData, imageCaptchaInfo, this); + doGenerateCaptchaImage(captchaExchange); + applyPostProcessorBeforeWrapImageCaptchaInfo(captchaExchange, this); + imageCaptchaInfo = wrapImageCaptchaInfo(captchaExchange); + applyPostProcessorAfterGenerateCaptchaImage(captchaExchange, imageCaptchaInfo, this); return imageCaptchaInfo; } - public ImageCaptchaInfo wrapImageCaptchaInfo(CaptchaTransferData transferData) { - ImageCaptchaInfo imageCaptchaInfo = doWrapImageCaptchaInfo(transferData); - imageCaptchaInfo.setData(transferData.getCustomData()); + public ImageCaptchaInfo wrapImageCaptchaInfo(CaptchaExchange captchaExchange) { + ImageCaptchaInfo imageCaptchaInfo = doWrapImageCaptchaInfo(captchaExchange); + imageCaptchaInfo.setData(captchaExchange.getCustomData()); return imageCaptchaInfo; } @@ -225,12 +224,12 @@ public abstract class AbstractImageCaptchaGenerator implements ImageCaptchaGener /** * 生成验证码方法 * - * @param transferData transferData + * @param captchaExchange captchaExchange * @return ImageCaptchaInfo */ - protected abstract void doGenerateCaptchaImage(CaptchaTransferData transferData); + protected abstract void doGenerateCaptchaImage(CaptchaExchange captchaExchange); - protected abstract ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData); + protected abstract ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange); @Override public ImageCaptchaResourceManager getImageResourceManager() { diff --git a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGenerator.java index 719bd29..8b88dbb 100644 --- a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGenerator.java @@ -41,7 +41,7 @@ public interface ImageCaptchaGenerator { ImageCaptchaInfo generateCaptchaImage(String type, String targetFormatName, String matrixFormatName); /** - * 生成滑块验证码 + * 生成验证码 * * @param param 生成参数 * @return SliderCaptchaInfo diff --git a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGeneratorProvider.java b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGeneratorProvider.java index 787500b..d6a6e83 100644 --- a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGeneratorProvider.java +++ b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGeneratorProvider.java @@ -24,5 +24,7 @@ public interface ImageCaptchaGeneratorProvider { * * @return String */ - String getType(); + default String getType() { + return "unknown"; + } } diff --git a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaPostProcessor.java b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaPostProcessor.java index 8174f0c..58a744c 100644 --- a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaPostProcessor.java +++ b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaPostProcessor.java @@ -1,7 +1,6 @@ package cloud.tianai.captcha.generator; -import cloud.tianai.captcha.generator.ImageCaptchaGenerator; -import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData; +import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange; import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo; /** @@ -11,15 +10,35 @@ import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo; */ public interface ImageCaptchaPostProcessor { - default ImageCaptchaInfo beforeGenerateCaptchaImage(CaptchaTransferData transferData, ImageCaptchaGenerator context) { + /** + * 在生成验证码核心逻辑之前调用, 用于拦截验证码生成、限流、自定义返回数据等处理 + * + * @param captchaExchange 传输数据 + * @param generator generator + * @return ImageCaptchaInfo + */ + default ImageCaptchaInfo beforeGenerateCaptchaImage(CaptchaExchange captchaExchange, ImageCaptchaGenerator generator) { return null; } - default void beforeWrapImageCaptchaInfo(CaptchaTransferData transferData, ImageCaptchaGenerator context) { + /** + * 在执行包装 ImageCaptchaInfo 核心逻辑之前处理 + * + * @param captchaExchange 传输数据 + * @param generator generator + */ + default void beforeWrapImageCaptchaInfo(CaptchaExchange captchaExchange, ImageCaptchaGenerator generator) { } - default void afterGenerateCaptchaImage(CaptchaTransferData transferData, ImageCaptchaInfo imageCaptchaInfo, ImageCaptchaGenerator context) { + /** + * 在执行包装 ImageCaptchaInfo 核心逻辑之后处理 + * + * @param captchaExchange captchaExchange + * @param imageCaptchaInfo imageCaptchaInfo + * @param generator generator + */ + default void afterGenerateCaptchaImage(CaptchaExchange captchaExchange, ImageCaptchaInfo imageCaptchaInfo, ImageCaptchaGenerator generator) { } } diff --git a/src/main/java/cloud/tianai/captcha/generator/ImageTransform.java b/src/main/java/cloud/tianai/captcha/generator/ImageTransform.java index e748766..dbe6ef2 100644 --- a/src/main/java/cloud/tianai/captcha/generator/ImageTransform.java +++ b/src/main/java/cloud/tianai/captcha/generator/ImageTransform.java @@ -20,10 +20,11 @@ public interface ImageTransform { * @param backgroundImage 背景图片 * @param param 参数 * @param backgroundResource 背景资源对象 + * @param data 自定义透传数据 * @return ImageTransformData */ - default ImageTransformData transform(GenerateParam param, BufferedImage backgroundImage, Resource backgroundResource,CustomData data) { - return transform(param, backgroundImage, null, backgroundResource, null,data); + default ImageTransformData transform(GenerateParam param, BufferedImage backgroundImage, Resource backgroundResource, CustomData data) { + return transform(param, backgroundImage, null, backgroundResource, null, data); } /** @@ -34,6 +35,7 @@ public interface ImageTransform { * @param param 参数 * @param backgroundResource 背景资源对象 * @param templateResource 模板资源对象(可能为空) + * @param data 自定义透传数据 * @return String */ ImageTransformData transform(GenerateParam param, diff --git a/src/main/java/cloud/tianai/captcha/generator/common/FontWrapper.java b/src/main/java/cloud/tianai/captcha/generator/common/FontWrapper.java new file mode 100644 index 0000000..7f4f59c --- /dev/null +++ b/src/main/java/cloud/tianai/captcha/generator/common/FontWrapper.java @@ -0,0 +1,15 @@ +package cloud.tianai.captcha.generator.common; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.awt.*; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FontWrapper { + private Font font; + private float currentFontTopCoef; +} diff --git a/src/main/java/cloud/tianai/captcha/generator/common/constant/SliderCaptchaConstant.java b/src/main/java/cloud/tianai/captcha/generator/common/constant/SliderCaptchaConstant.java deleted file mode 100644 index 46b0a58..0000000 --- a/src/main/java/cloud/tianai/captcha/generator/common/constant/SliderCaptchaConstant.java +++ /dev/null @@ -1,18 +0,0 @@ -package cloud.tianai.captcha.generator.common.constant; - -/** - * @Author: 天爱有情 - * @date 2021/8/7 17:14 - * @Description 滑块验证码常量 - */ -public interface SliderCaptchaConstant { - - /** 模板滑块固定名称. */ - String TEMPLATE_ACTIVE_IMAGE_NAME = "active.png"; - /** 模板凹槽固定名称. */ - String TEMPLATE_FIXED_IMAGE_NAME = "fixed.png"; - /** 模板蒙版. */ - String TEMPLATE_MASK_IMAGE_NAME = "mask.png"; - /** 混淆的凹槽.*/ - String OBFUSCATE_TEMPLATE_FIXED_IMAGE_NAME = "obfuscate_" + TEMPLATE_FIXED_IMAGE_NAME; -} diff --git a/src/main/java/cloud/tianai/captcha/generator/common/model/dto/CaptchaTransferData.java b/src/main/java/cloud/tianai/captcha/generator/common/model/dto/CaptchaExchange.java similarity index 51% rename from src/main/java/cloud/tianai/captcha/generator/common/model/dto/CaptchaTransferData.java rename to src/main/java/cloud/tianai/captcha/generator/common/model/dto/CaptchaExchange.java index 80d418d..31647ec 100644 --- a/src/main/java/cloud/tianai/captcha/generator/common/model/dto/CaptchaTransferData.java +++ b/src/main/java/cloud/tianai/captcha/generator/common/model/dto/CaptchaExchange.java @@ -12,24 +12,30 @@ import java.awt.image.BufferedImage; * @Description 传输用 */ @Data -public class CaptchaTransferData { +public class CaptchaExchange { + /** 模板对象. */ private ResourceMap templateResource; + /** 资源对象. */ private Resource resourceImage; + /** 生成好的背景图片. */ private BufferedImage backgroundImage; + /** 生成好的模板图片. */ private BufferedImage templateImage; + /** 最终要回调给验证器的自定义对象. */ private CustomData customData; + /** 用户传来的生成参数. */ private GenerateParam param; - + /** 传输对象,扩展自定义. */ private Object transferData; - public static CaptchaTransferData create(CustomData customData, GenerateParam param) { - CaptchaTransferData captchaTransferData = new CaptchaTransferData(); - captchaTransferData.setCustomData(customData); - captchaTransferData.setParam(param); - return captchaTransferData; + public static CaptchaExchange create(CustomData customData, GenerateParam param) { + CaptchaExchange captchaExchange = new CaptchaExchange(); + captchaExchange.setCustomData(customData); + captchaExchange.setParam(param); + return captchaExchange; } - public static CaptchaTransferData create(GenerateParam param) { + public static CaptchaExchange create(GenerateParam param) { return create(new CustomData(), param); } } diff --git a/src/main/java/cloud/tianai/captcha/generator/common/model/dto/ClickImageCheckDefinition.java b/src/main/java/cloud/tianai/captcha/generator/common/model/dto/ClickImageCheckDefinition.java index 772e461..79136e0 100644 --- a/src/main/java/cloud/tianai/captcha/generator/common/model/dto/ClickImageCheckDefinition.java +++ b/src/main/java/cloud/tianai/captcha/generator/common/model/dto/ClickImageCheckDefinition.java @@ -5,6 +5,8 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import java.awt.*; + /** * @Author: 天爱有情 * @date 2022/4/28 16:51 @@ -24,5 +26,7 @@ public class ClickImageCheckDefinition { private Integer width; /** 高.*/ private Integer height; + /** 颜色.*/ + private Color imageColor; } diff --git a/src/main/java/cloud/tianai/captcha/generator/common/model/dto/ImageCaptchaInfo.java b/src/main/java/cloud/tianai/captcha/generator/common/model/dto/ImageCaptchaInfo.java index f3a5376..5249649 100644 --- a/src/main/java/cloud/tianai/captcha/generator/common/model/dto/ImageCaptchaInfo.java +++ b/src/main/java/cloud/tianai/captcha/generator/common/model/dto/ImageCaptchaInfo.java @@ -36,7 +36,6 @@ public class ImageCaptchaInfo { private Float tolerant; /** 验证码类型. */ private String type; - /** 透传字段,用于传给前端. */ private CustomData data; public ImageCaptchaInfo(String backgroundImage, diff --git a/src/main/java/cloud/tianai/captcha/generator/common/util/CaptchaImageUtils.java b/src/main/java/cloud/tianai/captcha/generator/common/util/CaptchaImageUtils.java index 66b19f9..8e5f809 100644 --- a/src/main/java/cloud/tianai/captcha/generator/common/util/CaptchaImageUtils.java +++ b/src/main/java/cloud/tianai/captcha/generator/common/util/CaptchaImageUtils.java @@ -9,15 +9,11 @@ import java.awt.geom.CubicCurve2D; import java.awt.geom.QuadCurve2D; import java.awt.image.BufferedImage; import java.awt.image.PixelGrabber; -import java.awt.image.RenderedImage; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; -import java.util.concurrent.atomic.AtomicInteger; /** * @Author: 天爱有情 @@ -75,25 +71,6 @@ public class CaptchaImageUtils { } - public static int getMaxPix(BufferedImage image, int x, int y, int width, int height) { - int[] rgbArr = new int[width * height]; - image.getRGB(x, y, width, height, rgbArr, 0, width); - Map map = new HashMap<>(); - for (int rgb : rgbArr) { - Integer count = map.getOrDefault(rgb, 0); - map.put(rgb, count + 1); - } - AtomicInteger maxRgb = new AtomicInteger(); - AtomicInteger maxRgbCount = new AtomicInteger(); - map.forEach((r, c) -> { - if (c > maxRgbCount.get()) { - maxRgb.set(r); - maxRgbCount.set(c); - } - }); - return maxRgb.get(); - } - /** * 将Image图像中的透明/不透明部分转换为Shape图形 * @@ -195,48 +172,6 @@ public class CaptchaImageUtils { } - @SneakyThrows - public static BufferedImage cutImage_bak(BufferedImage origin, BufferedImage template, int x, int y) { - int bw = template.getWidth(null); - int bh = template.getHeight(null); - int lw = origin.getWidth(null); - int lh = origin.getHeight(null); - //得到透明的区域(人物轮廓) - Shape imageShape = getImageShape(template, false); - long end = System.currentTimeMillis(); - //合成后的图片 - BufferedImage image = new BufferedImage(bw, bh, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = image.createGraphics(); - //设置画布为透明 - image = graphics.getDeviceConfiguration().createCompatibleImage(bw, bh, Transparency.TRANSLUCENT); - graphics.dispose(); - Graphics2D graphics2 = image.createGraphics(); - //取交集(限制可以画的范围为shape的范围) - graphics2.clip(imageShape); - //抗锯齿 - graphics2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics2.setStroke(new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - graphics2.drawImage(origin, -x, -y, lw, lh, null); - graphics2.dispose(); - return image; - } - - public static void replaceColorByOpaque(BufferedImage oriImage, int replaceRgb) { - int bh = oriImage.getHeight(); - int bw = oriImage.getWidth(); - // 透明色 - for (int y = 0; y < bh; y++) { - for (int x = 0; x < bw; x++) { - int rgb = oriImage.getRGB(x, y); - int alpha = (rgb >> 24) & 0xff; - // 透明度大于100才处理,过滤一下边缘过于透明的像素点 - if (alpha > 100) { - oriImage.setRGB(x, y, replaceRgb); - } - } - } - } - /** * 旋转图片 * @@ -278,26 +213,6 @@ public class CaptchaImageUtils { } - /** - * 通过x和y轴截取图片 - * - * @param x x - * @param y y - * @param width 宽度 - * @param height 高度 - * @param img 截取的图片 - * @return BufferedImage - */ - public static BufferedImage subImage(int x, int y, int width, int height, BufferedImage img) { - int[] simgRgb = new int[width * height]; - img.getRGB(x, y, width, height, simgRgb, 0, width); - // 得到图片透明度。 - int type = img.getColorModel().getTransparency(); - BufferedImage newImage = new BufferedImage(width, height, type); - newImage.setRGB(0, 0, width, height, simgRgb, 0, width); - return newImage; - } - /** * 分隔图片 * @@ -354,11 +269,11 @@ public class CaptchaImageUtils { for (BufferedImage img : imgArr) { if (direction) { // 水平方向 - graphics.drawImage(img, pos, 0, img.getWidth(), img.getHeight(),null); + graphics.drawImage(img, pos, 0, img.getWidth(), img.getHeight(), null); pos += img.getWidth(); } else { // 垂直方向 - graphics.drawImage(img, 0, pos, img.getWidth(), img.getHeight(),null); + graphics.drawImage(img, 0, pos, img.getWidth(), img.getHeight(), null); pos += img.getHeight(); } } @@ -366,10 +281,6 @@ public class CaptchaImageUtils { return newImage; } - public static char getRandomChar() { - return (char) (0x4e00 + (int) (Math.random() * (0x9fa5 - 0x4e00 + 1))); - } - @SneakyThrows public static BufferedImage drawWordImg(Color fontColor, @@ -497,23 +408,6 @@ public class CaptchaImageUtils { } - public static void drawInterfere(Graphics2D g, int width, - int height, - int interferenceLineNum, - int interferencePointNum) { - ThreadLocalRandom random = ThreadLocalRandom.current(); - // 干扰点 - if (interferencePointNum > 0) { - drawOval(interferencePointNum, null, g, width, height, random); - } - if (interferencePointNum > 0) { - g.setStroke(new BasicStroke(1.2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL)); - // 干扰线 - drawBesselLine(interferenceLineNum, null, g, width, height, random); - } - } - - /** * 随机获取颜色 * @@ -527,12 +421,6 @@ public class CaptchaImageUtils { } - public static RenderedImage toRenderedImage(Image img) { - if (img instanceof RenderedImage) { - return (RenderedImage) img; - } - return copyImage(img, BufferedImage.TYPE_INT_RGB); - } /** * 转换成指定类型的 BufferedImage @@ -595,30 +483,6 @@ public class CaptchaImageUtils { return bimage; } - /** - * 灰度处理,把原图传进去,传出来为修改后的图 - * - * @param b b - * @return BufferedImage - */ - public static BufferedImage gray(BufferedImage b) { - int width = b.getWidth(); - int height = b.getHeight(); - // 下面这个别忘了定义,不然会出错 - BufferedImage bufferedImageEnd = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); - // 双层循环更改图片的RGB值,把得到的灰度值存到bufferedImage_end中,然后返回bufferedImage_end - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - // 获取到(x,y)此像素点的Colo,转化为灰度 - Color color = new Color(b.getRGB(x, y)); - int gray = (int) (color.getRed() * 0.299 + color.getGreen() * 0.587 + color.getBlue() * 0.114); - Color color_end = new Color(gray, gray, gray); - bufferedImageEnd.setRGB(x, y, color_end.getRGB()); - } - } - return bufferedImageEnd; - } - /** * 创建画板 * @@ -636,21 +500,6 @@ public class CaptchaImageUtils { return g; } - public static BufferedImage toBufferedImage(Image img) { - if (img instanceof BufferedImage) { - return (BufferedImage) img; - } - // Create a buffered image with transparency - BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); - // Draw the image on to the buffered image - Graphics2D bGr = bimage.createGraphics(); - bGr.drawImage(img, 0, 0, null); - bGr.dispose(); - // Return the buffered image - return bimage; - } - - /** * 后缀是否是jpg * @@ -672,3 +521,4 @@ public class CaptchaImageUtils { } } + diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/AbstractClickImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/AbstractClickImageCaptchaGenerator.java index 4013983..7c0e0f8 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/AbstractClickImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/AbstractClickImageCaptchaGenerator.java @@ -1,10 +1,9 @@ package cloud.tianai.captcha.generator.impl; import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator; -import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData; +import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange; import cloud.tianai.captcha.generator.common.model.dto.ClickImageCheckDefinition; import cloud.tianai.captcha.generator.common.model.dto.GenerateParam; -import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo; import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils; import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; import cloud.tianai.captcha.resource.common.model.dto.Resource; @@ -13,10 +12,10 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.SneakyThrows; +import java.awt.*; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ThreadLocalRandom; /** * @Author: 天爱有情 @@ -25,6 +24,7 @@ import java.util.concurrent.ThreadLocalRandom; */ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCaptchaGenerator { + public static final String CLICK_IMAGE_DISTORT_KEY = "clickImageDistort"; public AbstractClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) { super(imageCaptchaResourceManager); @@ -35,8 +35,8 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa @SneakyThrows @Override - public void doGenerateCaptchaImage(CaptchaTransferData transferData) { - GenerateParam param = transferData.getParam(); + public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) { + GenerateParam param = captchaExchange.getParam(); // 文字点选验证码不需要模板 只需要背景图 Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag()); @@ -65,19 +65,20 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa // 随机y int randomY = randomInt(10, bgImage.getHeight() - clickImgHeight); // 通过随机x和y 进行覆盖图片 - CaptchaImageUtils.overlayImage(bgImage, imgWrapper.getImage(), randomX, randomY); + CaptchaImageUtils.overlayImage(bgImage, image, randomX, randomY); ClickImageCheckDefinition clickImageCheckDefinition = new ClickImageCheckDefinition(); clickImageCheckDefinition.setTip(imgWrapper.getTip()); clickImageCheckDefinition.setX(randomX + clickImgWidth / 2); clickImageCheckDefinition.setY(randomY + clickImgHeight / 2); clickImageCheckDefinition.setWidth(clickImgWidth); clickImageCheckDefinition.setHeight(clickImgHeight); + clickImageCheckDefinition.setImageColor(imgWrapper.getImageColor()); clickImageCheckDefinitionList.add(clickImageCheckDefinition); } List checkClickImageCheckDefinitionList = filterAndSortClickImageCheckDefinition(clickImageCheckDefinitionList); - transferData.setBackgroundImage(bgImage); - transferData.setTransferData(checkClickImageCheckDefinitionList); - transferData.setResourceImage(resourceImage); + captchaExchange.setBackgroundImage(bgImage); + captchaExchange.setTransferData(checkClickImageCheckDefinitionList); + captchaExchange.setResourceImage(resourceImage); // // wrap @@ -123,5 +124,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa private BufferedImage image; /** 提示. */ private Resource tip; + /** 图片颜色. */ + private Color imageColor; } } diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/MultiImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/MultiImageCaptchaGenerator.java index 29b8450..6c7fbc1 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/MultiImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/MultiImageCaptchaGenerator.java @@ -1,18 +1,14 @@ package cloud.tianai.captcha.generator.impl; -import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; import cloud.tianai.captcha.common.util.ObjectUtils; 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.model.dto.CaptchaTransferData; +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; -import cloud.tianai.captcha.generator.impl.provider.StandardConcatImageCaptchaGeneratorProvider; -import cloud.tianai.captcha.generator.impl.provider.StandardWordClickImageCaptchaGeneratorProvider; -import cloud.tianai.captcha.generator.impl.provider.StandardRotateImageCaptchaGeneratorProvider; -import cloud.tianai.captcha.generator.impl.provider.StandardSliderImageImageCaptchaGeneratorProvider; +import cloud.tianai.captcha.generator.impl.provider.CommonImageCaptchaGeneratorProvider; import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; import lombok.Getter; import lombok.Setter; @@ -21,6 +17,8 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static cloud.tianai.captcha.common.constant.CaptchaTypeConstant.*; + /** * @Author: 天爱有情 * @date 2022/4/24 9:27 @@ -33,7 +31,7 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator { @Setter @Getter - private String defaultCaptcha = CaptchaTypeConstant.SLIDER; + private String defaultCaptcha = SLIDER; protected boolean initDefaultResource = false; @@ -49,14 +47,15 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator { @Override protected void doInit(boolean initDefaultResource) { this.initDefaultResource = initDefaultResource; + // 滑块验证码 - addImageCaptchaGeneratorProvider(new StandardSliderImageImageCaptchaGeneratorProvider()); + addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(SLIDER, StandardSliderImageCaptchaGenerator::new)); // 旋转验证码 - addImageCaptchaGeneratorProvider(new StandardRotateImageCaptchaGeneratorProvider()); + addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(ROTATE, StandardRotateImageCaptchaGenerator::new)); // 拼接验证码 - addImageCaptchaGeneratorProvider(new StandardConcatImageCaptchaGeneratorProvider()); + addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(CONCAT, StandardConcatImageCaptchaGenerator::new)); // 点选文字验证码 - addImageCaptchaGeneratorProvider(new StandardWordClickImageCaptchaGeneratorProvider()); + addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(WORD_IMAGE_CLICK, StandardWordClickImageCaptchaGenerator::new)); } public void addImageCaptchaGeneratorProvider(ImageCaptchaGeneratorProvider provider) { @@ -96,12 +95,12 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator { @Override - protected void doGenerateCaptchaImage(CaptchaTransferData transferData) { + protected void doGenerateCaptchaImage(CaptchaExchange captchaExchange) { } @Override - protected ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) { + protected ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) { return null; } diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/StandardConcatImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/StandardConcatImageCaptchaGenerator.java index 0901437..1267567 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardConcatImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardConcatImageCaptchaGenerator.java @@ -11,15 +11,11 @@ import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider; import lombok.SneakyThrows; import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.util.Collection; -import java.util.LinkedList; -import java.util.concurrent.ThreadLocalRandom; +import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH; import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG; -import static cloud.tianai.captcha.generator.common.util.CaptchaImageUtils.*; -import static cloud.tianai.captcha.generator.impl.StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH; +import static cloud.tianai.captcha.generator.common.util.CaptchaImageUtils.concatImage; +import static cloud.tianai.captcha.generator.common.util.CaptchaImageUtils.splitImage; /** * @Author: 天爱有情 @@ -51,8 +47,8 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen } @Override - public void doGenerateCaptchaImage(CaptchaTransferData transferData) { - GenerateParam param = transferData.getParam(); + public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) { + GenerateParam param = captchaExchange.getParam(); // 拼接验证码不需要模板 只需要背景图 Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag()); BufferedImage bgImage = getResourceImage(resourceImage); @@ -72,9 +68,9 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen data.x = randomX; data.y = randomY; - transferData.setTransferData(data); - transferData.setBackgroundImage(bgImage); - transferData.setResourceImage(resourceImage); + captchaExchange.setTransferData(data); + captchaExchange.setBackgroundImage(bgImage); + captchaExchange.setResourceImage(resourceImage); } public static class Data { @@ -84,13 +80,13 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen @SneakyThrows @Override - public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) { - GenerateParam param = transferData.getParam(); - BufferedImage bgImage = transferData.getBackgroundImage(); - Resource resourceImage = transferData.getResourceImage(); - CustomData customData = transferData.getCustomData(); + public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) { + GenerateParam param = captchaExchange.getParam(); + BufferedImage bgImage = captchaExchange.getBackgroundImage(); + Resource resourceImage = captchaExchange.getResourceImage(); + CustomData customData = captchaExchange.getCustomData(); ImageTransformData transform = getImageTransform().transform(param, bgImage, resourceImage, customData); - Data data = (Data) transferData.getTransferData(); + Data data = (Data) captchaExchange.getTransferData(); ImageCaptchaInfo imageCaptchaInfo = ImageCaptchaInfo.of(transform.getBackgroundImageUrl(), null, resourceImage.getTag(), diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/StandardRotateImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/StandardRotateImageCaptchaGenerator.java index 37419b1..c7ea3b1 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardRotateImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardRotateImageCaptchaGenerator.java @@ -4,7 +4,6 @@ import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; import cloud.tianai.captcha.common.constant.CommonConstant; import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator; import cloud.tianai.captcha.generator.ImageTransform; -import cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant; import cloud.tianai.captcha.generator.common.model.dto.*; import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils; import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; @@ -15,14 +14,9 @@ import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider; import lombok.SneakyThrows; import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; +import java.util.Optional; -import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG; -import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant.*; -import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant.TEMPLATE_MASK_IMAGE_NAME; +import static cloud.tianai.captcha.common.constant.CommonConstant.*; /** * @Author: 天爱有情 @@ -31,6 +25,13 @@ import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConsta */ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGenerator { + /** 模板滑块固定名称. */ + public static String TEMPLATE_ACTIVE_IMAGE_NAME = "active.png"; + /** 模板凹槽固定名称. */ + public static String TEMPLATE_FIXED_IMAGE_NAME = "fixed.png"; + /** 模板蒙版. */ + public static String TEMPLATE_MASK_IMAGE_NAME = "mask.png"; + public StandardRotateImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) { super(imageCaptchaResourceManager); } @@ -50,18 +51,24 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen public void initDefaultResource() { ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore(); // 添加一些系统的资源文件 - resourceStore.addResource(CaptchaTypeConstant.ROTATE, new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG)); + resourceStore.addResource(CaptchaTypeConstant.ROTATE, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG)); // 添加一些系统的 模板文件 ResourceMap template1 = new ResourceMap(DEFAULT_TAG, 4); - template1.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/active.png"))); - template1.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/fixed.png"))); + template1.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/active.png"))); + template1.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/fixed.png"))); resourceStore.addTemplate(CaptchaTypeConstant.ROTATE, template1); + + ResourceMap template2 = new ResourceMap(CommonConstant.DEFAULT_TAG + "_obfuscate", 4); + template2.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/4/active.png"))); + template2.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/4/fixed.png"))); + template2.put(TEMPLATE_MASK_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/4/mask.png"))); + resourceStore.addTemplate(CaptchaTypeConstant.ROTATE, template2); } @Override - public void doGenerateCaptchaImage(CaptchaTransferData transferData) { - GenerateParam param = transferData.getParam(); + public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) { + GenerateParam param = captchaExchange.getParam(); CustomData data = new CustomData(); ResourceMap templateResource = requiredRandomGetTemplate(param.getType(), param.getTemplateImageTag()); Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag()); @@ -96,17 +103,17 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen int randomX = randomInt(fixedTemplate.getWidth() + 10, background.getWidth() - 10); double degree = 360d - randomX / ((background.getWidth()) / 360d); // 旋转的透明图片是一张正方形的 - BufferedImage matrixTemplate = CaptchaImageUtils.createTransparentImage(background.getHeight(), background.getHeight()); + BufferedImage matrixTemplate = CaptchaImageUtils.createTransparentImage(cutImage.getWidth(), background.getHeight()); CaptchaImageUtils.centerOverlayAndRotateImage(matrixTemplate, cutImage, degree); RotateData rotateData = new RotateData(); rotateData.degree = degree; rotateData.randomX = randomX; - transferData.setTransferData(rotateData); - transferData.setBackgroundImage(background); - transferData.setTemplateImage(matrixTemplate); - transferData.setTemplateResource(templateResource); - transferData.setResourceImage(resourceImage); + captchaExchange.setTransferData(rotateData); + captchaExchange.setBackgroundImage(background); + captchaExchange.setTemplateImage(matrixTemplate); + captchaExchange.setTemplateResource(templateResource); + captchaExchange.setResourceImage(resourceImage); // return wrapRotateCaptchaInfo(degree, randomX, background, matrixTemplate, param, templateResource, resourceImage, data); } @@ -125,14 +132,14 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen @SneakyThrows @Override - public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) { - GenerateParam param = transferData.getParam(); - BufferedImage backgroundImage = transferData.getBackgroundImage(); - BufferedImage sliderImage = transferData.getTemplateImage(); - Resource resourceImage = transferData.getResourceImage(); - ResourceMap templateResource = transferData.getTemplateResource(); - CustomData data = transferData.getCustomData(); - RotateData rotateData = (RotateData) transferData.getTransferData(); + public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) { + GenerateParam param = captchaExchange.getParam(); + BufferedImage backgroundImage = captchaExchange.getBackgroundImage(); + BufferedImage sliderImage = captchaExchange.getTemplateImage(); + Resource resourceImage = captchaExchange.getResourceImage(); + ResourceMap templateResource = captchaExchange.getTemplateResource(); + CustomData data = captchaExchange.getCustomData(); + RotateData rotateData = (RotateData) captchaExchange.getTransferData(); ImageTransformData transform = getImageTransform().transform(param, backgroundImage, sliderImage, resourceImage, templateResource, data); RotateImageCaptchaInfo imageCaptchaInfo = RotateImageCaptchaInfo.of(rotateData.degree, rotateData.randomX, diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/StandardSliderImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/StandardSliderImageCaptchaGenerator.java index f6ea0e8..74db479 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardSliderImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardSliderImageCaptchaGenerator.java @@ -3,7 +3,6 @@ package cloud.tianai.captcha.generator.impl; import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator; import cloud.tianai.captcha.generator.ImageTransform; -import cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant; import cloud.tianai.captcha.generator.common.model.dto.*; import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils; import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; @@ -16,14 +15,10 @@ import lombok.extern.slf4j.Slf4j; import java.awt.*; import java.awt.image.BufferedImage; -import java.io.IOException; -import java.io.InputStream; -import java.util.*; +import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; -import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG; -import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant.*; -import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME; +import static cloud.tianai.captcha.common.constant.CommonConstant.*; /** * @Author: 天爱有情 @@ -33,14 +28,16 @@ import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConsta @Slf4j public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGenerator { - /** - * 默认的resource资源文件路径. - */ - public static final String DEFAULT_SLIDER_IMAGE_RESOURCE_PATH = "META-INF/cut-image/resource"; - /** - * 默认的template资源文件路径. - */ - public static final String DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH = "META-INF/cut-image/template"; + + /** 模板滑块固定名称. */ + public static String TEMPLATE_ACTIVE_IMAGE_NAME = "active.png"; + /** 模板凹槽固定名称. */ + public static String TEMPLATE_FIXED_IMAGE_NAME = "fixed.png"; + /** 模板蒙版. */ + public static String TEMPLATE_MASK_IMAGE_NAME = "mask.png"; + /** 混淆的凹槽. */ + public static String OBFUSCATE_TEMPLATE_FIXED_IMAGE_NAME = "obfuscate_" + TEMPLATE_FIXED_IMAGE_NAME; + public StandardSliderImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) { super(imageCaptchaResourceManager); @@ -60,8 +57,8 @@ public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGen @SneakyThrows @Override - public void doGenerateCaptchaImage(CaptchaTransferData transferData) { - GenerateParam param = transferData.getParam(); + public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) { + GenerateParam param = captchaExchange.getParam(); Boolean obfuscate = param.getObfuscate(); ResourceMap templateResource = requiredRandomGetTemplate(param.getType(), param.getTemplateImageTag()); Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag()); @@ -93,15 +90,15 @@ public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGen XandY xandY = new XandY(); xandY.x = randomX; xandY.y = randomY; - transferData.setBackgroundImage(background); - transferData.setTemplateImage(matrixTemplate); - transferData.setTemplateResource(templateResource); - transferData.setResourceImage(resourceImage); - transferData.setTransferData(xandY); + captchaExchange.setBackgroundImage(background); + captchaExchange.setTemplateImage(matrixTemplate); + captchaExchange.setTemplateResource(templateResource); + captchaExchange.setResourceImage(resourceImage); + captchaExchange.setTransferData(xandY); // 后处理 -// applyPostProcessorBeforeWrapImageCaptchaInfo(transferData, this); -// imageCaptchaInfo = wrapSliderCaptchaInfo(randomX, randomY, transferData); -// applyPostProcessorAfterGenerateCaptchaImage(transferData, imageCaptchaInfo, this); +// applyPostProcessorBeforeWrapImageCaptchaInfo(captchaExchange, this); +// imageCaptchaInfo = wrapSliderCaptchaInfo(randomX, randomY, captchaExchange); +// applyPostProcessorAfterGenerateCaptchaImage(captchaExchange, imageCaptchaInfo, this); // return imageCaptchaInfo; } @@ -134,14 +131,14 @@ public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGen @SneakyThrows @Override - public SliderImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) { - GenerateParam param = transferData.getParam(); - BufferedImage backgroundImage = transferData.getBackgroundImage(); - BufferedImage sliderImage = transferData.getTemplateImage(); - Resource resourceImage = transferData.getResourceImage(); - ResourceMap templateResource = transferData.getTemplateResource(); - CustomData customData = transferData.getCustomData(); - XandY data = (XandY) transferData.getTransferData(); + public SliderImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) { + GenerateParam param = captchaExchange.getParam(); + BufferedImage backgroundImage = captchaExchange.getBackgroundImage(); + BufferedImage sliderImage = captchaExchange.getTemplateImage(); + Resource resourceImage = captchaExchange.getResourceImage(); + ResourceMap templateResource = captchaExchange.getTemplateResource(); + CustomData customData = captchaExchange.getCustomData(); + XandY data = (XandY) captchaExchange.getTransferData(); ImageTransformData transform = getImageTransform().transform(param, backgroundImage, sliderImage, resourceImage, templateResource, customData); SliderImageCaptchaInfo imageCaptchaInfo = SliderImageCaptchaInfo.of(data.x, data.y, diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/StandardWordClickImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/StandardWordClickImageCaptchaGenerator.java index 1787d4a..d1b679a 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardWordClickImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardWordClickImageCaptchaGenerator.java @@ -4,13 +4,16 @@ import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; 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.resource.ImageCaptchaResourceManager; import cloud.tianai.captcha.resource.ResourceStore; import cloud.tianai.captcha.resource.common.model.dto.Resource; import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider; -import lombok.*; +import lombok.Getter; +import lombok.Setter; +import lombok.SneakyThrows; import java.awt.*; import java.awt.image.BufferedImage; @@ -22,6 +25,7 @@ import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; +import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH; import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG; /** @@ -114,7 +118,7 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa public void initDefaultResource() { ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore(); // 添加一些系统的资源文件 - resourceStore.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG)); + resourceStore.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG)); } public ImgWrapper genTipImage(List imageCheckDefinitions) { @@ -130,7 +134,7 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa float top = 6 / 2f + font.getSize() - currentFontTopCoef; BufferedImage bufferedImage = CaptchaImageUtils.genSimpleImgCaptcha(tips, font, width, height, left, top, tipImageInterferenceLineNum, tipImageInterferencePointNum); - return new ImgWrapper(bufferedImage, new Resource(null, tips)); + return new ImgWrapper(bufferedImage, new Resource(null, tips), null); } @Override @@ -150,7 +154,7 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa clickImgWidth, clickImgHeight, randomDeg); - return new ImgWrapper(fontImage, tip); + return new ImgWrapper(fontImage, tip, randomColor); } @Override @@ -167,12 +171,12 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa } @Override - public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) { - List checkClickImageCheckDefinitionList = (List) transferData.getTransferData(); - BufferedImage bgImage = transferData.getBackgroundImage(); - GenerateParam param = transferData.getParam(); - Resource resourceImage = transferData.getResourceImage(); - CustomData data = transferData.getCustomData(); + public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) { + List checkClickImageCheckDefinitionList = (List) captchaExchange.getTransferData(); + BufferedImage bgImage = captchaExchange.getBackgroundImage(); + GenerateParam param = captchaExchange.getParam(); + Resource resourceImage = captchaExchange.getResourceImage(); + CustomData data = captchaExchange.getCustomData(); // 提示图片 BufferedImage tipImage = genTipImage(checkClickImageCheckDefinitionList).getImage(); ImageTransformData transform = getImageTransform().transform(param, bgImage, tipImage, resourceImage, checkClickImageCheckDefinitionList, data); @@ -191,12 +195,5 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa return clickImageCaptchaInfo; } - @Data - @NoArgsConstructor - @AllArgsConstructor - public static class FontWrapper { - private Font font; - private float currentFontTopCoef; - } -} +} diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/StaticCaptchaPostProcessorManager.java b/src/main/java/cloud/tianai/captcha/generator/impl/StaticCaptchaPostProcessorManager.java index 186f260..8438d21 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/StaticCaptchaPostProcessorManager.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/StaticCaptchaPostProcessorManager.java @@ -3,7 +3,7 @@ package cloud.tianai.captcha.generator.impl; import cloud.tianai.captcha.common.exception.ImageCaptchaException; import cloud.tianai.captcha.generator.ImageCaptchaGenerator; import cloud.tianai.captcha.generator.ImageCaptchaPostProcessor; -import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData; +import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange; import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo; import lombok.Getter; @@ -20,10 +20,6 @@ public class StaticCaptchaPostProcessorManager { @Getter private static LinkedList processors = new LinkedList<>(); - static { - - } - public static void add(ImageCaptchaPostProcessor processor) { processors.add(processor); } @@ -49,10 +45,10 @@ public class StaticCaptchaPostProcessorManager { } - public static ImageCaptchaInfo applyPostProcessorBeforeGenerate(CaptchaTransferData transferData, ImageCaptchaGenerator context) { + public static ImageCaptchaInfo applyPostProcessorBeforeGenerate(CaptchaExchange captchaExchange, ImageCaptchaGenerator context) { for (ImageCaptchaPostProcessor processor : processors) { try { - ImageCaptchaInfo imageCaptchaInfo = processor.beforeGenerateCaptchaImage(transferData, context); + ImageCaptchaInfo imageCaptchaInfo = processor.beforeGenerateCaptchaImage(captchaExchange, context); if (imageCaptchaInfo != null) { return imageCaptchaInfo; } @@ -63,10 +59,10 @@ public class StaticCaptchaPostProcessorManager { return null; } - public static void applyPostProcessorBeforeWrapImageCaptchaInfo(CaptchaTransferData transferData, ImageCaptchaGenerator context) { + public static void applyPostProcessorBeforeWrapImageCaptchaInfo(CaptchaExchange captchaExchange, ImageCaptchaGenerator context) { for (ImageCaptchaPostProcessor processor : processors) { try { - processor.beforeWrapImageCaptchaInfo(transferData, context); + processor.beforeWrapImageCaptchaInfo(captchaExchange, context); } catch (Exception e) { throw new ImageCaptchaException("apply ImageCaptchaPostProcessor.beforeWrapImageCaptchaInfo error, [" + processor.getClass() + "]", e); } @@ -74,10 +70,10 @@ public class StaticCaptchaPostProcessorManager { } - public static void applyPostProcessorAfterGenerateCaptchaImage(CaptchaTransferData transferData, ImageCaptchaInfo imageCaptchaInfo, ImageCaptchaGenerator context) { + public static void applyPostProcessorAfterGenerateCaptchaImage(CaptchaExchange captchaExchange, ImageCaptchaInfo imageCaptchaInfo, ImageCaptchaGenerator context) { for (ImageCaptchaPostProcessor processor : processors) { try { - processor.afterGenerateCaptchaImage(transferData, imageCaptchaInfo, context); + processor.afterGenerateCaptchaImage(captchaExchange, imageCaptchaInfo, context); } catch (Exception e) { throw new ImageCaptchaException("apply ImageCaptchaPostProcessor.afterGenerateCaptchaImage error, [" + processor.getClass() + "]", e); } diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardWordClickImageCaptchaGeneratorProvider.java b/src/main/java/cloud/tianai/captcha/generator/impl/provider/CommonImageCaptchaGeneratorProvider.java similarity index 53% rename from src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardWordClickImageCaptchaGeneratorProvider.java rename to src/main/java/cloud/tianai/captcha/generator/impl/provider/CommonImageCaptchaGeneratorProvider.java index 57ad90d..f5414e6 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardWordClickImageCaptchaGeneratorProvider.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/provider/CommonImageCaptchaGeneratorProvider.java @@ -1,20 +1,28 @@ package cloud.tianai.captcha.generator.impl.provider; -import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; import cloud.tianai.captcha.generator.ImageCaptchaGenerator; import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider; import cloud.tianai.captcha.generator.ImageTransform; -import cloud.tianai.captcha.generator.impl.StandardWordClickImageCaptchaGenerator; import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; -public class StandardWordClickImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider { +public class CommonImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider { + + private String type; + private ImageCaptchaGeneratorProvider provider; + + public CommonImageCaptchaGeneratorProvider(String type, ImageCaptchaGeneratorProvider provider) { + this.type = type; + this.provider = provider; + + } + @Override public ImageCaptchaGenerator get(ImageCaptchaResourceManager resourceManager, ImageTransform imageTransform) { - return new StandardWordClickImageCaptchaGenerator(resourceManager, imageTransform); + return provider.get(resourceManager, imageTransform); } @Override public String getType() { - return CaptchaTypeConstant.WORD_IMAGE_CLICK; + return type; } } diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardConcatImageCaptchaGeneratorProvider.java b/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardConcatImageCaptchaGeneratorProvider.java deleted file mode 100644 index 9954637..0000000 --- a/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardConcatImageCaptchaGeneratorProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -package cloud.tianai.captcha.generator.impl.provider; - -import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; -import cloud.tianai.captcha.generator.ImageCaptchaGenerator; -import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider; -import cloud.tianai.captcha.generator.ImageTransform; -import cloud.tianai.captcha.generator.impl.StandardConcatImageCaptchaGenerator; -import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; - -/** - * @Author: 天爱有情 - * @date 2022/5/19 15:12 - * @Description 滑动还原验证码 - */ -public class StandardConcatImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider { - @Override - public ImageCaptchaGenerator get(ImageCaptchaResourceManager resourceManager, ImageTransform imageTransform) { - return new StandardConcatImageCaptchaGenerator(resourceManager, imageTransform); - } - - @Override - public String getType() { - return CaptchaTypeConstant.CONCAT; - } -} diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardRotateImageCaptchaGeneratorProvider.java b/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardRotateImageCaptchaGeneratorProvider.java deleted file mode 100644 index e3851c5..0000000 --- a/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardRotateImageCaptchaGeneratorProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -package cloud.tianai.captcha.generator.impl.provider; - -import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; -import cloud.tianai.captcha.generator.ImageCaptchaGenerator; -import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider; -import cloud.tianai.captcha.generator.ImageTransform; -import cloud.tianai.captcha.generator.impl.StandardRotateImageCaptchaGenerator; -import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; - -/** - * @Author: 天爱有情 - * @date 2022/5/19 15:14 - * @Description 旋转验证码 - */ -public class StandardRotateImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider { - @Override - public ImageCaptchaGenerator get(ImageCaptchaResourceManager resourceManager, ImageTransform imageTransform) { - return new StandardRotateImageCaptchaGenerator(resourceManager, imageTransform); - } - - @Override - public String getType() { - return CaptchaTypeConstant.ROTATE; - } -} diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardSliderImageImageCaptchaGeneratorProvider.java b/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardSliderImageImageCaptchaGeneratorProvider.java deleted file mode 100644 index efdbc10..0000000 --- a/src/main/java/cloud/tianai/captcha/generator/impl/provider/StandardSliderImageImageCaptchaGeneratorProvider.java +++ /dev/null @@ -1,25 +0,0 @@ -package cloud.tianai.captcha.generator.impl.provider; - -import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; -import cloud.tianai.captcha.generator.ImageCaptchaGenerator; -import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider; -import cloud.tianai.captcha.generator.ImageTransform; -import cloud.tianai.captcha.generator.impl.StandardSliderImageCaptchaGenerator; -import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; - -/** - * @Author: 天爱有情 - * @date 2022/5/19 15:09 - * @Description 滑动验证码 生成器 - */ -public class StandardSliderImageImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider { - @Override - public ImageCaptchaGenerator get(ImageCaptchaResourceManager resourceManager, ImageTransform imageTransform) { - return new StandardSliderImageCaptchaGenerator(resourceManager, imageTransform); - } - - @Override - public String getType() { - return CaptchaTypeConstant.SLIDER; - } -} diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/transform/Base64ImageTransform.java b/src/main/java/cloud/tianai/captcha/generator/impl/transform/Base64ImageTransform.java index a0f6b84..6cbe398 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/transform/Base64ImageTransform.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/transform/Base64ImageTransform.java @@ -6,7 +6,6 @@ import cloud.tianai.captcha.generator.common.model.dto.GenerateParam; import cloud.tianai.captcha.generator.common.model.dto.ImageTransformData; import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils; import cloud.tianai.captcha.generator.common.util.ImgWriter; -import cloud.tianai.captcha.resource.common.model.dto.Resource; import lombok.SneakyThrows; import javax.imageio.ImageIO; @@ -60,12 +59,7 @@ public class Base64ImageTransform implements ImageTransform { } @Override - public ImageTransformData transform(GenerateParam param, - BufferedImage backgroundImage, - BufferedImage templateImage, - Object backgroundResource, - Object templateResource, - CustomData data) { + public ImageTransformData transform(GenerateParam param, BufferedImage backgroundImage, BufferedImage templateImage, Object backgroundResource, Object templateResource, CustomData data) { ImageTransformData imageTransformData = new ImageTransformData(); if (backgroundImage != null) { imageTransformData.setBackgroundImageUrl(transform(backgroundImage, param.getBackgroundFormatName())); diff --git a/src/main/java/cloud/tianai/captcha/resource/ResourceProvider.java b/src/main/java/cloud/tianai/captcha/resource/ResourceProvider.java index 2a0e8a6..ad78dde 100644 --- a/src/main/java/cloud/tianai/captcha/resource/ResourceProvider.java +++ b/src/main/java/cloud/tianai/captcha/resource/ResourceProvider.java @@ -1,6 +1,5 @@ package cloud.tianai.captcha.resource; -import cloud.tianai.captcha.resource.common.model.dto.Resource; import cloud.tianai.captcha.resource.common.model.dto.Resource; import java.io.InputStream; diff --git a/src/main/java/cloud/tianai/captcha/resource/ResourceStore.java b/src/main/java/cloud/tianai/captcha/resource/ResourceStore.java index 63c73f7..e21cde8 100644 --- a/src/main/java/cloud/tianai/captcha/resource/ResourceStore.java +++ b/src/main/java/cloud/tianai/captcha/resource/ResourceStore.java @@ -3,8 +3,6 @@ package cloud.tianai.captcha.resource; import cloud.tianai.captcha.resource.common.model.dto.Resource; import cloud.tianai.captcha.resource.common.model.dto.ResourceMap; -import java.util.Map; - /** * @Author: 天爱有情 * @date 2022/5/7 9:04 diff --git a/src/main/java/cloud/tianai/captcha/resource/common/model/dto/Resource.java b/src/main/java/cloud/tianai/captcha/resource/common/model/dto/Resource.java index 05faedb..a1f322c 100644 --- a/src/main/java/cloud/tianai/captcha/resource/common/model/dto/Resource.java +++ b/src/main/java/cloud/tianai/captcha/resource/common/model/dto/Resource.java @@ -1,7 +1,6 @@ package cloud.tianai.captcha.resource.common.model.dto; import cloud.tianai.captcha.resource.ResourceProvider; -import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -19,7 +18,10 @@ public class Resource { public String data; /** 标签.*/ private String tag; - + /** 提示.*/ + private String tip; + /** 扩展.*/ + private Object extra; public Resource(String type, String data) { this.type = type; this.data = data; @@ -30,4 +32,11 @@ public class Resource { this.data = data; this.tag = tag; } + + public Resource(String type, String data, String tag, String tip) { + this.type = type; + this.data = data; + this.tag = tag; + this.tip = tip; + } } diff --git a/src/main/java/cloud/tianai/captcha/resource/impl/DefaultImageCaptchaResourceManager.java b/src/main/java/cloud/tianai/captcha/resource/impl/DefaultImageCaptchaResourceManager.java index 2ff017d..9ff1277 100644 --- a/src/main/java/cloud/tianai/captcha/resource/impl/DefaultImageCaptchaResourceManager.java +++ b/src/main/java/cloud/tianai/captcha/resource/impl/DefaultImageCaptchaResourceManager.java @@ -1,12 +1,10 @@ package cloud.tianai.captcha.resource.impl; -import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; -import cloud.tianai.captcha.resource.common.model.dto.ResourceMap; -import cloud.tianai.captcha.resource.impl.provider.URLResourceProvider; import cloud.tianai.captcha.resource.ImageCaptchaResourceManager; import cloud.tianai.captcha.resource.ResourceProvider; import cloud.tianai.captcha.resource.ResourceStore; import cloud.tianai.captcha.resource.common.model.dto.Resource; +import cloud.tianai.captcha.resource.common.model.dto.ResourceMap; import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider; import cloud.tianai.captcha.resource.impl.provider.FileResourceProvider; import cloud.tianai.captcha.resource.impl.provider.URLResourceProvider; @@ -15,7 +13,6 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; /** * @Author: 天爱有情 @@ -41,7 +38,7 @@ public class DefaultImageCaptchaResourceManager implements ImageCaptchaResourceM private void init() { if (this.resourceStore == null) { - this.resourceStore = new DefaultResourceStore(); + this.resourceStore = new LocalMemoryResourceStore(); } // 注入一些默认的提供者 registerResourceProvider(new URLResourceProvider()); diff --git a/src/main/java/cloud/tianai/captcha/resource/impl/DefaultResourceStore.java b/src/main/java/cloud/tianai/captcha/resource/impl/LocalMemoryResourceStore.java similarity index 50% rename from src/main/java/cloud/tianai/captcha/resource/impl/DefaultResourceStore.java rename to src/main/java/cloud/tianai/captcha/resource/impl/LocalMemoryResourceStore.java index 5d7fb6b..da25b4f 100644 --- a/src/main/java/cloud/tianai/captcha/resource/impl/DefaultResourceStore.java +++ b/src/main/java/cloud/tianai/captcha/resource/impl/LocalMemoryResourceStore.java @@ -1,5 +1,6 @@ package cloud.tianai.captcha.resource.impl; +import cloud.tianai.captcha.common.constant.CommonConstant; import cloud.tianai.captcha.common.util.CollectionUtils; import cloud.tianai.captcha.common.util.ObjectUtils; import cloud.tianai.captcha.resource.ResourceStore; @@ -14,17 +15,8 @@ import java.util.concurrent.ThreadLocalRandom; * @date 2021/8/7 15:43 * @Description 默认的资源存储 */ -public class DefaultResourceStore implements ResourceStore { +public class LocalMemoryResourceStore implements ResourceStore { private static final String TYPE_TAG_SPLIT_FLAG = "|"; - /** - * 模板资源. - */ - private Map> templateResourceMap = new HashMap<>(2); - - /** - * resource. - */ - private Map> resourceMap = new HashMap<>(2); /** 用于检索 type和tag. */ private Map> templateResourceTagMap = new HashMap<>(2); @@ -32,32 +24,25 @@ public class DefaultResourceStore implements ResourceStore { @Override public void addResource(String type, Resource resource) { - resourceMap.computeIfAbsent(type, k -> new ArrayList<>(20)).add(resource); - // 添加tag标签字典 - if (!ObjectUtils.isEmpty(resource.getTag())) { - resourceTagMap.computeIfAbsent(mergeTypeAndTag(type, resource.getTag()), k -> new ArrayList<>(20)).add(resource); + if (ObjectUtils.isEmpty(resource.getTag())) { + resource.setTag(CommonConstant.DEFAULT_TAG); } + resourceTagMap.computeIfAbsent(mergeTypeAndTag(type, resource.getTag()), k -> new ArrayList<>(20)).add(resource); } @Override public void addTemplate(String type, ResourceMap template) { - templateResourceMap.computeIfAbsent(type, k -> new ArrayList<>(2)).add(template); - // 添加tag标签字典 - if (!ObjectUtils.isEmpty(template.getTag())) { - templateResourceTagMap.computeIfAbsent(mergeTypeAndTag(type, template.getTag()), k -> new ArrayList<>(2)).add(template); + if (ObjectUtils.isEmpty(template.getTag())) { + template.setTag(CommonConstant.DEFAULT_TAG); } + templateResourceTagMap.computeIfAbsent(mergeTypeAndTag(type, template.getTag()), k -> new ArrayList<>(2)).add(template); } @Override public Resource randomGetResourceByTypeAndTag(String type, String tag) { - List resources; - if (ObjectUtils.isEmpty(tag)) { - resources = resourceMap.get(type); - } else { - resources = resourceTagMap.get(mergeTypeAndTag(type, tag)); - } + List resources = resourceTagMap.get(mergeTypeAndTag(type, tag)); if (CollectionUtils.isEmpty(resources)) { - throw new IllegalStateException("随机获取资源错误,store中资源为空, type:" + type); + throw new IllegalStateException("随机获取资源错误,store中资源为空, type:" + type + ",tag:" + tag); } if (resources.size() == 1) { return resources.get(0); @@ -68,16 +53,10 @@ public class DefaultResourceStore implements ResourceStore { @Override public ResourceMap randomGetTemplateByTypeAndTag(String type, String tag) { - List templateList; - if (ObjectUtils.isEmpty(tag)) { - templateList = templateResourceMap.get(type); - } else { - templateList = templateResourceTagMap.get(mergeTypeAndTag(type, tag)); - } + List templateList = templateResourceTagMap.get(mergeTypeAndTag(type, tag)); if (CollectionUtils.isEmpty(templateList)) { - throw new IllegalStateException("随机获取模板错误,store中模板为空, type:" + type); + throw new IllegalStateException("随机获取模板错误,store中模板为空, type:" + type + ",tag:" + tag); } - if (templateList.size() == 1) { return templateList.get(0); } @@ -86,53 +65,56 @@ public class DefaultResourceStore implements ResourceStore { } public String mergeTypeAndTag(String type, String tag) { + if (tag == null) { + tag = CommonConstant.DEFAULT_TAG; + } return type + TYPE_TAG_SPLIT_FLAG + tag; } - public void clearResources(String type) { - resourceMap.remove(type); + public void clearResources(String type, String tag) { + resourceTagMap.remove(mergeTypeAndTag(type, tag)); } public void clearAllResources() { - resourceMap.clear(); + resourceTagMap.clear(); } public Map> listAllResources() { - return resourceMap; + return resourceTagMap; } - public List listResourcesByType(String type) { - return resourceMap.getOrDefault(type, Collections.emptyList()); + public List listResourcesByType(String type, String tag) { + return resourceTagMap.getOrDefault(mergeTypeAndTag(type, tag), Collections.emptyList()); } public int getAllResourceCount() { int count = 0; - for (List value : resourceMap.values()) { + for (List value : resourceTagMap.values()) { count += value.size(); } return count; } - public int getResourceCount(String type) { - return resourceMap.getOrDefault(type, Collections.emptyList()).size(); + public int getResourceCount(String type, String tag) { + return resourceTagMap.getOrDefault(mergeTypeAndTag(type, tag), Collections.emptyList()).size(); } public void clearAllTemplates() { - templateResourceMap.clear(); + templateResourceTagMap.clear(); } - public void clearTemplates(String type) { - templateResourceMap.remove(type); + public void clearTemplates(String type, String tag) { + templateResourceTagMap.remove(mergeTypeAndTag(type, tag)); } - public List listTemplatesByType(String type) { - return templateResourceMap.getOrDefault(type, Collections.emptyList()); + public List listTemplatesByType(String type, String tag) { + return templateResourceTagMap.getOrDefault(mergeTypeAndTag(type, tag), Collections.emptyList()); } - public Map> listAllTemplates() { - return templateResourceMap; + public Map> listAllTemplates() { + return templateResourceTagMap; } diff --git a/src/main/java/cloud/tianai/captcha/resource/impl/provider/ClassPathResourceProvider.java b/src/main/java/cloud/tianai/captcha/resource/impl/provider/ClassPathResourceProvider.java index 33fd4a9..7cb0d51 100644 --- a/src/main/java/cloud/tianai/captcha/resource/impl/provider/ClassPathResourceProvider.java +++ b/src/main/java/cloud/tianai/captcha/resource/impl/provider/ClassPathResourceProvider.java @@ -1,7 +1,5 @@ package cloud.tianai.captcha.resource.impl.provider; -import cloud.tianai.captcha.resource.AbstractResourceProvider; -import cloud.tianai.captcha.resource.common.model.dto.Resource; import cloud.tianai.captcha.resource.AbstractResourceProvider; import cloud.tianai.captcha.resource.common.model.dto.Resource; diff --git a/src/main/java/cloud/tianai/captcha/resource/impl/provider/FileResourceProvider.java b/src/main/java/cloud/tianai/captcha/resource/impl/provider/FileResourceProvider.java index ebaee67..065eda5 100644 --- a/src/main/java/cloud/tianai/captcha/resource/impl/provider/FileResourceProvider.java +++ b/src/main/java/cloud/tianai/captcha/resource/impl/provider/FileResourceProvider.java @@ -1,7 +1,5 @@ package cloud.tianai.captcha.resource.impl.provider; -import cloud.tianai.captcha.resource.AbstractResourceProvider; -import cloud.tianai.captcha.resource.common.model.dto.Resource; import cloud.tianai.captcha.resource.AbstractResourceProvider; import cloud.tianai.captcha.resource.common.model.dto.Resource; import lombok.SneakyThrows; diff --git a/src/main/java/cloud/tianai/captcha/resource/impl/provider/URLResourceProvider.java b/src/main/java/cloud/tianai/captcha/resource/impl/provider/URLResourceProvider.java index 5543db7..507598b 100644 --- a/src/main/java/cloud/tianai/captcha/resource/impl/provider/URLResourceProvider.java +++ b/src/main/java/cloud/tianai/captcha/resource/impl/provider/URLResourceProvider.java @@ -1,6 +1,5 @@ package cloud.tianai.captcha.resource.impl.provider; -import cloud.tianai.captcha.resource.AbstractResourceProvider; import cloud.tianai.captcha.resource.AbstractResourceProvider; import cloud.tianai.captcha.resource.common.model.dto.Resource; import lombok.SneakyThrows; diff --git a/src/main/java/cloud/tianai/captcha/validator/common/model/dto/ImageCaptchaTrack.java b/src/main/java/cloud/tianai/captcha/validator/common/model/dto/ImageCaptchaTrack.java index 96ff727..093fe49 100644 --- a/src/main/java/cloud/tianai/captcha/validator/common/model/dto/ImageCaptchaTrack.java +++ b/src/main/java/cloud/tianai/captcha/validator/common/model/dto/ImageCaptchaTrack.java @@ -20,10 +20,10 @@ public class ImageCaptchaTrack { private Integer bgImageWidth; /** 背景图片高度. */ private Integer bgImageHeight; - /** 滑块图片宽度. */ - private Integer sliderImageWidth; - /** 滑块图片高度. */ - private Integer sliderImageHeight; + /** 模板图片宽度. */ + private Integer templateImageWidth; + /** 模板图片高度. */ + private Integer templateImageHeight; /** 滑动开始时间. */ private Date startSlidingTime; /** 滑动结束时间. */ @@ -32,28 +32,16 @@ public class ImageCaptchaTrack { private List trackList; /** 扩展数据,用户传输加密数据等.*/ private Object data; - /** - * 兼容一下旧版本 - * - * @return Date - */ - public Date getEntSlidingTime() { - return endSlidingTime; - } - public void setEntSlidingTime(Date entSlidingTime) { - this.endSlidingTime = entSlidingTime; - } - @Data @NoArgsConstructor @AllArgsConstructor public static class Track { /** x. */ - private Integer x; + private Float x; /** y. */ - private Integer y; + private Float y; /** 时间. */ - private Integer t; + private Float t; /** 类型. */ private String type = TrackTypeConstant.MOVE; } diff --git a/src/main/java/cloud/tianai/captcha/validator/impl/BasicCaptchaTrackValidator.java b/src/main/java/cloud/tianai/captcha/validator/impl/BasicCaptchaTrackValidator.java index df93313..2d6792c 100644 --- a/src/main/java/cloud/tianai/captcha/validator/impl/BasicCaptchaTrackValidator.java +++ b/src/main/java/cloud/tianai/captcha/validator/impl/BasicCaptchaTrackValidator.java @@ -2,13 +2,9 @@ package cloud.tianai.captcha.validator.impl; import cloud.tianai.captcha.common.response.ApiResponse; import cloud.tianai.captcha.common.response.CodeDefinition; -import cloud.tianai.captcha.common.util.CaptchaUtils; +import cloud.tianai.captcha.common.util.CaptchaTypeClassifier; import cloud.tianai.captcha.common.util.CollectionUtils; import cloud.tianai.captcha.common.util.ObjectUtils; -import cloud.tianai.captcha.common.util.CaptchaUtils; -import cloud.tianai.captcha.common.util.CollectionUtils; -import cloud.tianai.captcha.common.util.ObjectUtils; -import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack; import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack; import java.util.List; @@ -21,6 +17,7 @@ import java.util.Map; */ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator { public static final CodeDefinition DEFINITION = new CodeDefinition(50001, "basic check fail"); + public BasicCaptchaTrackValidator() { } @@ -29,15 +26,15 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator { } @Override - public ApiResponse beforeValid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData, Float tolerant, String type) { + public ApiResponse beforeValid(ImageCaptchaTrack imageCaptchaTrack, Map captchaValidData, Float tolerant, String type) { // 校验参数 checkParam(imageCaptchaTrack); - return ApiResponse.SUCCESS; + return ApiResponse.ofSuccess(); } @Override - public ApiResponse afterValid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData, Float tolerant, String type) { - if (!CaptchaUtils.isSliderCaptcha(type)) { + public ApiResponse afterValid(ImageCaptchaTrack imageCaptchaTrack, Map captchaValidData, Float tolerant, String type) { + if (!CaptchaTypeClassifier.isSliderCaptcha(type)) { // 不是滑动验证码的话暂时跳过,点选验证码行为轨迹还没做 return ApiResponse.ofSuccess(); } @@ -125,9 +122,9 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator { throw new IllegalArgumentException("trackList must not be null"); } for (ImageCaptchaTrack.Track track : imageCaptchaTrack.getTrackList()) { - Integer x = track.getX(); - Integer y = track.getY(); - Integer t = track.getT(); + Float x = track.getX(); + Float y = track.getY(); + Float t = track.getT(); String type = track.getType(); if (x == null || y == null || t == null || ObjectUtils.isEmpty(type)) { throw new IllegalArgumentException("track[x,y,t,type] must not be null"); diff --git a/src/main/java/cloud/tianai/captcha/validator/impl/SimpleImageCaptchaValidator.java b/src/main/java/cloud/tianai/captcha/validator/impl/SimpleImageCaptchaValidator.java index 9fccffc..48c46e9 100644 --- a/src/main/java/cloud/tianai/captcha/validator/impl/SimpleImageCaptchaValidator.java +++ b/src/main/java/cloud/tianai/captcha/validator/impl/SimpleImageCaptchaValidator.java @@ -3,7 +3,7 @@ package cloud.tianai.captcha.validator.impl; import cloud.tianai.captcha.common.constant.CaptchaTypeConstant; import cloud.tianai.captcha.common.response.ApiResponse; import cloud.tianai.captcha.common.response.ApiResponseStatusConstant; -import cloud.tianai.captcha.common.util.CaptchaUtils; +import cloud.tianai.captcha.common.util.CaptchaTypeClassifier; import cloud.tianai.captcha.common.util.CollectionUtils; import cloud.tianai.captcha.common.util.ObjectUtils; import cloud.tianai.captcha.generator.common.model.dto.ClickImageCheckDefinition; @@ -38,15 +38,23 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide public static final String TOLERANT_KEY = "tolerant"; /** 类型 key, 标识是哪张类型的验证码. */ public static final String TYPE_KEY = "type"; + /** 计算当前验证码用户滑动的百分比率 - 生成时的百分比率, 多个的话取均值. */ + public static final String USER_CURRENT_PERCENTAGE_STD = "user_current_percentage_std"; + public static final String USER_CURRENT_PERCENTAGE = "user_current_percentage"; /** 容错值. */ @Getter @Setter public float defaultTolerant = DEFAULT_TOLERANT; public SimpleImageCaptchaValidator() { + CaptchaTypeClassifier.addSliderCaptchaType(CaptchaTypeConstant.CONCAT); + CaptchaTypeClassifier.addSliderCaptchaType(CaptchaTypeConstant.ROTATE); + CaptchaTypeClassifier.addSliderCaptchaType(CaptchaTypeConstant.SLIDER); + CaptchaTypeClassifier.addClickCaptchaType(CaptchaTypeConstant.WORD_IMAGE_CLICK); } public SimpleImageCaptchaValidator(float defaultTolerant) { + this(); this.defaultTolerant = defaultTolerant; } @@ -106,10 +114,10 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide // type String type = (String) map.getOrDefault(TYPE_KEY, CaptchaTypeConstant.SLIDER); Object expand = imageCaptchaInfo.getData() == null ? null : imageCaptchaInfo.getData().getExpand(); - if (CaptchaUtils.isSliderCaptcha(type)) { + if (CaptchaTypeClassifier.isSliderCaptcha(type)) { // 滑动验证码 addPercentage(imageCaptchaInfo, map); - } else if (CaptchaUtils.isClickCaptcha(type)) { + } else if (CaptchaTypeClassifier.isClickCaptcha(type)) { // 图片点选验证码 if (expand == null) { throw new IllegalArgumentException("点选验证码扩展数据转换为 List 失败, info=" + imageCaptchaInfo); @@ -139,7 +147,7 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide } // 添加点选验证数据 map.put(PERCENTAGE_KEY, sb.toString()); - } else if (CaptchaUtils.isJigsawCaptcha(type)) { + } else if (CaptchaTypeClassifier.isJigsawCaptcha(type)) { // 拼图验证码 map.put(PERCENTAGE_KEY, expand); } @@ -173,7 +181,7 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide if (valid) { // 验证后 response = afterValid(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); - }else { + } else { // 缺口位置校验失败 response = ApiResponse.ofMessage(ApiResponseStatusConstant.BASIC_CHECK_FAIL); } @@ -202,7 +210,7 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide * @param type type * @return boolean */ - public ApiResponse afterValid(ImageCaptchaTrack imageCaptchaTrack, Map captchaValidData, Float tolerant, String type) { + public ApiResponse afterValid(ImageCaptchaTrack imageCaptchaTrack, Map captchaValidData, Float tolerant, String type) { return ApiResponse.ofSuccess(); } @@ -210,13 +218,13 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide Map imageCaptchaValidData, Float tolerant, String type) { - if (CaptchaUtils.isSliderCaptcha(type)) { + if (CaptchaTypeClassifier.isSliderCaptcha(type)) { // 滑动类型验证码 return doValidSliderCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); - } else if (CaptchaUtils.isClickCaptcha(type)) { + } else if (CaptchaTypeClassifier.isClickCaptcha(type)) { // 点选类型验证码 return doValidClickCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); - } else if (CaptchaUtils.isJigsawCaptcha(type)) { + } else if (CaptchaTypeClassifier.isJigsawCaptcha(type)) { // 拼图类型验证码 return doValidJigsawCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); } @@ -237,10 +245,10 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide /** * 校验点选验证码 * - * @param imageCaptchaTrack sliderCaptchaTrack + * @param imageCaptchaTrack sliderCaptchaTrack * @param imageCaptchaValidData imageCaptchaValidData - * @param tolerant tolerant - * @param type type + * @param tolerant tolerant + * @param type type * @return boolean */ public boolean doValidClickCaptcha(ImageCaptchaTrack imageCaptchaTrack, @@ -292,10 +300,10 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide /** * 校验滑动验证码 * - * @param imageCaptchaTrack sliderCaptchaTrack + * @param imageCaptchaTrack sliderCaptchaTrack * @param imageCaptchaValidData imageCaptchaValidData - * @param tolerant tolerant - * @param type type + * @param tolerant tolerant + * @param type type * @return boolean */ public boolean doValidSliderCaptcha(ImageCaptchaTrack imageCaptchaTrack, @@ -313,7 +321,14 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide // 计算百分比 float calcPercentage = calcPercentage(lastTrack.getX(), imageCaptchaTrack.getBgImageWidth()); // 校验百分比 - return checkPercentage(calcPercentage, oriPercentage, tolerant); + boolean percentage = checkPercentage(calcPercentage, oriPercentage, tolerant); + if (percentage) { + // 校验成功 + // 存储一下当前计算出来的值 + imageCaptchaValidData.put(USER_CURRENT_PERCENTAGE, String.valueOf(calcPercentage)); + imageCaptchaValidData.put(USER_CURRENT_PERCENTAGE_STD, String.valueOf(calcPercentage - oriPercentage)); + } + return percentage; } public Float getFloatParam(String key, Map imageCaptchaValidData) {