mirror of
https://github.com/dromara/tianai-captcha.git
synced 2026-05-07 06:04:34 +08:00
优化
This commit is contained in:
+2
@@ -15,4 +15,6 @@ public interface CaptchaTypeConstant {
|
||||
String CONCAT = "CONCAT";
|
||||
/** 图片点选.*/
|
||||
String IMAGE_CLICK = "IMAGE_CLICK";
|
||||
/** 文字图片点选.*/
|
||||
String WORD_IMAGE_CLICK = "WORD_IMAGE_CLICK";
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ public class CaptchaUtils {
|
||||
|
||||
/**
|
||||
* 是否是滑动验证码
|
||||
*
|
||||
* @param type 类型
|
||||
* @return boolean
|
||||
*/
|
||||
@@ -22,11 +23,12 @@ public class CaptchaUtils {
|
||||
|
||||
/**
|
||||
* 是否是点击验证码
|
||||
*
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isClickCaptcha(String type) {
|
||||
return CaptchaTypeConstant.IMAGE_CLICK.equals(type);
|
||||
return CaptchaTypeConstant.WORD_IMAGE_CLICK.equals(type) || CaptchaTypeConstant.IMAGE_CLICK.equals(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-1
@@ -15,6 +15,7 @@ public interface ImageCaptchaGenerator {
|
||||
|
||||
/**
|
||||
* 生成验证码图片
|
||||
*
|
||||
* @param type 类型 {@link CaptchaTypeConstant}
|
||||
* @return SliderCaptchaInfo
|
||||
*/
|
||||
@@ -23,7 +24,8 @@ public interface ImageCaptchaGenerator {
|
||||
|
||||
/**
|
||||
* 生成滑块验证码
|
||||
* @param type type {@link CaptchaTypeConstant}
|
||||
*
|
||||
* @param type type {@link CaptchaTypeConstant}
|
||||
* @param targetFormatName jpeg或者webp格式
|
||||
* @param matrixFormatName png或者webp格式
|
||||
* @return SliderCaptchaInfo
|
||||
|
||||
+3
-1
@@ -34,8 +34,10 @@ public class ImageCaptchaInfo {
|
||||
private Integer randomX;
|
||||
/** 容错值, 可以为空 默认 0.02容错,校验的时候用. */
|
||||
private Float tolerant;
|
||||
/** 验证码类型.*/
|
||||
/** 验证码类型. */
|
||||
private String type;
|
||||
/** 透传字段,用于传给前端.*/
|
||||
private Object data;
|
||||
/**
|
||||
* 扩展字段
|
||||
*/
|
||||
|
||||
+10
-8
@@ -406,14 +406,15 @@ public class CaptchaImageUtils {
|
||||
|
||||
/**
|
||||
* 生成简单的验证码图片
|
||||
* @param data 验证码内容
|
||||
* @param font 字体包
|
||||
* @param metrics FontDesignMetrics
|
||||
* @param width 验证码宽度
|
||||
* @param height 验证码高度
|
||||
* @param startX 起始X
|
||||
* @param startY 起始Y
|
||||
* @param interferenceLineNum 干扰线数量
|
||||
*
|
||||
* @param data 验证码内容
|
||||
* @param font 字体包
|
||||
* @param metrics FontDesignMetrics
|
||||
* @param width 验证码宽度
|
||||
* @param height 验证码高度
|
||||
* @param startX 起始X
|
||||
* @param startY 起始Y
|
||||
* @param interferenceLineNum 干扰线数量
|
||||
* @param interferencePointNum 干扰点数量
|
||||
* @return BufferedImage
|
||||
*/
|
||||
@@ -450,6 +451,7 @@ public class CaptchaImageUtils {
|
||||
|
||||
/**
|
||||
* 随机获取颜色
|
||||
*
|
||||
* @return Color
|
||||
*/
|
||||
public static Color getRandomColor(Random random) {
|
||||
|
||||
+43
-48
@@ -1,23 +1,16 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.template.slider.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ClickImageCheckDefinition;
|
||||
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.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.template.slider.resource.common.model.dto.Resource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.*;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@@ -28,12 +21,15 @@ import static cloud.tianai.captcha.template.slider.generator.common.util.Captcha
|
||||
* @date 2022/4/27 11:46
|
||||
* @Description 点选验证码 点选验证码分为点选文字和点选图标等
|
||||
*/
|
||||
@Data
|
||||
public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
/** 参与校验的数量.*/
|
||||
/** 参与校验的数量. */
|
||||
@Getter
|
||||
@Setter
|
||||
protected Integer checkClickCount = 4;
|
||||
/** 干扰数量.*/
|
||||
/** 干扰数量. */
|
||||
@Getter
|
||||
@Setter
|
||||
protected Integer interferenceCount = 2;
|
||||
|
||||
@SneakyThrows
|
||||
@@ -49,6 +45,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
|
||||
List<ClickImageCheckDefinition> clickImageCheckDefinitionList = new ArrayList<>(interferenceCount);
|
||||
int allImages = interferenceCount + checkClickCount;
|
||||
int avg = bgImage.getWidth() / allImages;
|
||||
for (int i = 0; i < allImages; i++) {
|
||||
// 随机获取点击图片
|
||||
ImgWrapper imgWrapper = randomGetClickImg();
|
||||
@@ -56,12 +53,16 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
int clickImgWidth = image.getWidth();
|
||||
int clickImgHeight = image.getHeight();
|
||||
// 随机x
|
||||
int randomX = ThreadLocalRandom.current().nextInt(10, bgImage.getWidth() - clickImgWidth);
|
||||
int randomX;
|
||||
if (i == 0) {
|
||||
randomX = 1;
|
||||
} else {
|
||||
randomX = avg * i;
|
||||
}
|
||||
// 随机y
|
||||
int randomY = ThreadLocalRandom.current().nextInt(10, bgImage.getHeight() - clickImgHeight);
|
||||
// 通过随机x和y 进行覆盖图片
|
||||
CaptchaImageUtils.overlayImage(bgImage, imgWrapper.getImage(), randomX, randomY);
|
||||
ImageIO.write(imgWrapper.getImage(), "png", new FileOutputStream("C:\\Users\\tianai\\Desktop\\111\\" + i + ".png"));
|
||||
ClickImageCheckDefinition clickImageCheckDefinition = new ClickImageCheckDefinition();
|
||||
clickImageCheckDefinition.setTip(imgWrapper.getTip());
|
||||
clickImageCheckDefinition.setX(randomX + clickImgWidth / 2);
|
||||
@@ -70,14 +71,6 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
clickImageCheckDefinition.setHeight(clickImgHeight);
|
||||
clickImageCheckDefinitionList.add(clickImageCheckDefinition);
|
||||
}
|
||||
// 背景图转换为字符串
|
||||
// String bgImageStr = transform(bgImage, param.getBackgroundFormatName());
|
||||
try {
|
||||
ImageIO.write(bgImage, "jpeg", new FileOutputStream("C:\\Users\\tianai\\Desktop\\123.jpg"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 打乱
|
||||
Collections.shuffle(clickImageCheckDefinitionList);
|
||||
// 拿出参与校验的数据
|
||||
@@ -88,12 +81,6 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
}
|
||||
// 将校验的文字生成提示图片
|
||||
ImgWrapper tipImage = genTipImage(checkClickImageCheckDefinitionList);
|
||||
|
||||
try {
|
||||
ImageIO.write(tipImage.getImage(), "png", new FileOutputStream("C:\\Users\\tianai\\Desktop\\456.png"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return wrapClickImageCaptchaInfo(param, bgImage, tipImage.getImage(), checkClickImageCheckDefinitionList);
|
||||
|
||||
} finally {
|
||||
@@ -110,26 +97,34 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
// return null;
|
||||
}
|
||||
|
||||
protected ImageCaptchaInfo wrapClickImageCaptchaInfo(GenerateParam param, BufferedImage bgImage,
|
||||
BufferedImage tipImage,
|
||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList) {
|
||||
ImageCaptchaInfo clickImageCaptchaInfo = new ImageCaptchaInfo();
|
||||
clickImageCaptchaInfo.setBackgroundImage(transform(bgImage, param.getBackgroundFormatName()));
|
||||
clickImageCaptchaInfo.setSliderImage(transform(bgImage, param.getSliderFormatName()));
|
||||
clickImageCaptchaInfo.setBgImageWidth(bgImage.getWidth());
|
||||
clickImageCaptchaInfo.setBgImageHeight(bgImage.getHeight());
|
||||
clickImageCaptchaInfo.setSliderImageWidth(tipImage.getWidth());
|
||||
clickImageCaptchaInfo.setSliderImageHeight(tipImage.getHeight());
|
||||
clickImageCaptchaInfo.setRandomX(null);
|
||||
clickImageCaptchaInfo.setTolerant(null);
|
||||
clickImageCaptchaInfo.setType(CaptchaTypeConstant.IMAGE_CLICK);
|
||||
clickImageCaptchaInfo.setExpand(checkClickImageCheckDefinitionList);
|
||||
return clickImageCaptchaInfo;
|
||||
}
|
||||
|
||||
protected abstract ImgWrapper genTipImage(List<ClickImageCheckDefinition> imageCheckDefinitions);
|
||||
/**
|
||||
* 随机获取点击的图片
|
||||
*
|
||||
* @return ImgWrapper
|
||||
*/
|
||||
public abstract ImgWrapper randomGetClickImg();
|
||||
|
||||
protected abstract ImgWrapper randomGetClickImg();
|
||||
/**
|
||||
* 生成 tip 图片
|
||||
*
|
||||
* @param imageCheckDefinitions imageCheckDefinitions
|
||||
* @return ImgWrapper
|
||||
*/
|
||||
public abstract ImgWrapper genTipImage(List<ClickImageCheckDefinition> imageCheckDefinitions);
|
||||
|
||||
/**
|
||||
* 包装 ImageCaptchaInfo
|
||||
*
|
||||
* @param param param
|
||||
* @param bgImage bgImage
|
||||
* @param tipImage tipImage
|
||||
* @param checkClickImageCheckDefinitionList checkClickImageCheckDefinitionList
|
||||
* @return ImageCaptchaInfo
|
||||
*/
|
||||
public abstract ImageCaptchaInfo wrapClickImageCaptchaInfo(GenerateParam param, BufferedImage bgImage,
|
||||
BufferedImage tipImage,
|
||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList);
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -140,9 +135,9 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class ImgWrapper {
|
||||
/** 图片.*/
|
||||
/** 图片. */
|
||||
private BufferedImage image;
|
||||
/** 提示.*/
|
||||
/** 提示. */
|
||||
private String tip;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -136,21 +136,21 @@ public class CacheImageCaptchaGenerator implements ImageCaptchaGenerator {
|
||||
captchaInfo = queue.poll();
|
||||
if (captchaInfo == null) {
|
||||
log.warn("滑块验证码缓存不足, genParam:{}", generateParam);
|
||||
}else {
|
||||
} else {
|
||||
AtomicInteger pos = posMap.get(generateParam);
|
||||
if (pos != null) {
|
||||
pos.decrementAndGet();
|
||||
}
|
||||
}
|
||||
}else {
|
||||
} else {
|
||||
queueMap.putIfAbsent(generateParam, new ConcurrentLinkedQueue<>());
|
||||
posMap.putIfAbsent(generateParam, new AtomicInteger(0));
|
||||
}
|
||||
if (captchaInfo == null && requiredGetCaptcha) {
|
||||
// 直接生成 不走缓存
|
||||
captchaInfo = target.generateCaptchaImage(generateParam);
|
||||
captchaInfo = target.generateCaptchaImage(generateParam);
|
||||
}
|
||||
if (captchaInfo != null){
|
||||
if (captchaInfo != null) {
|
||||
// 记录最新时间
|
||||
lastUpdateMap.put(generateParam, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
+6
-2
@@ -1,9 +1,9 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.common.constant.CaptchaTypeConstant;
|
||||
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.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;
|
||||
@@ -24,6 +24,7 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
private boolean initDefaultResource;
|
||||
|
||||
private String defaultCaptcha = CaptchaTypeConstant.SLIDER;
|
||||
|
||||
public MultiImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, boolean initDefaultResource) {
|
||||
this.imageCaptchaResourceManager = imageCaptchaResourceManager;
|
||||
this.initDefaultResource = initDefaultResource;
|
||||
@@ -37,11 +38,14 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
addImageCaptchaGenerator(CaptchaTypeConstant.ROTATE, new StandardRotateImageCaptchaGenerator(imageCaptchaResourceManager, initDefaultResource));
|
||||
// 拼接验证码
|
||||
addImageCaptchaGenerator(CaptchaTypeConstant.CONCAT, new StandardConcatImageCaptchaGenerator(imageCaptchaResourceManager, initDefaultResource));
|
||||
// 点选文字验证码
|
||||
addImageCaptchaGenerator(CaptchaTypeConstant.WORD_IMAGE_CLICK, new StandardRandomWordClickImageCaptchaGenerator(imageCaptchaResourceManager, initDefaultResource));
|
||||
}
|
||||
|
||||
public void addImageCaptchaGenerator(String key, ImageCaptchaGenerator captchaGenerator) {
|
||||
imageCaptchaGeneratorMap.put(key, captchaGenerator);
|
||||
}
|
||||
|
||||
public ImageCaptchaGenerator removeImageCaptchaGenerator(String key) {
|
||||
return imageCaptchaGeneratorMap.remove(key);
|
||||
}
|
||||
@@ -49,7 +53,7 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
@Override
|
||||
public ImageCaptchaInfo generateCaptchaImage(GenerateParam param) {
|
||||
String type = param.getType();
|
||||
if (ObjectUtils.isEmpty(type)){
|
||||
if (ObjectUtils.isEmpty(type)) {
|
||||
param.setType(defaultCaptcha);
|
||||
type = defaultCaptcha;
|
||||
}
|
||||
|
||||
+15
-14
@@ -1,7 +1,7 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.AbstractImageCaptchaGenerator;
|
||||
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;
|
||||
@@ -51,18 +51,19 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
InputStream resourceInputStream = imageCaptchaResourceManager.getResourceInputStream(resourceImage);
|
||||
inputStreams.add(resourceInputStream);
|
||||
BufferedImage bgImage = wrapFile2BufferedImage(resourceInputStream);
|
||||
int spacing = bgImage.getHeight() / 4;
|
||||
BufferedImage[] bgImageSplit = splitImage(ThreadLocalRandom.current().nextInt(spacing, bgImage.getHeight() - spacing), true, bgImage);
|
||||
|
||||
spacing = bgImage.getWidth() / 8;
|
||||
int randomX = ThreadLocalRandom.current().nextInt(spacing, bgImage.getWidth() - spacing);
|
||||
int spacingY = bgImage.getHeight() / 4;
|
||||
int randomY = ThreadLocalRandom.current().nextInt(spacingY, bgImage.getHeight() - spacingY);
|
||||
BufferedImage[] bgImageSplit = splitImage(randomY, true, bgImage);
|
||||
int spacingX = bgImage.getWidth() / 8;
|
||||
int randomX = ThreadLocalRandom.current().nextInt(spacingX, bgImage.getWidth() - bgImage.getWidth() / 5);
|
||||
BufferedImage[] bgImageTopSplit = splitImage(randomX, false, bgImageSplit[0]);
|
||||
|
||||
BufferedImage sliderImage = concatImage(true,
|
||||
bgImageTopSplit[0].getWidth()
|
||||
+ bgImageTopSplit[1].getWidth()
|
||||
+ bgImageSplit[0].getWidth(), bgImageTopSplit[1].getHeight(), bgImageSplit[0], bgImageTopSplit[0]);
|
||||
return wrapConcatCaptchaInfo(randomX, bgImageSplit[1], sliderImage, param);
|
||||
+ bgImageTopSplit[1].getWidth(), bgImageTopSplit[0].getHeight(), bgImageTopSplit[1], bgImageTopSplit[0]);
|
||||
bgImage = concatImage(false, bgImageSplit[1].getWidth(), sliderImage.getHeight() + bgImageSplit[1].getHeight(),
|
||||
sliderImage, bgImageSplit[1]);
|
||||
return wrapConcatCaptchaInfo(randomX, randomY,bgImage, param);
|
||||
} finally {
|
||||
// 使用完后关闭流
|
||||
for (InputStream inputStream : inputStreams) {
|
||||
@@ -76,17 +77,17 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private ImageCaptchaInfo wrapConcatCaptchaInfo(int randomX, BufferedImage bgImage, BufferedImage sliderImage, GenerateParam param) {
|
||||
private ImageCaptchaInfo wrapConcatCaptchaInfo(int randomX, int randomY, BufferedImage bgImage, GenerateParam param) {
|
||||
String backGroundImageBase64 = transform(bgImage, param.getBackgroundFormatName());
|
||||
String sliderImageBase64 = transform(sliderImage, param.getSliderFormatName());
|
||||
ImageCaptchaInfo imageCaptchaInfo = ImageCaptchaInfo.of(backGroundImageBase64,
|
||||
sliderImageBase64,
|
||||
null,
|
||||
bgImage.getWidth(),
|
||||
bgImage.getHeight(),
|
||||
sliderImage.getWidth(),
|
||||
sliderImage.getHeight(),
|
||||
null,
|
||||
null,
|
||||
randomX,
|
||||
CaptchaTypeConstant.CONCAT);
|
||||
imageCaptchaInfo.setData(randomY);
|
||||
imageCaptchaInfo.setTolerant(0.05F);
|
||||
return imageCaptchaInfo;
|
||||
}
|
||||
|
||||
+32
-11
@@ -1,9 +1,11 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.template.slider.common.util.FontUtils;
|
||||
import cloud.tianai.captcha.template.slider.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.common.util.FontUtils;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ClickImageCheckDefinition;
|
||||
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.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.template.slider.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.ResourceStore;
|
||||
import cloud.tianai.captcha.template.slider.resource.common.model.dto.Resource;
|
||||
@@ -30,11 +32,11 @@ import static cloud.tianai.captcha.template.slider.generator.impl.StandardSlider
|
||||
public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickImageCaptchaGenerator {
|
||||
|
||||
protected ImageCaptchaResourceManager imageCaptchaResourceManager;
|
||||
/** 字体包.*/
|
||||
/** 字体包. */
|
||||
protected Font font;
|
||||
protected FontDesignMetrics metrics;
|
||||
protected Integer clickImgWidth = 60;
|
||||
protected Integer clickImgHeight = 60;
|
||||
protected Integer clickImgWidth = 80;
|
||||
protected Integer clickImgHeight = 80;
|
||||
protected int tipImageInterferenceLineNum = 2;
|
||||
protected int tipImageInterferencePointNum = 5;
|
||||
|
||||
@@ -48,11 +50,11 @@ public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickI
|
||||
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, 50);
|
||||
font = font.deriveFont(Font.BOLD, 70);
|
||||
this.metrics = FontDesignMetrics.getMetrics(font);
|
||||
this.font = font;
|
||||
setClickImgHeight(60);
|
||||
setClickImgWidth(60);
|
||||
setClickImgHeight(clickImgWidth);
|
||||
setClickImgWidth(clickImgHeight);
|
||||
}
|
||||
|
||||
public StandardRandomWordClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager,
|
||||
@@ -71,11 +73,11 @@ public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickI
|
||||
public void initDefaultResource() {
|
||||
ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
|
||||
// 添加一些系统的资源文件
|
||||
resourceStore.addResource(CaptchaTypeConstant.IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg")));
|
||||
resourceStore.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg")));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ImgWrapper genTipImage(List<ClickImageCheckDefinition> imageCheckDefinitions) {
|
||||
public ImgWrapper genTipImage(List<ClickImageCheckDefinition> imageCheckDefinitions) {
|
||||
String tips = imageCheckDefinitions.stream().map(ClickImageCheckDefinition::getTip).collect(Collectors.joining());
|
||||
// 生成随机颜色
|
||||
int fontWidth = metrics.stringWidth(tips);
|
||||
@@ -89,7 +91,7 @@ public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickI
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ImgWrapper randomGetClickImg() {
|
||||
public ImgWrapper randomGetClickImg() {
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
// 随机文字
|
||||
String randomWord = FontUtils.getRandomChar(random);
|
||||
@@ -107,6 +109,25 @@ public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickI
|
||||
return new ImgWrapper(fontImage, randomWord);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ImageCaptchaInfo wrapClickImageCaptchaInfo(GenerateParam param, BufferedImage bgImage,
|
||||
BufferedImage tipImage,
|
||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList) {
|
||||
ImageCaptchaInfo clickImageCaptchaInfo = new ImageCaptchaInfo();
|
||||
clickImageCaptchaInfo.setBackgroundImage(transform(bgImage, param.getBackgroundFormatName()));
|
||||
clickImageCaptchaInfo.setSliderImage(transform(tipImage, param.getSliderFormatName()));
|
||||
clickImageCaptchaInfo.setBgImageWidth(bgImage.getWidth());
|
||||
clickImageCaptchaInfo.setBgImageHeight(bgImage.getHeight());
|
||||
clickImageCaptchaInfo.setSliderImageWidth(tipImage.getWidth());
|
||||
clickImageCaptchaInfo.setSliderImageHeight(tipImage.getHeight());
|
||||
clickImageCaptchaInfo.setRandomX(null);
|
||||
clickImageCaptchaInfo.setTolerant(null);
|
||||
clickImageCaptchaInfo.setType(CaptchaTypeConstant.WORD_IMAGE_CLICK);
|
||||
clickImageCaptchaInfo.setExpand(checkClickImageCheckDefinitionList);
|
||||
return clickImageCaptchaInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCaptchaResourceManager getImageResourceManager() {
|
||||
return imageCaptchaResourceManager;
|
||||
|
||||
+1
-33
@@ -1,8 +1,7 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.template.slider.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.constant.SliderCaptchaConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
@@ -13,10 +12,7 @@ import cloud.tianai.captcha.template.slider.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.provider.ClassPathResourceProvider;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
@@ -61,7 +57,6 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
@Override
|
||||
public ImageCaptchaInfo generateCaptchaImage(GenerateParam param) {
|
||||
// 旋转验证码没有混淆
|
||||
Boolean obfuscate = param.getObfuscate();
|
||||
Map<String, Resource> templateImages = imageCaptchaResourceManager.randomGetTemplate(param.getType());
|
||||
if (templateImages == null || templateImages.isEmpty()) {
|
||||
return null;
|
||||
@@ -128,36 +123,9 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
);
|
||||
}
|
||||
|
||||
// @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 ImageCaptchaResourceManager getImageResourceManager() {
|
||||
return imageCaptchaResourceManager;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
BufferedImage bgImage = CaptchaImageUtils.wrapFile2BufferedImage(
|
||||
new FileInputStream("E:\\projects\\tianai-captcha\\src\\main\\resources\\META-INF\\cut-image\\resource\\1.jpg"));
|
||||
BufferedImage image1 = CaptchaImageUtils.wrapFile2BufferedImage(new FileInputStream("C:\\Users\\Thinkpad\\Desktop\\a.png"));
|
||||
BufferedImage image2 = CaptchaImageUtils.wrapFile2BufferedImage(new FileInputStream("C:\\Users\\Thinkpad\\Desktop\\b.png"));
|
||||
|
||||
BufferedImage cutImage = CaptchaImageUtils.cutImage(bgImage, image1, bgImage.getWidth() / 2 - 100, bgImage.getHeight() / 2 - 100);
|
||||
CaptchaImageUtils.overlayImage(cutImage, image2, 0, 0);
|
||||
cutImage = CaptchaImageUtils.rotateImage(cutImage, 180);
|
||||
CaptchaImageUtils.overlayImage(bgImage, image1, bgImage.getWidth() / 2 - 100, bgImage.getHeight() / 2 - 100);
|
||||
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Thinkpad\\Desktop\\a1.jpg");
|
||||
FileOutputStream file2OutputStream = new FileOutputStream("C:\\Users\\Thinkpad\\Desktop\\a2.png");
|
||||
ImageIO.write(bgImage, "jpeg", fileOutputStream);
|
||||
ImageIO.write(cutImage, "png", file2OutputStream);
|
||||
fileOutputStream.close();
|
||||
file2OutputStream.close();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package cloud.tianai.captcha.template.slider.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.constant.SliderCaptchaConstant;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
package cloud.tianai.captcha.template.slider.resource;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.resource.ResourceProvider;
|
||||
import cloud.tianai.captcha.template.slider.resource.common.model.dto.Resource;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@@ -31,7 +31,7 @@ public interface ResourceStore {
|
||||
*
|
||||
* @return List<Resource>
|
||||
*/
|
||||
Map<String,List<Resource>> listAllResources();
|
||||
Map<String, List<Resource>> listAllResources();
|
||||
|
||||
/**
|
||||
* 获取某个type下的所有资源对象
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package cloud.tianai.captcha.template.slider.validator.common.constant;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/4/29 8:33
|
||||
* @Description 滑动轨迹类型
|
||||
*/
|
||||
public interface TrackTypeConstant {
|
||||
|
||||
/** 抬起.*/
|
||||
String UP = "UP";
|
||||
/** 按下.*/
|
||||
String DOWN = "DOWN";
|
||||
/** 移动.*/
|
||||
String MOVE = "MOVE";
|
||||
/** 点击.*/
|
||||
String CLICK = "CLICK";
|
||||
}
|
||||
+6
@@ -1,5 +1,6 @@
|
||||
package cloud.tianai.captcha.template.slider.validator.common.model.dto;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.validator.common.constant.TrackTypeConstant;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -35,8 +36,13 @@ public class SliderCaptchaTrack {
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Track {
|
||||
/** x. */
|
||||
private Integer x;
|
||||
/** y. */
|
||||
private Integer y;
|
||||
/** 时间. */
|
||||
private Integer t;
|
||||
/** 类型. */
|
||||
private String type = TrackTypeConstant.MOVE;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-8
@@ -1,5 +1,6 @@
|
||||
package cloud.tianai.captcha.template.slider.validator.impl;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.common.util.CaptchaUtils;
|
||||
import cloud.tianai.captcha.template.slider.common.util.CollectionUtils;
|
||||
import cloud.tianai.captcha.template.slider.common.util.ObjectUtils;
|
||||
import cloud.tianai.captcha.template.slider.validator.common.model.dto.SliderCaptchaTrack;
|
||||
@@ -22,13 +23,17 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean valid(SliderCaptchaTrack sliderCaptchaTrack, Map<String, Object> sliderCaptchaValidData) {
|
||||
public boolean beforeValid(SliderCaptchaTrack sliderCaptchaTrack, Map<String, Object> sliderCaptchaValidData, Float tolerant, String type) {
|
||||
// 校验参数
|
||||
checkParam(sliderCaptchaTrack);
|
||||
// 基础校验
|
||||
boolean superValid = super.valid(sliderCaptchaTrack, sliderCaptchaValidData);
|
||||
if (!superValid) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterValid(SliderCaptchaTrack sliderCaptchaTrack, Map<String, Object> sliderCaptchaValidData, Float tolerant, String type) {
|
||||
if (!CaptchaUtils.isSliderCaptcha(type)){
|
||||
// 不是滑动验证码的话暂时跳过,点选验证码行为轨迹还没做
|
||||
return true;
|
||||
}
|
||||
// 进行行为轨迹检测
|
||||
long startSlidingTime = sliderCaptchaTrack.getStartSlidingTime().getTime();
|
||||
@@ -93,7 +98,6 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator {
|
||||
return endAvgPosTime > startAvgPosTime;
|
||||
}
|
||||
|
||||
|
||||
public void checkParam(SliderCaptchaTrack sliderCaptchaTrack) {
|
||||
if (ObjectUtils.isEmpty(sliderCaptchaTrack.getBgImageWidth())) {
|
||||
throw new IllegalArgumentException("bgImageWidth must not be null");
|
||||
@@ -120,8 +124,9 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator {
|
||||
Integer x = track.getX();
|
||||
Integer y = track.getY();
|
||||
Integer t = track.getT();
|
||||
if (x == null || y == null || t == null) {
|
||||
throw new IllegalArgumentException("track[x,y,t] must not be null");
|
||||
String type = track.getType();
|
||||
if (x == null || y == null || t == null || ObjectUtils.isEmpty(type)) {
|
||||
throw new IllegalArgumentException("track[x,y,t,type] must not be null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+86
-28
@@ -7,6 +7,7 @@ import cloud.tianai.captcha.template.slider.common.util.ObjectUtils;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ClickImageCheckDefinition;
|
||||
import cloud.tianai.captcha.template.slider.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.template.slider.validator.ImageCaptchaValidator;
|
||||
import cloud.tianai.captcha.template.slider.validator.common.constant.TrackTypeConstant;
|
||||
import cloud.tianai.captcha.template.slider.validator.common.model.dto.SliderCaptchaTrack;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -15,6 +16,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -25,15 +27,15 @@ import java.util.Map;
|
||||
public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
|
||||
public static float DEFAULT_TOLERANT = 0.02f;
|
||||
public static final String PERCENTAGE_KEY = "percentage";
|
||||
public static final String TOLERANT_KEY = "tolerant";
|
||||
public static final String TYPE_KEY = "type";
|
||||
|
||||
/** 容错值. */
|
||||
@Getter
|
||||
@Setter
|
||||
public float defaultTolerant = DEFAULT_TOLERANT;
|
||||
|
||||
public static final String PERCENTAGE_KEY = "percentage";
|
||||
public static final String TOLERANT_KEY = "Tolerant";
|
||||
public static final String TYPE_KEY = "type";
|
||||
|
||||
public SimpleImageCaptchaValidator() {
|
||||
}
|
||||
|
||||
@@ -66,6 +68,14 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
@Override
|
||||
public Map<String, Object> generateImageCaptchaValidData(ImageCaptchaInfo imageCaptchaInfo) {
|
||||
Map<String, Object> map = new HashMap<>(8);
|
||||
if(beforeGenerateImageCaptchaValidData(imageCaptchaInfo, map)) {
|
||||
doGenerateImageCaptchaValidData(map, imageCaptchaInfo);
|
||||
}
|
||||
afterGenerateImageCaptchaValidData(imageCaptchaInfo, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
public boolean beforeGenerateImageCaptchaValidData(ImageCaptchaInfo imageCaptchaInfo, Map<String, Object> map) {
|
||||
// 容错值
|
||||
Float tolerant = imageCaptchaInfo.getTolerant();
|
||||
if (tolerant != null && tolerant > 0) {
|
||||
@@ -77,13 +87,17 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
type = CaptchaTypeConstant.SLIDER;
|
||||
}
|
||||
map.put(TYPE_KEY, type);
|
||||
|
||||
return afterGenerateImageCaptchaValidData(map, imageCaptchaInfo, type);
|
||||
return true;
|
||||
}
|
||||
|
||||
public Map<String, Object> afterGenerateImageCaptchaValidData(Map<String, Object> map,
|
||||
ImageCaptchaInfo imageCaptchaInfo,
|
||||
String type) {
|
||||
public void afterGenerateImageCaptchaValidData(ImageCaptchaInfo imageCaptchaInfo, Map<String, Object> map) {
|
||||
|
||||
}
|
||||
|
||||
public void doGenerateImageCaptchaValidData(Map<String, Object> map,
|
||||
ImageCaptchaInfo imageCaptchaInfo) {
|
||||
// type
|
||||
String type = (String) map.getOrDefault(TYPE_KEY, CaptchaTypeConstant.SLIDER);
|
||||
if (CaptchaUtils.isSliderCaptcha(type)) {
|
||||
// 滑动验证码
|
||||
addPercentage(imageCaptchaInfo, map);
|
||||
@@ -93,7 +107,7 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
if (expand == null) {
|
||||
throw new IllegalArgumentException("点选验证码扩展数据转换为 List<ClickImageCheckDefinition> 失败, info=" + imageCaptchaInfo);
|
||||
}
|
||||
List<ClickImageCheckDefinition> clickImageCheckDefinitionList = null;
|
||||
List<ClickImageCheckDefinition> clickImageCheckDefinitionList;
|
||||
try {
|
||||
clickImageCheckDefinitionList = (List<ClickImageCheckDefinition>) expand;
|
||||
} catch (Exception e) {
|
||||
@@ -116,17 +130,15 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
map.put(TOLERANT_KEY, tolerant);
|
||||
}
|
||||
}
|
||||
// 添加点选验证
|
||||
// 添加点选验证数据
|
||||
map.put(PERCENTAGE_KEY, sb.toString());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean valid(SliderCaptchaTrack sliderCaptchaTrack, Map<String, Object> sliderCaptchaValidData) {
|
||||
|
||||
// 读容错值
|
||||
Float tolerantData = getFloatParam(TOLERANT_KEY, sliderCaptchaValidData, defaultTolerant);
|
||||
Float tolerant = getFloatParam(TOLERANT_KEY, sliderCaptchaValidData, defaultTolerant);
|
||||
// 读验证码类型
|
||||
String type = getStringParam(TYPE_KEY, sliderCaptchaValidData, CaptchaTypeConstant.SLIDER);
|
||||
Integer bgImageWidth = sliderCaptchaTrack.getBgImageWidth();
|
||||
@@ -139,13 +151,49 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
// 没有滑动轨迹
|
||||
return false;
|
||||
}
|
||||
return afterValid(sliderCaptchaTrack, sliderCaptchaValidData, tolerantData, type);
|
||||
// 验证前
|
||||
if (!beforeValid(sliderCaptchaTrack, sliderCaptchaValidData, tolerant, type)) {
|
||||
return false;
|
||||
}
|
||||
// 验证
|
||||
boolean valid = doValid(sliderCaptchaTrack, sliderCaptchaValidData, tolerant, type);
|
||||
if (valid) {
|
||||
// 验证后
|
||||
valid = afterValid(sliderCaptchaTrack, sliderCaptchaValidData, tolerant, type);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
public boolean afterValid(SliderCaptchaTrack sliderCaptchaTrack,
|
||||
Map<String, Object> sliderCaptchaValidData,
|
||||
Float tolerant,
|
||||
String type) {
|
||||
/**
|
||||
* 验证前
|
||||
*
|
||||
* @param sliderCaptchaTrack sliderCaptchaTrack
|
||||
* @param sliderCaptchaValidData sliderCaptchaValidData
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean beforeValid(SliderCaptchaTrack sliderCaptchaTrack, Map<String, Object> sliderCaptchaValidData, Float tolerant, String type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证后
|
||||
*
|
||||
* @param sliderCaptchaTrack sliderCaptchaTrack
|
||||
* @param sliderCaptchaValidData sliderCaptchaValidData
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean afterValid(SliderCaptchaTrack sliderCaptchaTrack, Map<String, Object> sliderCaptchaValidData, Float tolerant, String type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean doValid(SliderCaptchaTrack sliderCaptchaTrack,
|
||||
Map<String, Object> sliderCaptchaValidData,
|
||||
Float tolerant,
|
||||
String type) {
|
||||
if (CaptchaUtils.isSliderCaptcha(type)) {
|
||||
// 滑动类型验证码
|
||||
return doValidSliderCaptcha(sliderCaptchaTrack, sliderCaptchaValidData, tolerant, type);
|
||||
@@ -160,10 +208,11 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
|
||||
/**
|
||||
* 校验点选验证码
|
||||
* @param sliderCaptchaTrack sliderCaptchaTrack
|
||||
*
|
||||
* @param sliderCaptchaTrack sliderCaptchaTrack
|
||||
* @param sliderCaptchaValidData sliderCaptchaValidData
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean doValidClickCaptcha(SliderCaptchaTrack sliderCaptchaTrack,
|
||||
@@ -176,18 +225,26 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
}
|
||||
String[] splitArr = validStr.split(";");
|
||||
List<SliderCaptchaTrack.Track> trackList = sliderCaptchaTrack.getTrackList();
|
||||
if (trackList.size() != splitArr.length) {
|
||||
if (trackList.size() < splitArr.length) {
|
||||
return false;
|
||||
}
|
||||
// 取出点击事件的轨迹数据
|
||||
List<SliderCaptchaTrack.Track> clickTrackList = trackList
|
||||
.stream()
|
||||
.filter(t -> TrackTypeConstant.CLICK.equalsIgnoreCase(t.getType()))
|
||||
.collect(Collectors.toList());
|
||||
if (clickTrackList.size() != splitArr.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < splitArr.length; i++) {
|
||||
SliderCaptchaTrack.Track track = trackList.get(i);
|
||||
SliderCaptchaTrack.Track track = clickTrackList.get(i);
|
||||
String posStr = splitArr[i];
|
||||
String[] posArr = posStr.split(",");
|
||||
float xPercentage = Float.parseFloat(posArr[0]);
|
||||
float yPercentage = Float.parseFloat(posArr[1]);
|
||||
|
||||
float calcXPercentage = calcPercentage(track.getX(), sliderCaptchaTrack.getBgImageWidth());
|
||||
float calcYPercentage = calcPercentage(track.getY(), sliderCaptchaTrack.getBgImageWidth());
|
||||
float calcYPercentage = calcPercentage(track.getY(), sliderCaptchaTrack.getBgImageHeight());
|
||||
|
||||
if (!checkPercentage(calcXPercentage, xPercentage, tolerant)
|
||||
|| !checkPercentage(calcYPercentage, yPercentage, tolerant)) {
|
||||
@@ -199,10 +256,11 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator {
|
||||
|
||||
/**
|
||||
* 校验滑动验证码
|
||||
* @param sliderCaptchaTrack sliderCaptchaTrack
|
||||
*
|
||||
* @param sliderCaptchaTrack sliderCaptchaTrack
|
||||
* @param sliderCaptchaValidData sliderCaptchaValidData
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean doValidSliderCaptcha(SliderCaptchaTrack sliderCaptchaTrack,
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package example;
|
||||
|
||||
import cloud.tianai.captcha.template.slider.common.constant.CaptchaTypeConstant;
|
||||
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.CacheImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.template.slider.generator.impl.StandardConcatImageCaptchaGenerator;
|
||||
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.impl.DefaultImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.template.slider.resource.impl.DefaultResourceStore;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class StandardConcatCaptchaGeneratorTest {
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
ResourceStore resourceStore = new DefaultResourceStore();
|
||||
// Map<String, Resource> template = new HashMap<>();
|
||||
// template.put(SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME, new Resource("file", "C:\\Users\\Thinkpad\\Desktop\\a.png"));
|
||||
// template.put(SliderCaptchaConstant.TEMPLATE_ACTIVE_IMAGE_NAME, new Resource("file", "C:\\Users\\Thinkpad\\Desktop\\b.png"));
|
||||
|
||||
// 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"));
|
||||
|
||||
ImageCaptchaResourceManager imageCaptchaResourceManager = new DefaultImageCaptchaResourceManager(resourceStore);
|
||||
|
||||
StandardConcatImageCaptchaGenerator captchaGenerator = new StandardConcatImageCaptchaGenerator(imageCaptchaResourceManager, true);
|
||||
ImageCaptchaInfo imageCaptchaInfo = captchaGenerator.generateCaptchaImage(CaptchaTypeConstant.CONCAT);
|
||||
System.out.println("backgroundImage:" + imageCaptchaInfo.getBackgroundImage());
|
||||
System.out.println("sliderImage:" + imageCaptchaInfo.getSliderImage());
|
||||
|
||||
TimeUnit.DAYS.sleep(1);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class StandardWordClickImageCaptchaGeneratorTest {
|
||||
new StandardRandomWordClickImageCaptchaGenerator(imageCaptchaResourceManager, true);
|
||||
|
||||
GenerateParam generateParam = new GenerateParam();
|
||||
generateParam.setType(CaptchaTypeConstant.IMAGE_CLICK);
|
||||
generateParam.setType(CaptchaTypeConstant.WORD_IMAGE_CLICK);
|
||||
generateParam.setSliderFormatName("png");
|
||||
ImageCaptchaInfo imageCaptchaInfo = defaultImageCaptchaResourceManager.generateCaptchaImage(generateParam);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user