From bf5b8987f2f0f008df4c98da575a30ad61c0de77 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, 27 May 2022 11:48:40 +0800 Subject: [PATCH] =?UTF-8?q?U=20=E4=BC=98=E5=8C=96=E7=82=B9=E9=80=89?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E7=A0=81=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=B0=86?= =?UTF-8?q?=E6=9D=A5=E6=94=AF=E6=8C=81=E8=AF=AD=E5=BA=8F=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E7=A0=81=E7=AD=89=E7=9B=B8=E5=85=B3=E5=85=B7=E6=9C=89=E8=81=94?= =?UTF-8?q?=E6=83=B3=E7=9A=84=E7=82=B9=E5=87=BB=E7=B1=BB=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbstractClickImageCaptchaGenerator.java | 57 ++++++++++++------- ...dRandomWordClickImageCaptchaGenerator.java | 30 ++++++---- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/AbstractClickImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/AbstractClickImageCaptchaGenerator.java index 7d847d9..79f34c8 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/AbstractClickImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/AbstractClickImageCaptchaGenerator.java @@ -31,7 +31,6 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa @Setter protected Integer interferenceCount = 2; - public AbstractClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) { super(imageCaptchaResourceManager); } @@ -53,9 +52,13 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa List clickImageCheckDefinitionList = new ArrayList<>(interferenceCount); int allImages = interferenceCount + checkClickCount; int avg = bgImage.getWidth() / allImages; + List imgTips = randomGetClickImgTips(allImages); + if (allImages < imgTips.size()) { + throw new IllegalStateException("随机生成点击图片小于请求数量, 请求生成数量=" + allImages + ",实际生成数量=" + imgTips.size()); + } for (int i = 0; i < allImages; i++) { // 随机获取点击图片 - ImgWrapper imgWrapper = randomGetClickImg(); + ImgWrapper imgWrapper = getClickImg(imgTips.get(i)); BufferedImage image = imgWrapper.getImage(); int clickImgWidth = image.getWidth(); int clickImgHeight = image.getHeight(); @@ -78,17 +81,10 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa clickImageCheckDefinition.setHeight(clickImgHeight); clickImageCheckDefinitionList.add(clickImageCheckDefinition); } - // 打乱 - Collections.shuffle(clickImageCheckDefinitionList); - // 拿出参与校验的数据 - List checkClickImageCheckDefinitionList = new ArrayList<>(checkClickCount); - for (int i = 0; i < checkClickCount; i++) { - ClickImageCheckDefinition clickImageCheckDefinition = clickImageCheckDefinitionList.get(i); - checkClickImageCheckDefinitionList.add(clickImageCheckDefinition); - } - // 将校验的文字生成提示图片 - ImgWrapper tipImage = genTipImage(checkClickImageCheckDefinitionList); - return wrapClickImageCaptchaInfo(param, bgImage, tipImage.getImage(), checkClickImageCheckDefinitionList); + List checkClickImageCheckDefinitionList = getCheckClickImageCheckDefinitionList(clickImageCheckDefinitionList, + checkClickCount); + // wrap + return wrapClickImageCaptchaInfo(param, bgImage, checkClickImageCheckDefinitionList); } finally { // 使用完后关闭流 @@ -103,31 +99,50 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa } /** - * 随机获取点击的图片 + * 从总的图片中 去除要校验的图片数据 以及顺序 * - * @return ImgWrapper + * @param allCheckDefinitionList 总的点选图片 + * @param checkClickCount 参与校验的数据 + * @return List */ - public abstract ImgWrapper randomGetClickImg(); + protected List getCheckClickImageCheckDefinitionList(List allCheckDefinitionList, + Integer checkClickCount) { + // 打乱 + Collections.shuffle(allCheckDefinitionList); + // 拿出参与校验的数据 + List checkClickImageCheckDefinitionList = new ArrayList<>(checkClickCount); + for (int i = 0; i < checkClickCount; i++) { + ClickImageCheckDefinition clickImageCheckDefinition = allCheckDefinitionList.get(i); + checkClickImageCheckDefinitionList.add(clickImageCheckDefinition); + } + return checkClickImageCheckDefinitionList; + } /** - * 生成 tip 图片 + * 随机获取一组数据用于生成随机图 * - * @param imageCheckDefinitions imageCheckDefinitions + * @param tipSize tipSize + * @return List + */ + protected abstract List randomGetClickImgTips(int tipSize); + + /** + * 随机获取点击的图片 + * + * @param tip 提示数据,根据改数据生成图片 * @return ImgWrapper */ - public abstract ImgWrapper genTipImage(List imageCheckDefinitions); + public abstract ImgWrapper getClickImg(String tip); /** * 包装 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); /** diff --git a/src/main/java/cloud/tianai/captcha/generator/impl/StandardRandomWordClickImageCaptchaGenerator.java b/src/main/java/cloud/tianai/captcha/generator/impl/StandardRandomWordClickImageCaptchaGenerator.java index dce7e07..5334d4e 100644 --- a/src/main/java/cloud/tianai/captcha/generator/impl/StandardRandomWordClickImageCaptchaGenerator.java +++ b/src/main/java/cloud/tianai/captcha/generator/impl/StandardRandomWordClickImageCaptchaGenerator.java @@ -18,6 +18,7 @@ import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @@ -47,8 +48,8 @@ public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickI protected int tipImageInterferencePointNum = 5; /** - * 因为在画文字图形的时候 y 值不能准确通过 除法计算得出, 字体大小不一致中间的容错值不可估计, - * 所以通过 线性回归模型 计算出 intercept和coef 用于计算 容错值 + * 因为在画文字图形的时候 y 值不能准确通过 除法计算得出, 字体大小不一致中间的容错值算不准确 + * 方案: 通过 线性回归模型 计算出 intercept和coef 用于计算 容错值 * 训练数据为 宋体 字体大小为 30~150 随机选择7组数据进行训练, 训练后r2结果为 0.9967106324620846 */ protected float intercept = 0.39583333f; @@ -63,6 +64,18 @@ public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickI } + @Override + protected List randomGetClickImgTips(int tipSize) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + List tipList = new ArrayList<>(tipSize); + for (int i = 0; i < tipSize; i++) { + String randomWord = FontUtils.getRandomChar(random); + tipList.add(randomWord); + } + // 随机文字 + return tipList; + } + @Override @SneakyThrows({IOException.class, FontFormatException.class}) protected void doInit(boolean initDefaultResource) { @@ -85,14 +98,12 @@ public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickI this.font = font; } - public void initDefaultResource() { ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore(); // 添加一些系统的资源文件 resourceStore.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"))); } - @Override public ImgWrapper genTipImage(List imageCheckDefinitions) { String tips = imageCheckDefinitions.stream().map(ClickImageCheckDefinition::getTip).collect(Collectors.joining()); // 生成随机颜色 @@ -107,29 +118,28 @@ public class StandardRandomWordClickImageCaptchaGenerator extends AbstractClickI } @Override - public ImgWrapper randomGetClickImg() { + public ImgWrapper getClickImg(String tip) { ThreadLocalRandom random = ThreadLocalRandom.current(); - // 随机文字 - String randomWord = FontUtils.getRandomChar(random); // 随机颜色 Color randomColor = CaptchaImageUtils.getRandomColor(random); // 随机角度 int randomDeg = ThreadLocalRandom.current().nextInt(0, 85); BufferedImage fontImage = CaptchaImageUtils.drawWordImg(randomColor, - randomWord, + tip, font, currentFontTopCoef, clickImgWidth, clickImgHeight, randomDeg); - return new ImgWrapper(fontImage, randomWord); + return new ImgWrapper(fontImage, tip); } @Override public ImageCaptchaInfo wrapClickImageCaptchaInfo(GenerateParam param, BufferedImage bgImage, - BufferedImage tipImage, List checkClickImageCheckDefinitionList) { + // 提示图片 + BufferedImage tipImage = genTipImage(checkClickImageCheckDefinitionList).getImage(); ImageCaptchaInfo clickImageCaptchaInfo = new ImageCaptchaInfo(); clickImageCaptchaInfo.setBackgroundImage(transform(bgImage, param.getBackgroundFormatName())); clickImageCaptchaInfo.setSliderImage(transform(tipImage, param.getSliderFormatName()));