mirror of
https://github.com/dromara/tianai-captcha.git
synced 2026-05-21 17:02:53 +08:00
1.5.0正式版
This commit is contained in:
@@ -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();
|
||||
|
||||
/**
|
||||
* 生成验证码方法
|
||||
|
||||
@@ -17,10 +17,9 @@ public interface ImageCaptchaGenerator {
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
* @param initDefaultResource 是否初始化默认资源
|
||||
* @return ImageCaptchaGenerator
|
||||
*/
|
||||
ImageCaptchaGenerator init(boolean initDefaultResource);
|
||||
ImageCaptchaGenerator init();
|
||||
|
||||
/**
|
||||
* 生成验证码图片
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<String, ImageCaptchaGenerator> imageCaptchaGeneratorMap = new ConcurrentHashMap<>(4);
|
||||
protected Map<String, ImageCaptchaGeneratorProvider> imageCaptchaGeneratorProviderMap = new HashMap<>(4);
|
||||
|
||||
// 点选类验证码字体
|
||||
@Setter
|
||||
@Getter
|
||||
protected List<FontWrapper> 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;
|
||||
}
|
||||
|
||||
+1
-13
@@ -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) {
|
||||
|
||||
+1
-21
@@ -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) {
|
||||
|
||||
+2
-29
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-26
@@ -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<ClickImageCheckDefinition> imageCheckDefinitions) {
|
||||
|
||||
Reference in New Issue
Block a user