From a4e0def76bbd0476d94bfd8c8ba35f6b697e698b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A9=E7=88=B1=E6=9C=89=E6=83=85?= Date: Fri, 29 Apr 2022 18:07:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/constant/CaptchaTypeConstant.java | 2 + .../slider/common/util/CaptchaUtils.java | 4 +- .../generator/ImageCaptchaGenerator.java | 4 +- .../common/model/dto/ImageCaptchaInfo.java | 4 +- .../common/util/CaptchaImageUtils.java | 18 +-- .../AbstractClickImageCaptchaGenerator.java | 91 +++++++------- .../impl/CacheImageCaptchaGenerator.java | 8 +- .../impl/MultiImageCaptchaGenerator.java | 8 +- .../StandardConcatImageCaptchaGenerator.java | 29 ++--- ...dRandomWordClickImageCaptchaGenerator.java | 43 +++++-- .../StandardRotateImageCaptchaGenerator.java | 34 +----- .../StandardSliderImageCaptchaGenerator.java | 2 +- .../resource/AbstractResourceProvider.java | 1 - .../slider/resource/ResourceStore.java | 2 +- .../common/constant/TrackTypeConstant.java | 18 +++ .../common/model/dto/SliderCaptchaTrack.java | 6 + .../impl/BasicCaptchaTrackValidator.java | 21 ++-- .../impl/SimpleImageCaptchaValidator.java | 114 +++++++++++++----- .../StandardConcatCaptchaGeneratorTest.java | 37 ++++++ ...ardWordClickImageCaptchaGeneratorTest.java | 2 +- 20 files changed, 285 insertions(+), 163 deletions(-) create mode 100644 src/main/java/cloud/tianai/captcha/template/slider/validator/common/constant/TrackTypeConstant.java create mode 100644 src/main/test/java/example/StandardConcatCaptchaGeneratorTest.java diff --git a/src/main/java/cloud/tianai/captcha/template/slider/common/constant/CaptchaTypeConstant.java b/src/main/java/cloud/tianai/captcha/template/slider/common/constant/CaptchaTypeConstant.java index 1a940b8..1e585d0 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/common/constant/CaptchaTypeConstant.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/common/constant/CaptchaTypeConstant.java @@ -15,4 +15,6 @@ public interface CaptchaTypeConstant { String CONCAT = "CONCAT"; /** 图片点选.*/ String IMAGE_CLICK = "IMAGE_CLICK"; + /** 文字图片点选.*/ + String WORD_IMAGE_CLICK = "WORD_IMAGE_CLICK"; } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/common/util/CaptchaUtils.java b/src/main/java/cloud/tianai/captcha/template/slider/common/util/CaptchaUtils.java index 92c54cc..d44bad2 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/common/util/CaptchaUtils.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/common/util/CaptchaUtils.java @@ -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); } } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/ImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/ImageCaptchaGenerator.java index 0d73e77..b8ee7ea 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/ImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/ImageCaptchaGenerator.java @@ -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 diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/common/model/dto/ImageCaptchaInfo.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/common/model/dto/ImageCaptchaInfo.java index 1695a9c..80284a9 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/common/model/dto/ImageCaptchaInfo.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/common/model/dto/ImageCaptchaInfo.java @@ -34,8 +34,10 @@ public class ImageCaptchaInfo { private Integer randomX; /** 容错值, 可以为空 默认 0.02容错,校验的时候用. */ private Float tolerant; - /** 验证码类型.*/ + /** 验证码类型. */ private String type; + /** 透传字段,用于传给前端.*/ + private Object data; /** * 扩展字段 */ diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/common/util/CaptchaImageUtils.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/common/util/CaptchaImageUtils.java index 0257958..30ccdb4 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/common/util/CaptchaImageUtils.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/common/util/CaptchaImageUtils.java @@ -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) { diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/AbstractClickImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/AbstractClickImageCaptchaGenerator.java index 99b606d..2a3c1f7 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/AbstractClickImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/AbstractClickImageCaptchaGenerator.java @@ -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 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 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 imageCheckDefinitions); + /** + * 随机获取点击的图片 + * + * @return ImgWrapper + */ + public abstract ImgWrapper randomGetClickImg(); - protected abstract ImgWrapper randomGetClickImg(); + /** + * 生成 tip 图片 + * + * @param imageCheckDefinitions imageCheckDefinitions + * @return ImgWrapper + */ + public abstract ImgWrapper genTipImage(List 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 checkClickImageCheckDefinitionList); /** * @Author: 天爱有情 @@ -140,9 +135,9 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa @NoArgsConstructor @AllArgsConstructor public static class ImgWrapper { - /** 图片.*/ + /** 图片. */ private BufferedImage image; - /** 提示.*/ + /** 提示. */ private String tip; } } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/CacheImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/CacheImageCaptchaGenerator.java index 0f33eef..804d398 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/CacheImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/CacheImageCaptchaGenerator.java @@ -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()); } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/MultiImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/MultiImageCaptchaGenerator.java index ea19eea..183f6a6 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/MultiImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/MultiImageCaptchaGenerator.java @@ -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; } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardConcatImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardConcatImageCaptchaGenerator.java index 01e2d62..a263dde 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardConcatImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardConcatImageCaptchaGenerator.java @@ -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; } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardRandomWordClickImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardRandomWordClickImageCaptchaGenerator.java index c78a1f7..c7ca520 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardRandomWordClickImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardRandomWordClickImageCaptchaGenerator.java @@ -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 imageCheckDefinitions) { + public ImgWrapper genTipImage(List 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 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; diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardRotateImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardRotateImageCaptchaGenerator.java index ac929ce..afb5eaa 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardRotateImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardRotateImageCaptchaGenerator.java @@ -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 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(); - } } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardSliderImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardSliderImageCaptchaGenerator.java index bf31f77..613dcdc 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardSliderImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/generator/impl/StandardSliderImageCaptchaGenerator.java @@ -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; diff --git a/src/main/java/cloud/tianai/captcha/template/slider/resource/AbstractResourceProvider.java b/src/main/java/cloud/tianai/captcha/template/slider/resource/AbstractResourceProvider.java index 2ccd2e6..bf37b07 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/resource/AbstractResourceProvider.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/resource/AbstractResourceProvider.java @@ -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; diff --git a/src/main/java/cloud/tianai/captcha/template/slider/resource/ResourceStore.java b/src/main/java/cloud/tianai/captcha/template/slider/resource/ResourceStore.java index 2f03b3e..32faf15 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/resource/ResourceStore.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/resource/ResourceStore.java @@ -31,7 +31,7 @@ public interface ResourceStore { * * @return List */ - Map> listAllResources(); + Map> listAllResources(); /** * 获取某个type下的所有资源对象 diff --git a/src/main/java/cloud/tianai/captcha/template/slider/validator/common/constant/TrackTypeConstant.java b/src/main/java/cloud/tianai/captcha/template/slider/validator/common/constant/TrackTypeConstant.java new file mode 100644 index 0000000..766ca17 --- /dev/null +++ b/src/main/java/cloud/tianai/captcha/template/slider/validator/common/constant/TrackTypeConstant.java @@ -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"; +} diff --git a/src/main/java/cloud/tianai/captcha/template/slider/validator/common/model/dto/SliderCaptchaTrack.java b/src/main/java/cloud/tianai/captcha/template/slider/validator/common/model/dto/SliderCaptchaTrack.java index 8f3e908..deab1e2 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/validator/common/model/dto/SliderCaptchaTrack.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/validator/common/model/dto/SliderCaptchaTrack.java @@ -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; } } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/validator/impl/BasicCaptchaTrackValidator.java b/src/main/java/cloud/tianai/captcha/template/slider/validator/impl/BasicCaptchaTrackValidator.java index 426e352..95ab22e 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/validator/impl/BasicCaptchaTrackValidator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/validator/impl/BasicCaptchaTrackValidator.java @@ -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 sliderCaptchaValidData) { + public boolean beforeValid(SliderCaptchaTrack sliderCaptchaTrack, Map 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 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"); } } } diff --git a/src/main/java/cloud/tianai/captcha/template/slider/validator/impl/SimpleImageCaptchaValidator.java b/src/main/java/cloud/tianai/captcha/template/slider/validator/impl/SimpleImageCaptchaValidator.java index 3643f6a..81e95d3 100644 --- a/src/main/java/cloud/tianai/captcha/template/slider/validator/impl/SimpleImageCaptchaValidator.java +++ b/src/main/java/cloud/tianai/captcha/template/slider/validator/impl/SimpleImageCaptchaValidator.java @@ -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 generateImageCaptchaValidData(ImageCaptchaInfo imageCaptchaInfo) { Map map = new HashMap<>(8); + if(beforeGenerateImageCaptchaValidData(imageCaptchaInfo, map)) { + doGenerateImageCaptchaValidData(map, imageCaptchaInfo); + } + afterGenerateImageCaptchaValidData(imageCaptchaInfo, map); + return map; + } + + public boolean beforeGenerateImageCaptchaValidData(ImageCaptchaInfo imageCaptchaInfo, Map 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 afterGenerateImageCaptchaValidData(Map map, - ImageCaptchaInfo imageCaptchaInfo, - String type) { + public void afterGenerateImageCaptchaValidData(ImageCaptchaInfo imageCaptchaInfo, Map map) { + + } + + public void doGenerateImageCaptchaValidData(Map 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 失败, info=" + imageCaptchaInfo); } - List clickImageCheckDefinitionList = null; + List clickImageCheckDefinitionList; try { clickImageCheckDefinitionList = (List) 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 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 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 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 sliderCaptchaValidData, Float tolerant, String type) { + return true; + } + + public boolean doValid(SliderCaptchaTrack sliderCaptchaTrack, + Map 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 trackList = sliderCaptchaTrack.getTrackList(); - if (trackList.size() != splitArr.length) { + if (trackList.size() < splitArr.length) { + return false; + } + // 取出点击事件的轨迹数据 + List 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, diff --git a/src/main/test/java/example/StandardConcatCaptchaGeneratorTest.java b/src/main/test/java/example/StandardConcatCaptchaGeneratorTest.java new file mode 100644 index 0000000..53cac4c --- /dev/null +++ b/src/main/test/java/example/StandardConcatCaptchaGeneratorTest.java @@ -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 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); + + } +} diff --git a/src/main/test/java/example/StandardWordClickImageCaptchaGeneratorTest.java b/src/main/test/java/example/StandardWordClickImageCaptchaGeneratorTest.java index 9744bda..3ee2b90 100644 --- a/src/main/test/java/example/StandardWordClickImageCaptchaGeneratorTest.java +++ b/src/main/test/java/example/StandardWordClickImageCaptchaGeneratorTest.java @@ -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);