diff --git a/pom.xml b/pom.xml
index 9457263..b617096 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
cloud.tianai.captcha
tianai-captcha
- 1.5.0.beta
+ 1.5.0
tianai-captcha
行为验证码
diff --git a/src/main/java/cloud/tianai/captcha/application/DefaultImageCaptchaApplication.java b/src/main/java/cloud/tianai/captcha/application/DefaultImageCaptchaApplication.java
index bc9af2f..bf31170 100644
--- a/src/main/java/cloud/tianai/captcha/application/DefaultImageCaptchaApplication.java
+++ b/src/main/java/cloud/tianai/captcha/application/DefaultImageCaptchaApplication.java
@@ -12,6 +12,7 @@ import cloud.tianai.captcha.common.util.CollectionUtils;
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
+import cloud.tianai.captcha.generator.impl.CacheImageCaptchaGenerator;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
import cloud.tianai.captcha.interceptor.EmptyCaptchaInterceptor;
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
@@ -51,7 +52,7 @@ public class DefaultImageCaptchaApplication implements ImageCaptchaApplication {
ImageCaptchaProperties prop,
CaptchaInterceptor captchaInterceptor) {
this.prop = prop;
- setImageCaptchaGenerator(captchaGenerator);
+
setImageCaptchaValidator(imageCaptchaValidator);
setCacheStore(cacheStore);
// 默认过期时间
@@ -65,6 +66,14 @@ public class DefaultImageCaptchaApplication implements ImageCaptchaApplication {
this.captchaInterceptor = captchaInterceptor;
}
captchaGenerator.setInterceptor(this.captchaInterceptor);
+ if (prop.isLocalCacheEnabled()) {
+ captchaGenerator = new CacheImageCaptchaGenerator(captchaGenerator,
+ prop.getLocalCacheSize(), prop.getLocalCacheWaitTime(),
+ prop.getLocalCachePeriod(), prop.getLocalCacheExpireTime());
+ }
+ // 初始化生成器
+ captchaGenerator.init();
+ setImageCaptchaGenerator(captchaGenerator);
}
@Override
diff --git a/src/main/java/cloud/tianai/captcha/application/ImageCaptchaProperties.java b/src/main/java/cloud/tianai/captcha/application/ImageCaptchaProperties.java
index 654d098..6af6aff 100644
--- a/src/main/java/cloud/tianai/captcha/application/ImageCaptchaProperties.java
+++ b/src/main/java/cloud/tianai/captcha/application/ImageCaptchaProperties.java
@@ -2,7 +2,7 @@ package cloud.tianai.captcha.application;
import lombok.Data;
-import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
/**
@@ -15,5 +15,12 @@ public class ImageCaptchaProperties {
/** 过期key prefix. */
private String prefix = "captcha";
/** 过期时间. */
- private Map expire = Collections.emptyMap();
+ private Map expire = new HashMap<>();
+
+ // 本地提前缓存
+ private boolean localCacheEnabled = false;
+ private int localCacheSize = 10;
+ private int localCacheWaitTime = 1000;
+ private int localCachePeriod = 5000;
+ private Long localCacheExpireTime;
}
diff --git a/src/main/java/cloud/tianai/captcha/application/TACBuilder.java b/src/main/java/cloud/tianai/captcha/application/TACBuilder.java
new file mode 100644
index 0000000..dbda9a0
--- /dev/null
+++ b/src/main/java/cloud/tianai/captcha/application/TACBuilder.java
@@ -0,0 +1,174 @@
+package cloud.tianai.captcha.application;
+
+import cloud.tianai.captcha.cache.CacheStore;
+import cloud.tianai.captcha.cache.impl.LocalCacheStore;
+import cloud.tianai.captcha.common.util.CollectionUtils;
+import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
+import cloud.tianai.captcha.generator.ImageTransform;
+import cloud.tianai.captcha.generator.common.FontWrapper;
+import cloud.tianai.captcha.generator.impl.MultiImageCaptchaGenerator;
+import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
+import cloud.tianai.captcha.interceptor.EmptyCaptchaInterceptor;
+import cloud.tianai.captcha.resource.DefaultBuiltInResources;
+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.DefaultImageCaptchaResourceManager;
+import cloud.tianai.captcha.resource.impl.LocalMemoryResourceStore;
+import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider;
+import cloud.tianai.captcha.validator.ImageCaptchaValidator;
+import cloud.tianai.captcha.validator.impl.SimpleImageCaptchaValidator;
+
+import java.awt.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author: 天爱有情
+ * @date 2024/7/14 16:41
+ * @Description 一个构建ImageCaptchaApplication的工具, 免去一些繁琐的配置,方便新手用户一键使用
+ */
+public class TACBuilder {
+
+ private CacheStore cacheStore;
+ private ImageCaptchaGenerator generator;
+ private ImageCaptchaValidator validator;
+ private CaptchaInterceptor interceptor = EmptyCaptchaInterceptor.INSTANCE;
+ private ImageCaptchaProperties prop = new ImageCaptchaProperties();
+ private ResourceStore resourceStore;
+ private ImageTransform imageTransform;
+ private List fontWrappers = new ArrayList<>();
+
+ public static TACBuilder builder() {
+ TACBuilder builder = new TACBuilder();
+ // 默认设置本地的
+ LocalMemoryResourceStore resourceStore = new LocalMemoryResourceStore();
+ builder.resourceStore = resourceStore;
+ builder.prop = new ImageCaptchaProperties();
+ return builder;
+ }
+
+ private TACBuilder() {
+ }
+
+ public TACBuilder addDefaultTemplate(String defaultPathPrefix) {
+ DefaultBuiltInResources defaultBuiltInResources = new DefaultBuiltInResources(defaultPathPrefix);
+ defaultBuiltInResources.addDefaultTemplate(resourceStore);
+ return this;
+ }
+
+ public TACBuilder addDefaultTemplate() {
+ return addDefaultTemplate(DefaultBuiltInResources.PATH_PREFIX);
+ }
+
+ public TACBuilder setCacheStore(CacheStore cacheStore) {
+ this.cacheStore = cacheStore;
+ return this;
+ }
+
+ public TACBuilder setGenerator(ImageCaptchaGenerator generator) {
+ this.generator = generator;
+ return this;
+ }
+
+ public TACBuilder setValidator(ImageCaptchaValidator validator) {
+ this.validator = validator;
+ return this;
+ }
+
+ public TACBuilder setInterceptor(CaptchaInterceptor interceptor) {
+ this.interceptor = interceptor;
+ return this;
+ }
+
+ public TACBuilder addFont(FontWrapper fontWrapper) {
+ this.fontWrappers.add(fontWrapper);
+ return this;
+ }
+
+ public TACBuilder addFont(Font font) {
+ return addFont(new FontWrapper(font));
+ }
+
+
+ public TACBuilder cached(int size, int waitTime, int period, Long expireTime) {
+ prop.setLocalCacheEnabled(true);
+ prop.setLocalCacheSize(size);
+ prop.setLocalCacheWaitTime(waitTime);
+ prop.setLocalCachePeriod(period);
+ prop.setLocalCacheExpireTime(expireTime);
+ return this;
+ }
+
+ public TACBuilder prefix(String prefix) {
+ this.prop.setPrefix(prefix);
+ return this;
+ }
+
+ public TACBuilder expire(String captchaType, Long expireTime) {
+ prop.getExpire().put(captchaType, expireTime);
+ return this;
+ }
+
+ public TACBuilder setProp(ImageCaptchaProperties prop) {
+ this.prop = prop;
+ return this;
+ }
+
+ public TACBuilder setResourceStore(ResourceStore resourceStore) {
+ this.resourceStore = resourceStore;
+ return this;
+ }
+
+
+ public TACBuilder addResource(String captchaType, Resource imageResource) {
+ this.resourceStore.addResource(captchaType, imageResource);
+ return this;
+ }
+
+ public TACBuilder addTemplate(String captchaType, ResourceMap resourceMap) {
+ this.resourceStore.addTemplate(captchaType, resourceMap);
+ return this;
+ }
+
+ public TACBuilder setTransform(ImageTransform imageTransform) {
+ this.imageTransform = imageTransform;
+ return this;
+ }
+
+ public ImageCaptchaApplication build() {
+ if (cacheStore == null) {
+ cacheStore = new LocalCacheStore();
+ }
+ if (generator == null) {
+ DefaultImageCaptchaResourceManager resourceManager = new DefaultImageCaptchaResourceManager(resourceStore);
+ generator = new MultiImageCaptchaGenerator(resourceManager, imageTransform);
+ }
+ if (generator instanceof MultiImageCaptchaGenerator) {
+ if (CollectionUtils.isEmpty(fontWrappers)) {
+ // 添加默认字体
+ try {
+ ClassPathResourceProvider resourceProvider = new ClassPathResourceProvider();
+ InputStream stream = resourceProvider.getResourceInputStream(new Resource("classpath", "META-INF/fonts/SIMSUN.TTC"));
+ Font font = Font.createFont(Font.TRUETYPE_FONT, stream);
+ stream.close();
+ fontWrappers.add(new FontWrapper(font));
+ } catch (Exception e) {
+ throw new RuntimeException("读取默认字体包报错",e);
+ }
+ }
+ ((MultiImageCaptchaGenerator) generator).setFontWrappers(fontWrappers);
+ }
+ if (validator == null) {
+ validator = new SimpleImageCaptchaValidator();
+ }
+ if (interceptor == null) {
+ interceptor = EmptyCaptchaInterceptor.INSTANCE;
+ }
+
+ DefaultImageCaptchaApplication application = new DefaultImageCaptchaApplication(generator, validator, cacheStore, prop, interceptor);
+ return application;
+ }
+}
diff --git a/src/main/java/cloud/tianai/captcha/generator/AbstractImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/AbstractImageCaptchaGenerator.java
index 87e0867..292351e 100644
--- a/src/main/java/cloud/tianai/captcha/generator/AbstractImageCaptchaGenerator.java
+++ b/src/main/java/cloud/tianai/captcha/generator/AbstractImageCaptchaGenerator.java
@@ -58,7 +58,7 @@ public abstract class AbstractImageCaptchaGenerator implements ImageCaptchaGener
}
@Override
- public ImageCaptchaGenerator init(boolean initDefaultResource) {
+ public ImageCaptchaGenerator init() {
if (init) {
return this;
}
@@ -69,7 +69,7 @@ public abstract class AbstractImageCaptchaGenerator implements ImageCaptchaGener
if (getImageTransform() == null) {
setImageTransform(new Base64ImageTransform());
}
- doInit(initDefaultResource);
+ doInit();
} catch (Exception e) {
init = false;
log.error("[{}]初始化失败,ex", this.getClass().getSimpleName(), e);
@@ -237,9 +237,8 @@ public abstract class AbstractImageCaptchaGenerator implements ImageCaptchaGener
/**
* 初始化
*
- * @param initDefaultResource 是否初始化默认资源
*/
- protected abstract void doInit(boolean initDefaultResource);
+ protected abstract void doInit();
/**
* 生成验证码方法
diff --git a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGenerator.java
index 25bf2eb..12408a6 100644
--- a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGenerator.java
+++ b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaGenerator.java
@@ -17,10 +17,9 @@ public interface ImageCaptchaGenerator {
/**
* 初始化
*
- * @param initDefaultResource 是否初始化默认资源
* @return ImageCaptchaGenerator
*/
- ImageCaptchaGenerator init(boolean initDefaultResource);
+ ImageCaptchaGenerator init();
/**
* 生成验证码图片
diff --git a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaPostProcessor.java b/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaPostProcessor.java
deleted file mode 100644
index 58a744c..0000000
--- a/src/main/java/cloud/tianai/captcha/generator/ImageCaptchaPostProcessor.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package cloud.tianai.captcha.generator;
-
-import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
-import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
-
-/**
- * @Author: 天爱有情
- * @date 2023/4/24 15:11
- * @Description 图片验证码后处理器
- */
-public interface ImageCaptchaPostProcessor {
-
- /**
- * 在生成验证码核心逻辑之前调用, 用于拦截验证码生成、限流、自定义返回数据等处理
- *
- * @param captchaExchange 传输数据
- * @param generator generator
- * @return ImageCaptchaInfo
- */
- default ImageCaptchaInfo beforeGenerateCaptchaImage(CaptchaExchange captchaExchange, ImageCaptchaGenerator generator) {
- return null;
- }
-
- /**
- * 在执行包装 ImageCaptchaInfo 核心逻辑之前处理
- *
- * @param captchaExchange 传输数据
- * @param generator generator
- */
- default void beforeWrapImageCaptchaInfo(CaptchaExchange captchaExchange, ImageCaptchaGenerator generator) {
-
- }
-
- /**
- * 在执行包装 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/common/FontWrapper.java b/src/main/java/cloud/tianai/captcha/generator/common/FontWrapper.java
index 7f4f59c..b09c311 100644
--- a/src/main/java/cloud/tianai/captcha/generator/common/FontWrapper.java
+++ b/src/main/java/cloud/tianai/captcha/generator/common/FontWrapper.java
@@ -11,5 +11,22 @@ import java.awt.*;
@AllArgsConstructor
public class FontWrapper {
private Font font;
- private float currentFontTopCoef;
+ private Float currentFontTopCoef;
+
+ public FontWrapper(Font font) {
+ this(font, 70);
+ }
+
+ public FontWrapper(Font font, int fontSize) {
+ this.font = font;
+ this.font = font.deriveFont(Font.BOLD, fontSize);
+ }
+
+ public float getCurrentFontTopCoef() {
+ if (currentFontTopCoef != null) {
+ return currentFontTopCoef;
+ }
+ currentFontTopCoef = 0.14645833f * font.getSize() + 0.39583333f;
+ return currentFontTopCoef;
+ }
}
diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/CacheImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/CacheImageCaptchaGenerator.java
index 90f26a4..1194ea4 100644
--- a/src/main/java/cloud/tianai/captcha/generator/impl/CacheImageCaptchaGenerator.java
+++ b/src/main/java/cloud/tianai/captcha/generator/impl/CacheImageCaptchaGenerator.java
@@ -126,8 +126,8 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
}
@Override
- public ImageCaptchaGenerator init(boolean initDefaultResource) {
- ImageCaptchaGenerator captchaGenerator = target.init(initDefaultResource);
+ public ImageCaptchaGenerator init() {
+ ImageCaptchaGenerator captchaGenerator = target.init();
// 初始化缓存
init(size);;
return captchaGenerator;
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 6af1c8a..c3e992c 100644
--- a/src/main/java/cloud/tianai/captcha/generator/impl/MultiImageCaptchaGenerator.java
+++ b/src/main/java/cloud/tianai/captcha/generator/impl/MultiImageCaptchaGenerator.java
@@ -5,6 +5,7 @@ import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
import cloud.tianai.captcha.generator.ImageTransform;
+import cloud.tianai.captcha.generator.common.FontWrapper;
import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
@@ -14,6 +15,7 @@ import lombok.Getter;
import lombok.Setter;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -28,13 +30,14 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
protected Map imageCaptchaGeneratorMap = new ConcurrentHashMap<>(4);
protected Map imageCaptchaGeneratorProviderMap = new HashMap<>(4);
-
+ // 点选类验证码字体
+ @Setter
+ @Getter
+ protected List fontWrappers;
@Setter
@Getter
private String defaultCaptcha = SLIDER;
- protected boolean initDefaultResource = false;
-
public MultiImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
super(imageCaptchaResourceManager);
}
@@ -45,9 +48,7 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
}
@Override
- protected void doInit(boolean initDefaultResource) {
- this.initDefaultResource = initDefaultResource;
-
+ protected void doInit() {
// 滑块验证码
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(SLIDER, StandardSliderImageCaptchaGenerator::new));
// 旋转验证码
@@ -55,7 +56,8 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
// 拼接验证码
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(CONCAT, StandardConcatImageCaptchaGenerator::new));
// 点选文字验证码
- addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(WORD_IMAGE_CLICK, StandardWordClickImageCaptchaGenerator::new));
+ addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(WORD_IMAGE_CLICK, (r, t, i) ->
+ new StandardWordClickImageCaptchaGenerator(r, t, i, fontWrappers)));
}
public void addImageCaptchaGeneratorProvider(ImageCaptchaGeneratorProvider provider) {
@@ -110,7 +112,7 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
if (provider == null) {
throw new IllegalArgumentException("生成验证码失败,错误的type类型:" + t);
}
- return provider.get(getImageResourceManager(), getImageTransform(), getInterceptor()).init(initDefaultResource);
+ return provider.get(getImageResourceManager(), getImageTransform(), getInterceptor()).init();
});
return imageCaptchaGenerator;
}
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 99ade97..9c6f2ef 100644
--- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardConcatImageCaptchaGenerator.java
+++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardConcatImageCaptchaGenerator.java
@@ -6,15 +6,11 @@ import cloud.tianai.captcha.generator.ImageTransform;
import cloud.tianai.captcha.generator.common.model.dto.*;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
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.SneakyThrows;
import java.awt.image.BufferedImage;
-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.concatImage;
import static cloud.tianai.captcha.generator.common.util.CaptchaImageUtils.splitImage;
@@ -41,17 +37,9 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen
}
@Override
- protected void doInit(boolean initDefaultResource) {
- if (initDefaultResource) {
- initDefaultResource();
- }
+ protected void doInit() {
}
- public void initDefaultResource() {
- ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
- // 添加一些系统的资源文件
- resourceStore.addResource(CaptchaTypeConstant.CONCAT, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
- }
@Override
public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
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 f7a347c..a5dd5a8 100644
--- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardRotateImageCaptchaGenerator.java
+++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardRotateImageCaptchaGenerator.java
@@ -1,23 +1,18 @@
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.model.dto.*;
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
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.common.model.dto.ResourceMap;
-import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider;
import lombok.SneakyThrows;
import java.awt.image.BufferedImage;
import java.util.Optional;
-import static cloud.tianai.captcha.common.constant.CommonConstant.*;
-
/**
* @Author: 天爱有情
* @date 2022/4/22 16:43
@@ -46,25 +41,10 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen
setImageTransform(imageTransform);
setInterceptor(interceptor);
}
-
@Override
- protected void doInit(boolean initDefaultResource) {
- if (initDefaultResource) {
- initDefaultResource();
- }
+ protected void doInit() {
}
- public void initDefaultResource() {
- ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
- // 添加一些系统的资源文件
- 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, 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);
- }
@Override
public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
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 f3003d9..b61ee70 100644
--- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardSliderImageCaptchaGenerator.java
+++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardSliderImageCaptchaGenerator.java
@@ -1,16 +1,13 @@
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.model.dto.*;
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
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.common.model.dto.ResourceMap;
-import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@@ -19,8 +16,6 @@ import java.awt.image.BufferedImage;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
-import static cloud.tianai.captcha.common.constant.CommonConstant.*;
-
/**
* @Author: 天爱有情
* @Date 2020/5/29 8:06
@@ -57,10 +52,8 @@ public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGen
@Override
- protected void doInit(boolean initDefaultResource) {
- if (initDefaultResource) {
- initDefaultResource();
- }
+ protected void doInit() {
+
}
@SneakyThrows
@@ -169,24 +162,4 @@ public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGen
// 左边混淆
return randomInt(slWidth, sliderX - slWidth);
}
-
- /**
- * 初始化默认资源
- */
- public void initDefaultResource() {
- ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
- // 添加一些系统的资源文件
- resourceStore.addResource(CaptchaTypeConstant.SLIDER, 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, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/active.png")));
- template1.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/fixed.png")));
- resourceStore.addTemplate(CaptchaTypeConstant.SLIDER, template1);
-
- ResourceMap template2 = new ResourceMap(DEFAULT_TAG, 4);
- template2.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/active.png")));
- template2.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/fixed.png")));
- resourceStore.addTemplate(CaptchaTypeConstant.SLIDER, template2);
- }
}
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 6f08522..9cbc881 100644
--- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardWordClickImageCaptchaGenerator.java
+++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardWordClickImageCaptchaGenerator.java
@@ -1,6 +1,7 @@
package cloud.tianai.captcha.generator.impl;
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
+import cloud.tianai.captcha.common.exception.ImageCaptchaException;
import cloud.tianai.captcha.common.util.CollectionUtils;
import cloud.tianai.captcha.common.util.FontUtils;
import cloud.tianai.captcha.generator.ImageTransform;
@@ -9,26 +10,18 @@ import cloud.tianai.captcha.generator.common.model.dto.*;
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
import cloud.tianai.captcha.resource.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.Getter;
import lombok.Setter;
-import lombok.SneakyThrows;
import java.awt.*;
import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
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;
-
/**
* @Author: 天爱有情
* @date 2022/4/27 11:46
@@ -108,27 +101,11 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
}
@Override
- @SneakyThrows({IOException.class, FontFormatException.class})
- protected void doInit(boolean initDefaultResource) {
+ protected void doInit() {
if (CollectionUtils.isEmpty(fonts)) {
- // 使用默认字体
- Resource fontResource = new Resource(null, "META-INF/fonts/SIMSUN.TTC");
- InputStream inputStream = new ClassPathResourceProvider().doGetResourceInputStream(fontResource);
- Font font = Font.createFont(Font.TRUETYPE_FONT, inputStream);
- font = font.deriveFont(Font.BOLD, 70);
- float currentFontTopCoef = 0.14645833f * font.getSize() + 0.39583333f;
- fonts.add(new FontWrapper(font, currentFontTopCoef));
+ throw new ImageCaptchaException("初始化文字点选验证码失败,请设置字体包后再调用init()");
}
- if (initDefaultResource) {
- initDefaultResource();
- }
- }
-
- public void initDefaultResource() {
- ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
- // 添加一些系统的资源文件
- resourceStore.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
}
public ImgWrapper genTipImage(List imageCheckDefinitions) {
diff --git a/src/main/java/cloud/tianai/captcha/resource/DefaultBuiltInResources.java b/src/main/java/cloud/tianai/captcha/resource/DefaultBuiltInResources.java
new file mode 100644
index 0000000..7baa330
--- /dev/null
+++ b/src/main/java/cloud/tianai/captcha/resource/DefaultBuiltInResources.java
@@ -0,0 +1,86 @@
+package cloud.tianai.captcha.resource;
+
+import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
+import cloud.tianai.captcha.resource.common.model.dto.Resource;
+import cloud.tianai.captcha.resource.common.model.dto.ResourceMap;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+
+import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG;
+import static cloud.tianai.captcha.generator.impl.StandardSliderImageCaptchaGenerator.TEMPLATE_ACTIVE_IMAGE_NAME;
+import static cloud.tianai.captcha.generator.impl.StandardSliderImageCaptchaGenerator.TEMPLATE_FIXED_IMAGE_NAME;
+
+
+/**
+ * @Author: 天爱有情
+ * @date 2024/7/15 9:10
+ * @Description 默认资源配置
+ * 注意: 不推荐使用该类,应该将资源模板自己设置,而不是使用默认的,这里编写的目的只是为了演示方便
+ */
+public class DefaultBuiltInResources {
+
+ public static final String PATH_PREFIX = "classpath:META-INF/cut-image/template";
+
+ private static Map> defaultTemplateResource = new HashMap<>(8);
+
+
+ public DefaultBuiltInResources(String defaultPathPrefix) {
+ init(defaultPathPrefix);
+ }
+
+ private void init(String defaultPathPrefix) {
+ String[] split = defaultPathPrefix.split(":");
+ String type;
+ String pathPrefix;
+ if (split.length < 1) {
+ type = "file";
+ pathPrefix = defaultPathPrefix;
+ } else {
+ type = split[0];
+ pathPrefix = split[1];
+ }
+ if (pathPrefix.endsWith("/")) {
+ pathPrefix = pathPrefix.substring(0, pathPrefix.length() - 1);
+ }
+ // 滑动验证
+ String finalPathPrefix = pathPrefix;
+ defaultTemplateResource.put(CaptchaTypeConstant.SLIDER, resourceStore -> {
+ ResourceMap template1 = new ResourceMap(DEFAULT_TAG, 4);
+ template1.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(type, finalPathPrefix.concat("/slider_1/active.png")));
+ template1.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(type, finalPathPrefix.concat("/slider_1/fixed.png")));
+ resourceStore.addTemplate(CaptchaTypeConstant.SLIDER, template1);
+
+ ResourceMap template2 = new ResourceMap(DEFAULT_TAG, 4);
+ template2.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(type, finalPathPrefix.concat("/slider_2/active.png")));
+ template2.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(type, finalPathPrefix.concat("/slider_2/fixed.png")));
+ resourceStore.addTemplate(CaptchaTypeConstant.SLIDER, template2);
+ });
+
+ // 旋转验证
+ defaultTemplateResource.put(CaptchaTypeConstant.ROTATE, resourceStore -> {
+ // 添加一些系统的 模板文件
+ ResourceMap template1 = new ResourceMap(DEFAULT_TAG, 4);
+ template1.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(type, finalPathPrefix.concat("/rotate_1/active.png")));
+ template1.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(type, finalPathPrefix.concat("/rotate_1/fixed.png")));
+ resourceStore.addTemplate(CaptchaTypeConstant.ROTATE, template1);
+ });
+ }
+
+
+ public void addDefaultTemplate(String type, ResourceStore resourceStore) {
+ Consumer resourceStoreConsumer = defaultTemplateResource.get(type);
+ if (resourceStoreConsumer == null) {
+ return;
+ }
+ resourceStoreConsumer.accept(resourceStore);
+ }
+
+ public void addDefaultTemplate(ResourceStore resourceStore) {
+ defaultTemplateResource.forEach((type, consumer) -> {
+ consumer.accept(resourceStore);
+ });
+ }
+
+}
diff --git a/src/main/resources/META-INF/cut-image/template/3/active.png b/src/main/resources/META-INF/cut-image/template/rotate_1/active.png
similarity index 100%
rename from src/main/resources/META-INF/cut-image/template/3/active.png
rename to src/main/resources/META-INF/cut-image/template/rotate_1/active.png
diff --git a/src/main/resources/META-INF/cut-image/template/3/fixed.png b/src/main/resources/META-INF/cut-image/template/rotate_1/fixed.png
similarity index 100%
rename from src/main/resources/META-INF/cut-image/template/3/fixed.png
rename to src/main/resources/META-INF/cut-image/template/rotate_1/fixed.png
diff --git a/src/main/resources/META-INF/cut-image/template/1/active.png b/src/main/resources/META-INF/cut-image/template/slider_1/active.png
similarity index 100%
rename from src/main/resources/META-INF/cut-image/template/1/active.png
rename to src/main/resources/META-INF/cut-image/template/slider_1/active.png
diff --git a/src/main/resources/META-INF/cut-image/template/1/fixed.png b/src/main/resources/META-INF/cut-image/template/slider_1/fixed.png
similarity index 100%
rename from src/main/resources/META-INF/cut-image/template/1/fixed.png
rename to src/main/resources/META-INF/cut-image/template/slider_1/fixed.png
diff --git a/src/main/resources/META-INF/cut-image/template/2/active.png b/src/main/resources/META-INF/cut-image/template/slider_2/active.png
similarity index 100%
rename from src/main/resources/META-INF/cut-image/template/2/active.png
rename to src/main/resources/META-INF/cut-image/template/slider_2/active.png
diff --git a/src/main/resources/META-INF/cut-image/template/2/fixed.png b/src/main/resources/META-INF/cut-image/template/slider_2/fixed.png
similarity index 100%
rename from src/main/resources/META-INF/cut-image/template/2/fixed.png
rename to src/main/resources/META-INF/cut-image/template/slider_2/fixed.png
diff --git a/src/main/test/java/example/readme/ApplicationTest.java b/src/main/test/java/example/readme/ApplicationTest.java
index 5dca1da..bb812ed 100644
--- a/src/main/test/java/example/readme/ApplicationTest.java
+++ b/src/main/test/java/example/readme/ApplicationTest.java
@@ -54,7 +54,7 @@ public class ApplicationTest {
// 验证码资源管理器 该类负责管理验证码背景图和模板图等数据
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager();
// 验证码生成器; 注意: 生成器必须调用init(...)初始化方法 true为加载默认资源,false为不加载,
- ImageCaptchaGenerator generator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager).init(true);
+ ImageCaptchaGenerator generator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager).init();
// 验证码校验器
ImageCaptchaValidator imageCaptchaValidator = new SimpleImageCaptchaValidator();
// 缓存, 用于存放校验数据
diff --git a/src/main/test/java/example/readme/SimpleDemo.java b/src/main/test/java/example/readme/SimpleDemo.java
index 2359619..297349d 100644
--- a/src/main/test/java/example/readme/SimpleDemo.java
+++ b/src/main/test/java/example/readme/SimpleDemo.java
@@ -22,7 +22,7 @@ public class SimpleDemo {
public static void main(String[] args) throws InterruptedException {
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager();
ImageTransform imageTransform = new Base64ImageTransform();
- ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,imageTransform).init(true);
+ ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,imageTransform).init();
BasicCaptchaTrackValidator imageCaptchaValidator = new BasicCaptchaTrackValidator();
// 注意: 上面这个四个对象都是单例的, 整个项目创建一次即可
diff --git a/src/main/test/java/example/readme/TACBuilderTest.java b/src/main/test/java/example/readme/TACBuilderTest.java
new file mode 100644
index 0000000..1b15595
--- /dev/null
+++ b/src/main/test/java/example/readme/TACBuilderTest.java
@@ -0,0 +1,22 @@
+package example.readme;
+
+import cloud.tianai.captcha.application.ImageCaptchaApplication;
+import cloud.tianai.captcha.application.TACBuilder;
+import cloud.tianai.captcha.application.vo.CaptchaResponse;
+import cloud.tianai.captcha.application.vo.ImageCaptchaVO;
+import cloud.tianai.captcha.resource.common.model.dto.Resource;
+
+public class TACBuilderTest {
+
+ public static void main(String[] args) {
+ TACBuilder builder = TACBuilder.builder();
+ ImageCaptchaApplication application = builder
+ .addDefaultTemplate()
+ .addResource("SLIDER", new Resource("classpath", "META-INF/cut-image/resource/1.jpg"))
+ .build();
+ CaptchaResponse response = application.generateCaptcha("SLIDER");
+ System.out.println(response);
+
+ }
+}
+
diff --git a/src/main/test/java/example/readme/Test.java b/src/main/test/java/example/readme/Test.java
index e68d956..5a44ecf 100644
--- a/src/main/test/java/example/readme/Test.java
+++ b/src/main/test/java/example/readme/Test.java
@@ -16,7 +16,7 @@ public class Test {
public static void main(String[] args) throws InterruptedException {
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager();
Base64ImageTransform imageTransform = new Base64ImageTransform();
- ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,imageTransform).init(true);
+ ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,imageTransform).init();
/*
生成滑块验证码图片, 可选项
SLIDER (滑块验证码)
diff --git a/src/main/test/java/example/readme/Test3.java b/src/main/test/java/example/readme/Test3.java
index 0c0575a..2646145 100644
--- a/src/main/test/java/example/readme/Test3.java
+++ b/src/main/test/java/example/readme/Test3.java
@@ -15,7 +15,7 @@ public class Test3 {
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager();
Base64ImageTransform imageTransform = new Base64ImageTransform();
// 标准验证码生成器
- ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,imageTransform).init(true);
+ ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,imageTransform).init();
// 生成 具有混淆的 滑块验证码 (目前只有滑块验证码支持混淆滑块, 旋转验证,滑动还原,点选验证 均不支持混淆功能)
ImageCaptchaInfo imageCaptchaInfo = imageCaptchaGenerator.generateCaptchaImage(GenerateParam.builder()
// 设置验证码类型
diff --git a/src/main/test/java/example/readme/Test4.java b/src/main/test/java/example/readme/Test4.java
index 752e6d1..fcd27a1 100644
--- a/src/main/test/java/example/readme/Test4.java
+++ b/src/main/test/java/example/readme/Test4.java
@@ -14,7 +14,7 @@ public class Test4 {
// 资源管理器
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager();
// 标准验证码生成器
- ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,new Base64ImageTransform()).init(true);
+ ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,new Base64ImageTransform()).init();
// 生成旋转验证码 图片类型为 webp
// 注意 tianai-captcha 后面默认删除了生成webp格式图片需要用户自定义添加webp转换的工具,需要用户自定义添加和扩展
// 参考 https://bitbucket.org/luciad/webp-imageio
diff --git a/src/main/test/java/example/readme/Test7.java b/src/main/test/java/example/readme/Test7.java
index 57f9b62..2f9505c 100644
--- a/src/main/test/java/example/readme/Test7.java
+++ b/src/main/test/java/example/readme/Test7.java
@@ -30,7 +30,7 @@ public class Test7 {
}
};
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager();
- ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,new Base64ImageTransform()).init(false);
+ ImageCaptchaGenerator imageCaptchaGenerator = new MultiImageCaptchaGenerator(imageCaptchaResourceManager,new Base64ImageTransform()).init();
// 注册
imageCaptchaResourceManager.registerResourceProvider(resourceProvider);
}
diff --git a/src/main/test/java/example/readme/Test8.java b/src/main/test/java/example/readme/Test8.java
index 0e3aed0..22733f7 100644
--- a/src/main/test/java/example/readme/Test8.java
+++ b/src/main/test/java/example/readme/Test8.java
@@ -18,7 +18,7 @@ public class Test8 {
// 参数四: 检查时间间隔
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager();
ImageCaptchaGenerator imageCaptchaGenerator = new CacheImageCaptchaGenerator(new MultiImageCaptchaGenerator(imageCaptchaResourceManager,new Base64ImageTransform()), 10, 1000, 100);
- imageCaptchaGenerator.init(true);
+ imageCaptchaGenerator.init();
// 生成滑块图片
ImageCaptchaInfo slideImageInfo = imageCaptchaGenerator.generateCaptchaImage(CaptchaTypeConstant.SLIDER);
// 获取背景图片的base64