加入旋转图片验证码

This commit is contained in:
天爱有情
2022-04-24 13:21:53 +08:00
parent aa8f774551
commit bf971e2d9f
14 changed files with 205 additions and 115 deletions
+1 -1
View File
@@ -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>
+17 -17
View File
@@ -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);
}
}
@@ -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);
}
}
@@ -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();
}
@@ -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;
}
@@ -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();
}
@@ -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;
}
}
@@ -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 {
@@ -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")));
@@ -9,9 +9,9 @@ import java.util.Map;
/**
* @Author: 天爱有情
* @date 2021/8/7 15:26
* @Description 滑块验证码图片资源管理器
* @Description 验证码图片资源管理器
*/
public interface SliderCaptchaResourceManager {
public interface ImageCaptchaResourceManager {
/**
* 随机获取某个模板
@@ -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());