mirror of
https://github.com/dromara/tianai-captcha.git
synced 2026-05-07 06:04:34 +08:00
加入旋转图片验证码
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>cloud.tianai.captcha</groupId>
|
||||
<artifactId>tianai-captcha</artifactId>
|
||||
<version>1.3.0.RELEASE</version>
|
||||
<version>1.3.1.alpha</version>
|
||||
|
||||
<name>tianai-captcha</name>
|
||||
<description>滑块验证码</description>
|
||||
|
||||
@@ -34,15 +34,15 @@
|
||||
### 2. 使用 `SliderCaptchaGenerator`生成器生成滑块验证码
|
||||
|
||||
```java
|
||||
import cloud.tianai.captcha.template.slider.generator.impl.StandardImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.impl.StandardSliderImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.impl.StandardSliderCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.resource.SliderCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.DefaultSliderCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.DefaultImageCaptchaResourceManager;
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
SliderCaptchaResourceManager sliderCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
StandardImageCaptchaGenerator sliderCaptchaGenerator = new StandardImageCaptchaGenerator(sliderCaptchaResourceManager, true);
|
||||
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager();
|
||||
StandardSliderImageCaptchaGenerator sliderCaptchaGenerator = new StandardSliderImageCaptchaGenerator(imageCaptchaResourceManager, true);
|
||||
// 生成滑块图片
|
||||
SliderCaptchaInfo slideImageInfo = sliderCaptchaGenerator.generateCaptchaImage();
|
||||
System.out.println(slideImageInfo);
|
||||
@@ -101,9 +101,9 @@ public class Test2 {
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
// 资源管理器
|
||||
SliderCaptchaResourceManager sliderCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
SliderCaptchaResourceManager imageCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
// 标准验证码生成器
|
||||
StandardSliderCaptchaGenerator sliderCaptchaGenerator = new StandardSliderCaptchaGenerator(sliderCaptchaResourceManager, true);
|
||||
StandardSliderCaptchaGenerator sliderCaptchaGenerator = new StandardSliderCaptchaGenerator(imageCaptchaResourceManager, true);
|
||||
// 生成滑块图片
|
||||
SliderCaptchaInfo slideImageInfo = sliderCaptchaGenerator.generateSlideImageInfo(GenerateParam.builder()
|
||||
.sliderFormatName("jpeg")
|
||||
@@ -121,9 +121,9 @@ public class Test {
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
// 资源管理器
|
||||
SliderCaptchaResourceManager sliderCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
SliderCaptchaResourceManager imageCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
// 标准验证码生成器
|
||||
StandardSliderCaptchaGenerator sliderCaptchaGenerator = new StandardSliderCaptchaGenerator(sliderCaptchaResourceManager, true);
|
||||
StandardSliderCaptchaGenerator sliderCaptchaGenerator = new StandardSliderCaptchaGenerator(imageCaptchaResourceManager, true);
|
||||
// 生成滑块图片
|
||||
SliderCaptchaInfo slideImageInfo = sliderCaptchaGenerator.generateSlideImageInfo(GenerateParam.builder()
|
||||
.sliderFormatName("webp")
|
||||
@@ -143,7 +143,7 @@ public class Test {
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
// 通过资源管理器或者资源存储器
|
||||
ResourceStore resourceStore = sliderCaptchaResourceManager.getResourceStore();
|
||||
ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
|
||||
// 添加classpath目录下的 aa.jpg 图片
|
||||
resourceStore.addResource(new Resource(ClassPathResourceProvider.NAME, "/aa.jpg"));
|
||||
// 添加远程url图片资源
|
||||
@@ -165,7 +165,7 @@ public class Test {
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
// 通过资源管理器或者资源存储器
|
||||
ResourceStore resourceStore = sliderCaptchaResourceManager.getResourceStore();
|
||||
ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
|
||||
// 添加模板.模板图片由三张图片组成
|
||||
Map<String, Resource> template1 = new HashMap<>(4);
|
||||
template1.put(SliderCaptchaConstant.TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, "/active.png"));
|
||||
@@ -185,7 +185,7 @@ public class Test {
|
||||
public static void main(String[] args) {
|
||||
//为方便快速上手 系统本身自带了一张图片和两套滑块模板,如果不想用系统自带的可以不让它加载系统自带的
|
||||
// 第二个构造参数设置为false时将不加载默认的图片和模板
|
||||
SliderCaptchaGenerator sliderCaptchaGenerator = new StandardSliderCaptchaGenerator(sliderCaptchaResourceManager, false);
|
||||
SliderCaptchaGenerator sliderCaptchaGenerator = new StandardSliderCaptchaGenerator(imageCaptchaResourceManager, false);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -207,10 +207,10 @@ public class Test {
|
||||
public class Test {
|
||||
public static void main(String[] args) {
|
||||
// 实现了 ResourceProvider 后
|
||||
SliderCaptchaResourceManager sliderCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
StandardSliderCaptchaGenerator sliderCaptchaGenerator = new StandardSliderCaptchaGenerator(sliderCaptchaResourceManager, true);
|
||||
SliderCaptchaResourceManager imageCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
StandardSliderCaptchaGenerator sliderCaptchaGenerator = new StandardSliderCaptchaGenerator(imageCaptchaResourceManager, true);
|
||||
// 注册
|
||||
sliderCaptchaResourceManager.registerResourceProvider(new CustomResourceProvider());
|
||||
imageCaptchaResourceManager.registerResourceProvider(new CustomResourceProvider());
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -227,8 +227,8 @@ public class Test {
|
||||
// 参数二: 默认提前缓存多少个
|
||||
// 参数三: 出错后 等待xx时间再进行生成
|
||||
// 参数四: 检查时间间隔
|
||||
SliderCaptchaResourceManager sliderCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
SliderCaptchaGenerator sliderCaptchaGenerator = new CacheSliderCaptchaGenerator(new StandardSliderCaptchaGenerator(sliderCaptchaResourceManager, true), 10, 1000, 100);
|
||||
SliderCaptchaResourceManager imageCaptchaResourceManager = new DefaultSliderCaptchaResourceManager();
|
||||
SliderCaptchaGenerator sliderCaptchaGenerator = new CacheSliderCaptchaGenerator(new StandardSliderCaptchaGenerator(imageCaptchaResourceManager, true), 10, 1000, 100);
|
||||
// 生成滑块图片
|
||||
SliderCaptchaInfo slideImageInfo = sliderCaptchaGenerator.generateSlideImageInfo();
|
||||
// 获取背景图片的base64
|
||||
|
||||
@@ -215,4 +215,14 @@ public class CaptchaImageUtils {
|
||||
return img;
|
||||
}
|
||||
|
||||
public static void centerOverlayAndRotateImage(BufferedImage baseBufferedImage, BufferedImage coverBufferedImage,
|
||||
final double degree) {
|
||||
coverBufferedImage = rotateImage(coverBufferedImage, degree);
|
||||
int bw = baseBufferedImage.getWidth();
|
||||
int bh = baseBufferedImage.getHeight();
|
||||
int cw = coverBufferedImage.getWidth();
|
||||
int ch = coverBufferedImage.getHeight();
|
||||
overlayImage(baseBufferedImage, coverBufferedImage, bw / 2 - cw / 2, bh / 2 - ch / 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-2
@@ -14,7 +14,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -71,7 +70,7 @@ public abstract class AbstractImageCaptchaGenerator implements ImageCaptchaGener
|
||||
if (resource == null) {
|
||||
throw new IllegalArgumentException("查找模板异常, 该模板下未找到 ".concat(imageName));
|
||||
}
|
||||
return getSlideImageResourceManager().getResourceInputStream(resource);
|
||||
return getImageResourceManager().getResourceInputStream(resource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-3
@@ -3,8 +3,7 @@ package cloud.tianai.captcha.template.slider.generator;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.resource.SliderCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.validator.SliderCaptchaValidator;
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -45,6 +44,6 @@ public interface ImageCaptchaGenerator {
|
||||
*
|
||||
* @return SliderCaptchaResourceManager
|
||||
*/
|
||||
SliderCaptchaResourceManager getSlideImageResourceManager();
|
||||
ImageCaptchaResourceManager getImageResourceManager();
|
||||
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,9 +1,7 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.common.model.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.constant.CaptchaTypeConstant;
|
||||
import lombok.*;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -14,6 +12,7 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public class GenerateParam {
|
||||
/** 背景格式化名称.*/
|
||||
private String backgroundFormatName = "jpeg";
|
||||
@@ -22,5 +21,5 @@ public class GenerateParam {
|
||||
/** 是否混淆.*/
|
||||
private Boolean obfuscate = false;
|
||||
/** 类型.*/
|
||||
private String type;
|
||||
private String type = CaptchaTypeConstant.SLIDER;
|
||||
}
|
||||
|
||||
+50
-42
@@ -1,19 +1,17 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.common.util.NamedThreadFactory;
|
||||
import cloud.tianai.captcha.template.slider.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.common.util.NamedThreadFactory;
|
||||
import cloud.tianai.captcha.template.slider.resource.SliderCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
@@ -25,29 +23,26 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
|
||||
|
||||
protected final ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("slider-captcha-queue"));
|
||||
protected ConcurrentLinkedQueue<ImageCaptchaInfo> queue;
|
||||
protected AtomicInteger pos = new AtomicInteger(0);
|
||||
protected Map<GenerateParam, ConcurrentLinkedQueue<ImageCaptchaInfo>> queueMap = new ConcurrentHashMap<>(8);
|
||||
protected Map<GenerateParam, AtomicInteger> posMap = new ConcurrentHashMap<>(8);
|
||||
protected ImageCaptchaGenerator target;
|
||||
protected int size;
|
||||
/** 等待时间,一般报错或者拉取为空时会休眠一段时间再试. */
|
||||
protected int waitTime = 1000;
|
||||
/** 调度器检查缓存的间隔时间. */
|
||||
protected int period = 100;
|
||||
protected GenerateParam generateParam;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
protected boolean requiredGetCaptcha = true;
|
||||
|
||||
public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, GenerateParam generateParam, int size) {
|
||||
public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, int size) {
|
||||
this.target = target;
|
||||
this.generateParam = generateParam;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, GenerateParam generateParam, int size, int waitTime, int period) {
|
||||
public CacheImageCaptchaGenerator(ImageCaptchaGenerator target, int size, int waitTime, int period) {
|
||||
this.target = target;
|
||||
this.generateParam = generateParam;
|
||||
this.size = size;
|
||||
this.waitTime = waitTime;
|
||||
this.period = period;
|
||||
@@ -62,34 +57,35 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
|
||||
|
||||
private void init(int z) {
|
||||
this.size = z;
|
||||
this.pos = new AtomicInteger(0);
|
||||
queue = new ConcurrentLinkedQueue<>();
|
||||
// 初始化一个队列扫描
|
||||
scheduledExecutor.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
while (pos.get() < this.size) {
|
||||
if (pos.get() >= size) {
|
||||
return;
|
||||
}
|
||||
ImageCaptchaInfo slideImageInfo = target.generateCaptchaImage(generateParam);
|
||||
if (slideImageInfo != null) {
|
||||
boolean addStatus = queue.offer(slideImageInfo);
|
||||
if (addStatus) {
|
||||
// 添加记录
|
||||
pos.incrementAndGet();
|
||||
queueMap.forEach((k, queue) -> {
|
||||
try {
|
||||
AtomicInteger pos = posMap.computeIfAbsent(k, k1 -> new AtomicInteger(0));
|
||||
while (pos.get() < this.size) {
|
||||
if (pos.get() >= size) {
|
||||
return;
|
||||
}
|
||||
ImageCaptchaInfo slideImageInfo = target.generateCaptchaImage(k);
|
||||
if (slideImageInfo != null) {
|
||||
boolean addStatus = queue.offer(slideImageInfo);
|
||||
if (addStatus) {
|
||||
// 添加记录
|
||||
pos.incrementAndGet();
|
||||
}
|
||||
} else {
|
||||
sleep();
|
||||
}
|
||||
} else {
|
||||
sleep();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// cache所有
|
||||
log.error("缓存队列扫描时出错, ex", e);
|
||||
// 休眠
|
||||
sleep();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// cache所有
|
||||
log.error("缓存队列扫描时出错, ex", e);
|
||||
// 休眠
|
||||
sleep();
|
||||
}
|
||||
});
|
||||
|
||||
}, 0, period, TimeUnit.MILLISECONDS);
|
||||
log.info("缓存滑块验证码调度器初始化完成: size:{}, genParam:{}", size, generateParam);
|
||||
}
|
||||
|
||||
private void sleep() {
|
||||
@@ -102,11 +98,14 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public ImageCaptchaInfo generateCaptchaImage(String type) {
|
||||
return generateCaptchaImage(this.requiredGetCaptcha);
|
||||
GenerateParam generateParam = new GenerateParam();
|
||||
generateParam.setType(type);
|
||||
return generateCaptchaImage(generateParam, this.requiredGetCaptcha);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public ImageCaptchaInfo generateCaptchaImage(boolean requiredGetCaptcha) {
|
||||
public ImageCaptchaInfo generateCaptchaImage(GenerateParam generateParam, boolean requiredGetCaptcha) {
|
||||
ConcurrentLinkedQueue<ImageCaptchaInfo> queue = queueMap.computeIfAbsent(generateParam, g -> new ConcurrentLinkedQueue<>());
|
||||
ImageCaptchaInfo poll = queue.poll();
|
||||
if (poll == null && requiredGetCaptcha) {
|
||||
log.warn("滑块验证码缓存不足, genParam:{}", generateParam);
|
||||
@@ -114,23 +113,32 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
|
||||
return target.generateCaptchaImage(generateParam);
|
||||
}
|
||||
// 减1
|
||||
pos.decrementAndGet();
|
||||
if (poll == null) {
|
||||
AtomicInteger pos = posMap.get(generateParam);
|
||||
if (pos != null) {
|
||||
pos.decrementAndGet();
|
||||
}
|
||||
}
|
||||
return poll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCaptchaInfo generateCaptchaImage(String type, String targetFormatName, String matrixFormatName) {
|
||||
return target.generateCaptchaImage(type,targetFormatName, matrixFormatName);
|
||||
return generateCaptchaImage(GenerateParam.builder()
|
||||
.type(type)
|
||||
.backgroundFormatName(targetFormatName)
|
||||
.sliderFormatName(matrixFormatName)
|
||||
.build(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCaptchaInfo generateCaptchaImage(GenerateParam param) {
|
||||
return target.generateCaptchaImage(param);
|
||||
return generateCaptchaImage(param, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SliderCaptchaResourceManager getSlideImageResourceManager() {
|
||||
return target.getSlideImageResourceManager();
|
||||
public ImageCaptchaResourceManager getImageResourceManager() {
|
||||
return target.getImageResourceManager();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.common.util.ObjectUtils;
|
||||
import cloud.tianai.captcha.template.slider.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/4/24 9:27
|
||||
* @Description 根据type 匹配对应的验证码生成器
|
||||
*/
|
||||
public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
private Map<String, ImageCaptchaGenerator> imageCaptchaGeneratorMap = new HashMap<>(4);
|
||||
|
||||
private ImageCaptchaResourceManager imageCaptchaResourceManager;
|
||||
private boolean initDefaultResource;
|
||||
|
||||
private String defaultCaptcha = CaptchaTypeConstant.SLIDER;
|
||||
public MultiImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, boolean initDefaultResource) {
|
||||
this.imageCaptchaResourceManager = imageCaptchaResourceManager;
|
||||
this.initDefaultResource = initDefaultResource;
|
||||
init();
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
addImageCaptchaGenerator(CaptchaTypeConstant.SLIDER, new StandardSliderImageCaptchaGenerator(imageCaptchaResourceManager, initDefaultResource));
|
||||
addImageCaptchaGenerator(CaptchaTypeConstant.ROTATE, new StandardRotateImageCaptchaGenerator(imageCaptchaResourceManager, initDefaultResource));
|
||||
}
|
||||
|
||||
public void addImageCaptchaGenerator(String key, ImageCaptchaGenerator captchaGenerator) {
|
||||
imageCaptchaGeneratorMap.put(key, captchaGenerator);
|
||||
}
|
||||
public ImageCaptchaGenerator removeImageCaptchaGenerator(String key) {
|
||||
return imageCaptchaGeneratorMap.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCaptchaInfo generateCaptchaImage(GenerateParam param) {
|
||||
String type = param.getType();
|
||||
if (ObjectUtils.isEmpty(type)){
|
||||
param.setType(defaultCaptcha);
|
||||
type = defaultCaptcha;
|
||||
}
|
||||
ImageCaptchaGenerator imageCaptchaGenerator = imageCaptchaGeneratorMap.get(type);
|
||||
if (imageCaptchaGenerator == null) {
|
||||
throw new IllegalArgumentException("生成验证码失败,错误的type类型:" + type);
|
||||
}
|
||||
|
||||
return imageCaptchaGenerator.generateCaptchaImage(param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCaptchaResourceManager getImageResourceManager() {
|
||||
return imageCaptchaResourceManager;
|
||||
}
|
||||
}
|
||||
+32
-16
@@ -7,8 +7,8 @@ import cloud.tianai.captcha.template.slider.generator.common.constant.SliderCapt
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.RotateImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.ResourceStore;
|
||||
import cloud.tianai.captcha.template.slider.resource.SliderCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.provider.ClassPathResourceProvider;
|
||||
import lombok.SneakyThrows;
|
||||
@@ -26,27 +26,27 @@ import java.util.Map;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import static cloud.tianai.captcha.template.slider.common.util.CaptchaImageUtils.*;
|
||||
import static cloud.tianai.captcha.template.slider.generator.impl.StandardImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH;
|
||||
import static cloud.tianai.captcha.template.slider.generator.impl.StandardImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH;
|
||||
import static cloud.tianai.captcha.template.slider.generator.impl.StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH;
|
||||
import static cloud.tianai.captcha.template.slider.generator.impl.StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/4/22 16:43
|
||||
* @Description 旋转图片验证码生成器
|
||||
*/
|
||||
public class StandardRotateCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
protected final SliderCaptchaResourceManager sliderCaptchaResourceManager;
|
||||
protected final ImageCaptchaResourceManager imageCaptchaResourceManager;
|
||||
|
||||
public StandardRotateCaptchaGenerator(SliderCaptchaResourceManager sliderCaptchaResourceManager, boolean initDefaultResource) {
|
||||
this.sliderCaptchaResourceManager = sliderCaptchaResourceManager;
|
||||
public StandardRotateImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, boolean initDefaultResource) {
|
||||
this.imageCaptchaResourceManager = imageCaptchaResourceManager;
|
||||
if (initDefaultResource) {
|
||||
initDefaultResource();
|
||||
}
|
||||
}
|
||||
|
||||
public void initDefaultResource() {
|
||||
ResourceStore resourceStore = sliderCaptchaResourceManager.getResourceStore();
|
||||
ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
|
||||
// 添加一些系统的资源文件
|
||||
resourceStore.addResource(CaptchaTypeConstant.ROTATE, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg")));
|
||||
|
||||
@@ -54,6 +54,7 @@ public class StandardRotateCaptchaGenerator extends AbstractImageCaptchaGenerato
|
||||
Map<String, Resource> template1 = new HashMap<>(4);
|
||||
template1.put(SliderCaptchaConstant.TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/active.png")));
|
||||
template1.put(SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/fixed.png")));
|
||||
template1.put(SliderCaptchaConstant.TEMPLATE_MATRIX_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/matrix.png")));
|
||||
resourceStore.addTemplate(CaptchaTypeConstant.ROTATE, template1);
|
||||
}
|
||||
|
||||
@@ -61,14 +62,14 @@ public class StandardRotateCaptchaGenerator extends AbstractImageCaptchaGenerato
|
||||
public ImageCaptchaInfo generateCaptchaImage(GenerateParam param) {
|
||||
// 旋转验证码没有混淆
|
||||
Boolean obfuscate = param.getObfuscate();
|
||||
Map<String, Resource> templateImages = sliderCaptchaResourceManager.randomGetTemplate(param.getType());
|
||||
Map<String, Resource> templateImages = imageCaptchaResourceManager.randomGetTemplate(param.getType());
|
||||
if (templateImages == null || templateImages.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Collection<InputStream> inputStreams = new LinkedList<>();
|
||||
try {
|
||||
Resource resourceImage = sliderCaptchaResourceManager.randomGetResource(param.getType());
|
||||
InputStream resourceInputStream = sliderCaptchaResourceManager.getResourceInputStream(resourceImage);
|
||||
Resource resourceImage = imageCaptchaResourceManager.randomGetResource(param.getType());
|
||||
InputStream resourceInputStream = imageCaptchaResourceManager.getResourceInputStream(resourceImage);
|
||||
inputStreams.add(resourceInputStream);
|
||||
BufferedImage cutBackground = wrapFile2BufferedImage(resourceInputStream);
|
||||
// 拷贝一份图片
|
||||
@@ -81,6 +82,11 @@ public class StandardRotateCaptchaGenerator extends AbstractImageCaptchaGenerato
|
||||
InputStream activeTemplateInput = getTemplateFile(templateImages, SliderCaptchaConstant.TEMPLATE_ACTIVE_IMAGE_NAME);
|
||||
inputStreams.add(activeTemplateInput);
|
||||
BufferedImage activeTemplate = wrapFile2BufferedImage(activeTemplateInput);
|
||||
|
||||
InputStream matrixTemplateInput = getTemplateFile(templateImages, SliderCaptchaConstant.TEMPLATE_MATRIX_IMAGE_NAME);
|
||||
inputStreams.add(matrixTemplateInput);
|
||||
BufferedImage matrixTemplate = wrapFile2BufferedImage(matrixTemplateInput);
|
||||
|
||||
// 算出居中的x和y
|
||||
int x = targetBackground.getWidth() / 2 - fixedTemplate.getWidth() / 2;
|
||||
int y = targetBackground.getHeight() / 2 - fixedTemplate.getHeight() / 2;
|
||||
@@ -91,10 +97,10 @@ public class StandardRotateCaptchaGenerator extends AbstractImageCaptchaGenerato
|
||||
// 随机旋转抠图部分
|
||||
// 随机x, 转换为角度
|
||||
int randomX = ThreadLocalRandom.current().nextInt(fixedTemplate.getWidth() + 10, targetBackground.getWidth() - 10);
|
||||
double degree = randomX / ((targetBackground.getWidth()) / 360d);
|
||||
double degree = 360d - randomX / ((targetBackground.getWidth()) / 360d);
|
||||
// int degree = ThreadLocalRandom.current().nextInt(10, 350);
|
||||
cutImage = rotateImage(cutImage, degree);
|
||||
return wrapRotateCaptchaInfo(degree, randomX, targetBackground, cutImage, param);
|
||||
centerOverlayAndRotateImage(matrixTemplate, cutImage, degree);
|
||||
return wrapRotateCaptchaInfo(degree, randomX, targetBackground, matrixTemplate, param);
|
||||
} finally {
|
||||
// 使用完后关闭流
|
||||
for (InputStream inputStream : inputStreams) {
|
||||
@@ -122,9 +128,19 @@ public class StandardRotateCaptchaGenerator extends AbstractImageCaptchaGenerato
|
||||
);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public String transform(BufferedImage bufferedImage, String formatType) throws IOException {
|
||||
// FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Thinkpad\\Desktop\\aa" + formatType + "." + formatType);
|
||||
// ImageIO.write(bufferedImage, formatType, fileOutputStream);
|
||||
// fileOutputStream.close();
|
||||
//// return super.transform(bufferedImage, formatType);
|
||||
// return "";
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public SliderCaptchaResourceManager getSlideImageResourceManager() {
|
||||
return sliderCaptchaResourceManager;
|
||||
public ImageCaptchaResourceManager getImageResourceManager() {
|
||||
return imageCaptchaResourceManager;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
+12
-12
@@ -6,8 +6,8 @@ import cloud.tianai.captcha.template.slider.generator.common.constant.SliderCapt
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.SliderImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.ResourceStore;
|
||||
import cloud.tianai.captcha.template.slider.resource.SliderCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.provider.ClassPathResourceProvider;
|
||||
import lombok.SneakyThrows;
|
||||
@@ -30,7 +30,7 @@ import static cloud.tianai.captcha.template.slider.common.util.CaptchaImageUtils
|
||||
* @Description 滑块验证码模板
|
||||
*/
|
||||
@Slf4j
|
||||
public class StandardImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
/**
|
||||
* 默认的resource资源文件路径.
|
||||
@@ -41,12 +41,12 @@ public class StandardImageCaptchaGenerator extends AbstractImageCaptchaGenerator
|
||||
*/
|
||||
public static final String DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH = "META-INF/cut-image/template";
|
||||
|
||||
protected final SliderCaptchaResourceManager sliderCaptchaResourceManager;
|
||||
protected final ImageCaptchaResourceManager imageCaptchaResourceManager;
|
||||
|
||||
|
||||
public StandardImageCaptchaGenerator(SliderCaptchaResourceManager sliderCaptchaResourceManager,
|
||||
boolean initDefaultResource) {
|
||||
this.sliderCaptchaResourceManager = sliderCaptchaResourceManager;
|
||||
public StandardSliderImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager,
|
||||
boolean initDefaultResource) {
|
||||
this.imageCaptchaResourceManager = imageCaptchaResourceManager;
|
||||
if (initDefaultResource) {
|
||||
initDefaultResource();
|
||||
}
|
||||
@@ -56,14 +56,14 @@ public class StandardImageCaptchaGenerator extends AbstractImageCaptchaGenerator
|
||||
@Override
|
||||
public ImageCaptchaInfo generateCaptchaImage(GenerateParam param) {
|
||||
Boolean obfuscate = param.getObfuscate();
|
||||
Map<String, Resource> templateImages = sliderCaptchaResourceManager.randomGetTemplate(param.getType());
|
||||
Map<String, Resource> templateImages = imageCaptchaResourceManager.randomGetTemplate(param.getType());
|
||||
if (templateImages == null || templateImages.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Collection<InputStream> inputStreams = new LinkedList<>();
|
||||
try {
|
||||
Resource resourceImage = sliderCaptchaResourceManager.randomGetResource(param.getType());
|
||||
InputStream resourceInputStream = sliderCaptchaResourceManager.getResourceInputStream(resourceImage);
|
||||
Resource resourceImage = imageCaptchaResourceManager.randomGetResource(param.getType());
|
||||
InputStream resourceInputStream = imageCaptchaResourceManager.getResourceInputStream(resourceImage);
|
||||
inputStreams.add(resourceInputStream);
|
||||
BufferedImage cutBackground = wrapFile2BufferedImage(resourceInputStream);
|
||||
// 拷贝一份图片
|
||||
@@ -139,8 +139,8 @@ public class StandardImageCaptchaGenerator extends AbstractImageCaptchaGenerator
|
||||
}
|
||||
|
||||
@Override
|
||||
public SliderCaptchaResourceManager getSlideImageResourceManager() {
|
||||
return sliderCaptchaResourceManager;
|
||||
public ImageCaptchaResourceManager getImageResourceManager() {
|
||||
return imageCaptchaResourceManager;
|
||||
}
|
||||
|
||||
protected int randomObfuscateX(int sliderX, int slWidth, int bgWidth) {
|
||||
@@ -156,7 +156,7 @@ public class StandardImageCaptchaGenerator extends AbstractImageCaptchaGenerator
|
||||
* 初始化默认资源
|
||||
*/
|
||||
public void initDefaultResource() {
|
||||
ResourceStore resourceStore = sliderCaptchaResourceManager.getResourceStore();
|
||||
ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
|
||||
// 添加一些系统的资源文件
|
||||
resourceStore.addResource(CaptchaTypeConstant.SLIDER, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg")));
|
||||
|
||||
+2
-2
@@ -9,9 +9,9 @@ import java.util.Map;
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2021/8/7 15:26
|
||||
* @Description 滑块验证码图片资源管理器
|
||||
* @Description 验证码图片资源管理器
|
||||
*/
|
||||
public interface SliderCaptchaResourceManager {
|
||||
public interface ImageCaptchaResourceManager {
|
||||
|
||||
/**
|
||||
* 随机获取某个模板
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package cloud.tianai.captcha.template.slider.resource.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.ResourceProvider;
|
||||
import cloud.tianai.captcha.template.slider.resource.ResourceStore;
|
||||
import cloud.tianai.captcha.template.slider.resource.SliderCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.provider.ClassPathResourceProvider;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.provider.FileResourceProvider;
|
||||
@@ -19,18 +19,18 @@ import java.util.Map;
|
||||
* @date 2021/8/7 15:35
|
||||
* @Description 默认的滑块验证码资源管理
|
||||
*/
|
||||
public class DefaultSliderCaptchaResourceManager implements SliderCaptchaResourceManager {
|
||||
public class DefaultImageCaptchaResourceManager implements ImageCaptchaResourceManager {
|
||||
|
||||
private ResourceStore resourceStore;
|
||||
|
||||
private List<ResourceProvider> resourceProviderList = new ArrayList<>(8);
|
||||
|
||||
|
||||
public DefaultSliderCaptchaResourceManager() {
|
||||
public DefaultImageCaptchaResourceManager() {
|
||||
init();
|
||||
}
|
||||
|
||||
public DefaultSliderCaptchaResourceManager(ResourceStore resourceStore) {
|
||||
public DefaultImageCaptchaResourceManager(ResourceStore resourceStore) {
|
||||
this.resourceStore = resourceStore;
|
||||
init();
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -1,18 +1,13 @@
|
||||
package example;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.generator.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.constant.SliderCaptchaConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.RotateImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.generator.impl.StandardRotateCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.impl.StandardRotateImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.ResourceStore;
|
||||
import cloud.tianai.captcha.template.slider.resource.SliderCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.DefaultImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.DefaultResourceStore;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.DefaultSliderCaptchaResourceManager;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class StandardRotateCaptchaGeneratorTest {
|
||||
|
||||
@@ -25,10 +20,10 @@ public class StandardRotateCaptchaGeneratorTest {
|
||||
// resourceStore.addTemplate(CaptchaTypeConstant.ROTATE, template);
|
||||
// resourceStore.addResource(CaptchaTypeConstant.ROTATE, new Resource("file", "E:\\projects\\tianai-captcha\\src\\main\\resources\\META-INF\\cut-image\\resource\\1.jpg"));
|
||||
|
||||
SliderCaptchaResourceManager sliderCaptchaResourceManager = new DefaultSliderCaptchaResourceManager(resourceStore);
|
||||
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager(resourceStore);
|
||||
|
||||
StandardRotateCaptchaGenerator standardRotateCaptchaGenerator = new StandardRotateCaptchaGenerator(sliderCaptchaResourceManager, true);
|
||||
ImageCaptchaInfo imageCaptchaInfo = standardRotateCaptchaGenerator.generateCaptchaImage(CaptchaTypeConstant.ROTATE);
|
||||
StandardRotateImageCaptchaGenerator standardRotateImageCaptchaGenerator = new StandardRotateImageCaptchaGenerator(imageCaptchaResourceManager, true);
|
||||
ImageCaptchaInfo imageCaptchaInfo = standardRotateImageCaptchaGenerator.generateCaptchaImage(CaptchaTypeConstant.ROTATE);
|
||||
System.out.println("backgroundImage:" + imageCaptchaInfo.getBackgroundImage());
|
||||
System.out.println("sliderImage:" + imageCaptchaInfo.getSliderImage());
|
||||
System.out.println(((RotateImageCaptchaInfo)imageCaptchaInfo).getDegree());
|
||||
|
||||
Reference in New Issue
Block a user