mirror of
https://github.com/dromara/tianai-captcha.git
synced 2026-05-07 06:04:34 +08:00
修复以及优化很多
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>cloud.tianai.captcha</groupId>
|
||||
<artifactId>tianai-captcha</artifactId>
|
||||
<version>1.4.2</version>
|
||||
<version>1.5.0</version>
|
||||
|
||||
<name>tianai-captcha</name>
|
||||
<description>行为验证码</description>
|
||||
|
||||
@@ -11,19 +11,8 @@ public interface CaptchaTypeConstant {
|
||||
String SLIDER = "SLIDER";
|
||||
/** 旋转. */
|
||||
String ROTATE = "ROTATE";
|
||||
/** 旋转角度.*/
|
||||
String ROTATE_DEGREE = "ROTATE_DEGREE";
|
||||
/** 拼接.*/
|
||||
/** 拼接. */
|
||||
String CONCAT = "CONCAT";
|
||||
/** 拼图.*/
|
||||
String JIGSAW = "JIGSAW";
|
||||
/** 图片点选.*/
|
||||
String IMAGE_CLICK = "IMAGE_CLICK";
|
||||
/** 文字图片点选.*/
|
||||
/** 文字图片点选. */
|
||||
String WORD_IMAGE_CLICK = "WORD_IMAGE_CLICK";
|
||||
/** 语序点选.*/
|
||||
String WORD_ORDER_IMAGE_CLICK = "WORD_ORDER_IMAGE_CLICK";
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,20 @@ package cloud.tianai.captcha.common.constant;
|
||||
public interface CommonConstant {
|
||||
|
||||
String DEFAULT_TAG = "default";
|
||||
/** 图标点选资源存储类型.*/
|
||||
/** 图标点选资源存储类型. */
|
||||
String IMAGE_CLICK_ICON = "ICON";
|
||||
/** 蜂窝点选.*/
|
||||
String HONEYCOMB_CLICK_ICON = "HONEYCOMB_ICON";
|
||||
/** 刮刮卡图标. */
|
||||
String SCRAPE_ICON = "SCRAPE_ICON";
|
||||
|
||||
|
||||
/**
|
||||
* 默认的resource资源文件路径.
|
||||
*/
|
||||
String DEFAULT_SLIDER_IMAGE_RESOURCE_PATH = "META-INF/cut-image/resource";
|
||||
/**
|
||||
* 默认的template资源文件路径.
|
||||
*/
|
||||
String DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH = "META-INF/cut-image/template";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package cloud.tianai.captcha.common.util;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2023/11/2 9:22
|
||||
* @Description 验证码类型分类
|
||||
*/
|
||||
public class CaptchaTypeClassifier {
|
||||
|
||||
private static final Set<String> SLIDER_CAPTCHA_TYPES = new HashSet<>();
|
||||
private static final Set<String> CLICK_CAPTCHA_TYPES = new HashSet<>();
|
||||
private static final Set<String> JIGSAW_CAPTCHA_TYPES = new HashSet<>();
|
||||
|
||||
public static void addSliderCaptchaType(String type) {
|
||||
SLIDER_CAPTCHA_TYPES.add(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static void addClickCaptchaType(String type) {
|
||||
CLICK_CAPTCHA_TYPES.add(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static boolean isSliderCaptcha(String type) {
|
||||
return SLIDER_CAPTCHA_TYPES.contains(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static boolean isClickCaptcha(String type) {
|
||||
return CLICK_CAPTCHA_TYPES.contains(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static Set<String> getSliderCaptchaTypes() {
|
||||
return SLIDER_CAPTCHA_TYPES;
|
||||
}
|
||||
|
||||
public static Set<String> getClickCaptchaTypes() {
|
||||
return CLICK_CAPTCHA_TYPES;
|
||||
}
|
||||
|
||||
public static void removeSliderCaptchaType(String type) {
|
||||
SLIDER_CAPTCHA_TYPES.remove(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static void removeClickCaptchaType(String type) {
|
||||
CLICK_CAPTCHA_TYPES.remove(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static boolean isJigsawCaptcha(String type) {
|
||||
return JIGSAW_CAPTCHA_TYPES.contains(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static void addJigsawCaptchaType(String type) {
|
||||
JIGSAW_CAPTCHA_TYPES.add(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static void removeJigsawCaptchaType(String type) {
|
||||
JIGSAW_CAPTCHA_TYPES.remove(type.toUpperCase());
|
||||
}
|
||||
|
||||
public static Set<String> getJigsawCaptchaTypes() {
|
||||
return JIGSAW_CAPTCHA_TYPES;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package cloud.tianai.captcha.common.util;
|
||||
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/4/28 17:03
|
||||
* @Description 验证码工具包
|
||||
*/
|
||||
public class CaptchaUtils {
|
||||
|
||||
/**
|
||||
* 是否是滑动验证码
|
||||
*
|
||||
* @param type 类型
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isSliderCaptcha(String type) {
|
||||
return CaptchaTypeConstant.SLIDER.equals(type)
|
||||
|| CaptchaTypeConstant.ROTATE.equals(type)
|
||||
|| CaptchaTypeConstant.CONCAT.equals(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是点击验证码
|
||||
*
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isClickCaptcha(String type) {
|
||||
return CaptchaTypeConstant.WORD_IMAGE_CLICK.equals(type) || CaptchaTypeConstant.IMAGE_CLICK.equals(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是拼图类验证码, 校验的值是 数字排列顺序
|
||||
*
|
||||
* @param type 类型
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isJigsawCaptcha(String type) {
|
||||
return CaptchaTypeConstant.JIGSAW.equals(type);
|
||||
}
|
||||
}
|
||||
@@ -268,7 +268,7 @@ public abstract class CollectionUtils {
|
||||
* @since 5.2.3
|
||||
* @see SortedSet
|
||||
* @see LinkedHashMap#keySet()
|
||||
* @see java.util.LinkedHashSet
|
||||
* @see LinkedHashSet
|
||||
*/
|
||||
public static <T> T firstElement(Set<T> set) {
|
||||
if (isEmpty(set)) {
|
||||
@@ -307,7 +307,7 @@ public abstract class CollectionUtils {
|
||||
* @since 5.0.3
|
||||
* @see SortedSet
|
||||
* @see LinkedHashMap#keySet()
|
||||
* @see java.util.LinkedHashSet
|
||||
* @see LinkedHashSet
|
||||
*/
|
||||
public static <T> T lastElement(Set<T> set) {
|
||||
if (isEmpty(set)) {
|
||||
|
||||
@@ -2,9 +2,7 @@ package cloud.tianai.captcha.common.util;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
|
||||
@@ -17,11 +17,7 @@
|
||||
package cloud.tianai.captcha.common.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 拷贝spring
|
||||
@@ -60,9 +56,9 @@ public abstract class ObjectUtils {
|
||||
* that is, neither a RuntimeException nor an Error.
|
||||
* @param ex the throwable to check
|
||||
* @return whether the throwable is a checked exception
|
||||
* @see java.lang.Exception
|
||||
* @see java.lang.RuntimeException
|
||||
* @see java.lang.Error
|
||||
* @see Exception
|
||||
* @see RuntimeException
|
||||
* @see Error
|
||||
*/
|
||||
public static boolean isCheckedException(Throwable ex) {
|
||||
return !(ex instanceof RuntimeException || ex instanceof Error);
|
||||
@@ -125,8 +121,8 @@ public abstract class ObjectUtils {
|
||||
* @since 4.2
|
||||
* @see Optional#isPresent()
|
||||
* @see ObjectUtils#isEmpty(Object[])
|
||||
* @see CollectionUtils#isEmpty(java.util.Collection)
|
||||
* @see CollectionUtils#isEmpty(java.util.Map)
|
||||
* @see CollectionUtils#isEmpty(Collection)
|
||||
* @see CollectionUtils#isEmpty(Map)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static boolean isEmpty(Object obj) {
|
||||
@@ -155,7 +151,7 @@ public abstract class ObjectUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Unwrap the given object which is potentially a {@link java.util.Optional}.
|
||||
* Unwrap the given object which is potentially a {@link Optional}.
|
||||
* @param obj the candidate object
|
||||
* @return either the value held within the {@code Optional}, {@code null}
|
||||
* if the {@code Optional} is empty, or simply the given object as-is
|
||||
@@ -308,7 +304,7 @@ public abstract class ObjectUtils {
|
||||
* @param o2 second Object to compare
|
||||
* @return whether the given objects are equal
|
||||
* @see Object#equals(Object)
|
||||
* @see java.util.Arrays#equals
|
||||
* @see Arrays#equals
|
||||
*/
|
||||
public static boolean nullSafeEquals(Object o1, Object o2) {
|
||||
if (o1 == o2) {
|
||||
@@ -333,7 +329,7 @@ public abstract class ObjectUtils {
|
||||
* @param o2 second array to compare
|
||||
* @return whether the given objects are equal
|
||||
* @see #nullSafeEquals(Object, Object)
|
||||
* @see java.util.Arrays#equals
|
||||
* @see Arrays#equals
|
||||
*/
|
||||
private static boolean arrayEquals(Object o1, Object o2) {
|
||||
if (o1 instanceof Object[] && o2 instanceof Object[]) {
|
||||
|
||||
@@ -2,7 +2,7 @@ package cloud.tianai.captcha.generator;
|
||||
|
||||
import cloud.tianai.captcha.common.exception.ImageCaptchaException;
|
||||
import cloud.tianai.captcha.common.util.CollectionUtils;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CustomData;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
||||
@@ -20,7 +20,6 @@ import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@@ -102,21 +101,21 @@ public abstract class AbstractImageCaptchaGenerator implements ImageCaptchaGener
|
||||
public ImageCaptchaInfo generateCaptchaImage(GenerateParam param) {
|
||||
assertInit();
|
||||
CustomData data = new CustomData();
|
||||
CaptchaTransferData transferData = CaptchaTransferData.create(data, param);
|
||||
ImageCaptchaInfo imageCaptchaInfo = applyPostProcessorBeforeGenerate(transferData, this);
|
||||
CaptchaExchange captchaExchange = CaptchaExchange.create(data, param);
|
||||
ImageCaptchaInfo imageCaptchaInfo = applyPostProcessorBeforeGenerate(captchaExchange, this);
|
||||
if (imageCaptchaInfo != null) {
|
||||
return imageCaptchaInfo;
|
||||
}
|
||||
doGenerateCaptchaImage(transferData);
|
||||
applyPostProcessorBeforeWrapImageCaptchaInfo(transferData, this);
|
||||
imageCaptchaInfo = wrapImageCaptchaInfo(transferData);
|
||||
applyPostProcessorAfterGenerateCaptchaImage(transferData, imageCaptchaInfo, this);
|
||||
doGenerateCaptchaImage(captchaExchange);
|
||||
applyPostProcessorBeforeWrapImageCaptchaInfo(captchaExchange, this);
|
||||
imageCaptchaInfo = wrapImageCaptchaInfo(captchaExchange);
|
||||
applyPostProcessorAfterGenerateCaptchaImage(captchaExchange, imageCaptchaInfo, this);
|
||||
return imageCaptchaInfo;
|
||||
}
|
||||
|
||||
public ImageCaptchaInfo wrapImageCaptchaInfo(CaptchaTransferData transferData) {
|
||||
ImageCaptchaInfo imageCaptchaInfo = doWrapImageCaptchaInfo(transferData);
|
||||
imageCaptchaInfo.setData(transferData.getCustomData());
|
||||
public ImageCaptchaInfo wrapImageCaptchaInfo(CaptchaExchange captchaExchange) {
|
||||
ImageCaptchaInfo imageCaptchaInfo = doWrapImageCaptchaInfo(captchaExchange);
|
||||
imageCaptchaInfo.setData(captchaExchange.getCustomData());
|
||||
return imageCaptchaInfo;
|
||||
}
|
||||
|
||||
@@ -225,12 +224,12 @@ public abstract class AbstractImageCaptchaGenerator implements ImageCaptchaGener
|
||||
/**
|
||||
* 生成验证码方法
|
||||
*
|
||||
* @param transferData transferData
|
||||
* @param captchaExchange captchaExchange
|
||||
* @return ImageCaptchaInfo
|
||||
*/
|
||||
protected abstract void doGenerateCaptchaImage(CaptchaTransferData transferData);
|
||||
protected abstract void doGenerateCaptchaImage(CaptchaExchange captchaExchange);
|
||||
|
||||
protected abstract ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData);
|
||||
protected abstract ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange);
|
||||
|
||||
@Override
|
||||
public ImageCaptchaResourceManager getImageResourceManager() {
|
||||
|
||||
@@ -41,7 +41,7 @@ public interface ImageCaptchaGenerator {
|
||||
ImageCaptchaInfo generateCaptchaImage(String type, String targetFormatName, String matrixFormatName);
|
||||
|
||||
/**
|
||||
* 生成滑块验证码
|
||||
* 生成验证码
|
||||
*
|
||||
* @param param 生成参数
|
||||
* @return SliderCaptchaInfo
|
||||
|
||||
@@ -24,5 +24,7 @@ public interface ImageCaptchaGeneratorProvider {
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getType();
|
||||
default String getType() {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package cloud.tianai.captcha.generator;
|
||||
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
||||
|
||||
/**
|
||||
@@ -11,15 +10,35 @@ import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
||||
*/
|
||||
public interface ImageCaptchaPostProcessor {
|
||||
|
||||
default ImageCaptchaInfo beforeGenerateCaptchaImage(CaptchaTransferData transferData, ImageCaptchaGenerator context) {
|
||||
/**
|
||||
* 在生成验证码核心逻辑之前调用, 用于拦截验证码生成、限流、自定义返回数据等处理
|
||||
*
|
||||
* @param captchaExchange 传输数据
|
||||
* @param generator generator
|
||||
* @return ImageCaptchaInfo
|
||||
*/
|
||||
default ImageCaptchaInfo beforeGenerateCaptchaImage(CaptchaExchange captchaExchange, ImageCaptchaGenerator generator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
default void beforeWrapImageCaptchaInfo(CaptchaTransferData transferData, ImageCaptchaGenerator context) {
|
||||
/**
|
||||
* 在执行包装 ImageCaptchaInfo 核心逻辑之前处理
|
||||
*
|
||||
* @param captchaExchange 传输数据
|
||||
* @param generator generator
|
||||
*/
|
||||
default void beforeWrapImageCaptchaInfo(CaptchaExchange captchaExchange, ImageCaptchaGenerator generator) {
|
||||
|
||||
}
|
||||
|
||||
default void afterGenerateCaptchaImage(CaptchaTransferData transferData, ImageCaptchaInfo imageCaptchaInfo, ImageCaptchaGenerator context) {
|
||||
/**
|
||||
* 在执行包装 ImageCaptchaInfo 核心逻辑之后处理
|
||||
*
|
||||
* @param captchaExchange captchaExchange
|
||||
* @param imageCaptchaInfo imageCaptchaInfo
|
||||
* @param generator generator
|
||||
*/
|
||||
default void afterGenerateCaptchaImage(CaptchaExchange captchaExchange, ImageCaptchaInfo imageCaptchaInfo, ImageCaptchaGenerator generator) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,11 @@ public interface ImageTransform {
|
||||
* @param backgroundImage 背景图片
|
||||
* @param param 参数
|
||||
* @param backgroundResource 背景资源对象
|
||||
* @param data 自定义透传数据
|
||||
* @return ImageTransformData
|
||||
*/
|
||||
default ImageTransformData transform(GenerateParam param, BufferedImage backgroundImage, Resource backgroundResource,CustomData data) {
|
||||
return transform(param, backgroundImage, null, backgroundResource, null,data);
|
||||
default ImageTransformData transform(GenerateParam param, BufferedImage backgroundImage, Resource backgroundResource, CustomData data) {
|
||||
return transform(param, backgroundImage, null, backgroundResource, null, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,6 +35,7 @@ public interface ImageTransform {
|
||||
* @param param 参数
|
||||
* @param backgroundResource 背景资源对象
|
||||
* @param templateResource 模板资源对象(可能为空)
|
||||
* @param data 自定义透传数据
|
||||
* @return String
|
||||
*/
|
||||
ImageTransformData transform(GenerateParam param,
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package cloud.tianai.captcha.generator.common;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class FontWrapper {
|
||||
private Font font;
|
||||
private float currentFontTopCoef;
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
package cloud.tianai.captcha.generator.common.constant;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2021/8/7 17:14
|
||||
* @Description 滑块验证码常量
|
||||
*/
|
||||
public interface SliderCaptchaConstant {
|
||||
|
||||
/** 模板滑块固定名称. */
|
||||
String TEMPLATE_ACTIVE_IMAGE_NAME = "active.png";
|
||||
/** 模板凹槽固定名称. */
|
||||
String TEMPLATE_FIXED_IMAGE_NAME = "fixed.png";
|
||||
/** 模板蒙版. */
|
||||
String TEMPLATE_MASK_IMAGE_NAME = "mask.png";
|
||||
/** 混淆的凹槽.*/
|
||||
String OBFUSCATE_TEMPLATE_FIXED_IMAGE_NAME = "obfuscate_" + TEMPLATE_FIXED_IMAGE_NAME;
|
||||
}
|
||||
+14
-8
@@ -12,24 +12,30 @@ import java.awt.image.BufferedImage;
|
||||
* @Description 传输用
|
||||
*/
|
||||
@Data
|
||||
public class CaptchaTransferData {
|
||||
public class CaptchaExchange {
|
||||
/** 模板对象. */
|
||||
private ResourceMap templateResource;
|
||||
/** 资源对象. */
|
||||
private Resource resourceImage;
|
||||
/** 生成好的背景图片. */
|
||||
private BufferedImage backgroundImage;
|
||||
/** 生成好的模板图片. */
|
||||
private BufferedImage templateImage;
|
||||
/** 最终要回调给验证器的自定义对象. */
|
||||
private CustomData customData;
|
||||
/** 用户传来的生成参数. */
|
||||
private GenerateParam param;
|
||||
|
||||
/** 传输对象,扩展自定义. */
|
||||
private Object transferData;
|
||||
|
||||
public static CaptchaTransferData create(CustomData customData, GenerateParam param) {
|
||||
CaptchaTransferData captchaTransferData = new CaptchaTransferData();
|
||||
captchaTransferData.setCustomData(customData);
|
||||
captchaTransferData.setParam(param);
|
||||
return captchaTransferData;
|
||||
public static CaptchaExchange create(CustomData customData, GenerateParam param) {
|
||||
CaptchaExchange captchaExchange = new CaptchaExchange();
|
||||
captchaExchange.setCustomData(customData);
|
||||
captchaExchange.setParam(param);
|
||||
return captchaExchange;
|
||||
}
|
||||
|
||||
public static CaptchaTransferData create(GenerateParam param) {
|
||||
public static CaptchaExchange create(GenerateParam param) {
|
||||
return create(new CustomData(), param);
|
||||
}
|
||||
}
|
||||
+4
@@ -5,6 +5,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/4/28 16:51
|
||||
@@ -24,5 +26,7 @@ public class ClickImageCheckDefinition {
|
||||
private Integer width;
|
||||
/** 高.*/
|
||||
private Integer height;
|
||||
/** 颜色.*/
|
||||
private Color imageColor;
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ public class ImageCaptchaInfo {
|
||||
private Float tolerant;
|
||||
/** 验证码类型. */
|
||||
private String type;
|
||||
/** 透传字段,用于传给前端. */
|
||||
private CustomData data;
|
||||
|
||||
public ImageCaptchaInfo(String backgroundImage,
|
||||
|
||||
@@ -9,15 +9,11 @@ import java.awt.geom.CubicCurve2D;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.PixelGrabber;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -75,25 +71,6 @@ public class CaptchaImageUtils {
|
||||
}
|
||||
|
||||
|
||||
public static int getMaxPix(BufferedImage image, int x, int y, int width, int height) {
|
||||
int[] rgbArr = new int[width * height];
|
||||
image.getRGB(x, y, width, height, rgbArr, 0, width);
|
||||
Map<Integer, Integer> map = new HashMap<>();
|
||||
for (int rgb : rgbArr) {
|
||||
Integer count = map.getOrDefault(rgb, 0);
|
||||
map.put(rgb, count + 1);
|
||||
}
|
||||
AtomicInteger maxRgb = new AtomicInteger();
|
||||
AtomicInteger maxRgbCount = new AtomicInteger();
|
||||
map.forEach((r, c) -> {
|
||||
if (c > maxRgbCount.get()) {
|
||||
maxRgb.set(r);
|
||||
maxRgbCount.set(c);
|
||||
}
|
||||
});
|
||||
return maxRgb.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Image图像中的透明/不透明部分转换为Shape图形
|
||||
*
|
||||
@@ -195,48 +172,6 @@ public class CaptchaImageUtils {
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public static BufferedImage cutImage_bak(BufferedImage origin, BufferedImage template, int x, int y) {
|
||||
int bw = template.getWidth(null);
|
||||
int bh = template.getHeight(null);
|
||||
int lw = origin.getWidth(null);
|
||||
int lh = origin.getHeight(null);
|
||||
//得到透明的区域(人物轮廓)
|
||||
Shape imageShape = getImageShape(template, false);
|
||||
long end = System.currentTimeMillis();
|
||||
//合成后的图片
|
||||
BufferedImage image = new BufferedImage(bw, bh, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D graphics = image.createGraphics();
|
||||
//设置画布为透明
|
||||
image = graphics.getDeviceConfiguration().createCompatibleImage(bw, bh, Transparency.TRANSLUCENT);
|
||||
graphics.dispose();
|
||||
Graphics2D graphics2 = image.createGraphics();
|
||||
//取交集(限制可以画的范围为shape的范围)
|
||||
graphics2.clip(imageShape);
|
||||
//抗锯齿
|
||||
graphics2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
graphics2.setStroke(new BasicStroke(5, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
graphics2.drawImage(origin, -x, -y, lw, lh, null);
|
||||
graphics2.dispose();
|
||||
return image;
|
||||
}
|
||||
|
||||
public static void replaceColorByOpaque(BufferedImage oriImage, int replaceRgb) {
|
||||
int bh = oriImage.getHeight();
|
||||
int bw = oriImage.getWidth();
|
||||
// 透明色
|
||||
for (int y = 0; y < bh; y++) {
|
||||
for (int x = 0; x < bw; x++) {
|
||||
int rgb = oriImage.getRGB(x, y);
|
||||
int alpha = (rgb >> 24) & 0xff;
|
||||
// 透明度大于100才处理,过滤一下边缘过于透明的像素点
|
||||
if (alpha > 100) {
|
||||
oriImage.setRGB(x, y, replaceRgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 旋转图片
|
||||
*
|
||||
@@ -278,26 +213,6 @@ public class CaptchaImageUtils {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 通过x和y轴截取图片
|
||||
*
|
||||
* @param x x
|
||||
* @param y y
|
||||
* @param width 宽度
|
||||
* @param height 高度
|
||||
* @param img 截取的图片
|
||||
* @return BufferedImage
|
||||
*/
|
||||
public static BufferedImage subImage(int x, int y, int width, int height, BufferedImage img) {
|
||||
int[] simgRgb = new int[width * height];
|
||||
img.getRGB(x, y, width, height, simgRgb, 0, width);
|
||||
// 得到图片透明度。
|
||||
int type = img.getColorModel().getTransparency();
|
||||
BufferedImage newImage = new BufferedImage(width, height, type);
|
||||
newImage.setRGB(0, 0, width, height, simgRgb, 0, width);
|
||||
return newImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分隔图片
|
||||
*
|
||||
@@ -354,11 +269,11 @@ public class CaptchaImageUtils {
|
||||
for (BufferedImage img : imgArr) {
|
||||
if (direction) {
|
||||
// 水平方向
|
||||
graphics.drawImage(img, pos, 0, img.getWidth(), img.getHeight(),null);
|
||||
graphics.drawImage(img, pos, 0, img.getWidth(), img.getHeight(), null);
|
||||
pos += img.getWidth();
|
||||
} else {
|
||||
// 垂直方向
|
||||
graphics.drawImage(img, 0, pos, img.getWidth(), img.getHeight(),null);
|
||||
graphics.drawImage(img, 0, pos, img.getWidth(), img.getHeight(), null);
|
||||
pos += img.getHeight();
|
||||
}
|
||||
}
|
||||
@@ -366,10 +281,6 @@ public class CaptchaImageUtils {
|
||||
return newImage;
|
||||
}
|
||||
|
||||
public static char getRandomChar() {
|
||||
return (char) (0x4e00 + (int) (Math.random() * (0x9fa5 - 0x4e00 + 1)));
|
||||
}
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
public static BufferedImage drawWordImg(Color fontColor,
|
||||
@@ -497,23 +408,6 @@ public class CaptchaImageUtils {
|
||||
}
|
||||
|
||||
|
||||
public static void drawInterfere(Graphics2D g, int width,
|
||||
int height,
|
||||
int interferenceLineNum,
|
||||
int interferencePointNum) {
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
// 干扰点
|
||||
if (interferencePointNum > 0) {
|
||||
drawOval(interferencePointNum, null, g, width, height, random);
|
||||
}
|
||||
if (interferencePointNum > 0) {
|
||||
g.setStroke(new BasicStroke(1.2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
|
||||
// 干扰线
|
||||
drawBesselLine(interferenceLineNum, null, g, width, height, random);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 随机获取颜色
|
||||
*
|
||||
@@ -527,12 +421,6 @@ public class CaptchaImageUtils {
|
||||
|
||||
}
|
||||
|
||||
public static RenderedImage toRenderedImage(Image img) {
|
||||
if (img instanceof RenderedImage) {
|
||||
return (RenderedImage) img;
|
||||
}
|
||||
return copyImage(img, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成指定类型的 BufferedImage
|
||||
@@ -595,30 +483,6 @@ public class CaptchaImageUtils {
|
||||
return bimage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 灰度处理,把原图传进去,传出来为修改后的图
|
||||
*
|
||||
* @param b b
|
||||
* @return BufferedImage
|
||||
*/
|
||||
public static BufferedImage gray(BufferedImage b) {
|
||||
int width = b.getWidth();
|
||||
int height = b.getHeight();
|
||||
// 下面这个别忘了定义,不然会出错
|
||||
BufferedImage bufferedImageEnd = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
|
||||
// 双层循环更改图片的RGB值,把得到的灰度值存到bufferedImage_end中,然后返回bufferedImage_end
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// 获取到(x,y)此像素点的Colo,转化为灰度
|
||||
Color color = new Color(b.getRGB(x, y));
|
||||
int gray = (int) (color.getRed() * 0.299 + color.getGreen() * 0.587 + color.getBlue() * 0.114);
|
||||
Color color_end = new Color(gray, gray, gray);
|
||||
bufferedImageEnd.setRGB(x, y, color_end.getRGB());
|
||||
}
|
||||
}
|
||||
return bufferedImageEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建画板
|
||||
*
|
||||
@@ -636,21 +500,6 @@ public class CaptchaImageUtils {
|
||||
return g;
|
||||
}
|
||||
|
||||
public static BufferedImage toBufferedImage(Image img) {
|
||||
if (img instanceof BufferedImage) {
|
||||
return (BufferedImage) img;
|
||||
}
|
||||
// Create a buffered image with transparency
|
||||
BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
|
||||
// Draw the image on to the buffered image
|
||||
Graphics2D bGr = bimage.createGraphics();
|
||||
bGr.drawImage(img, 0, 0, null);
|
||||
bGr.dispose();
|
||||
// Return the buffered image
|
||||
return bimage;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 后缀是否是jpg
|
||||
*
|
||||
@@ -672,3 +521,4 @@ public class CaptchaImageUtils {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+12
-9
@@ -1,10 +1,9 @@
|
||||
package cloud.tianai.captcha.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ClickImageCheckDefinition;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
@@ -13,10 +12,10 @@ import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -25,6 +24,7 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||
*/
|
||||
public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
public static final String CLICK_IMAGE_DISTORT_KEY = "clickImageDistort";
|
||||
|
||||
public AbstractClickImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
|
||||
super(imageCaptchaResourceManager);
|
||||
@@ -35,8 +35,8 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void doGenerateCaptchaImage(CaptchaTransferData transferData) {
|
||||
GenerateParam param = transferData.getParam();
|
||||
public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
|
||||
GenerateParam param = captchaExchange.getParam();
|
||||
// 文字点选验证码不需要模板 只需要背景图
|
||||
Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag());
|
||||
|
||||
@@ -65,19 +65,20 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
// 随机y
|
||||
int randomY = randomInt(10, bgImage.getHeight() - clickImgHeight);
|
||||
// 通过随机x和y 进行覆盖图片
|
||||
CaptchaImageUtils.overlayImage(bgImage, imgWrapper.getImage(), randomX, randomY);
|
||||
CaptchaImageUtils.overlayImage(bgImage, image, randomX, randomY);
|
||||
ClickImageCheckDefinition clickImageCheckDefinition = new ClickImageCheckDefinition();
|
||||
clickImageCheckDefinition.setTip(imgWrapper.getTip());
|
||||
clickImageCheckDefinition.setX(randomX + clickImgWidth / 2);
|
||||
clickImageCheckDefinition.setY(randomY + clickImgHeight / 2);
|
||||
clickImageCheckDefinition.setWidth(clickImgWidth);
|
||||
clickImageCheckDefinition.setHeight(clickImgHeight);
|
||||
clickImageCheckDefinition.setImageColor(imgWrapper.getImageColor());
|
||||
clickImageCheckDefinitionList.add(clickImageCheckDefinition);
|
||||
}
|
||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = filterAndSortClickImageCheckDefinition(clickImageCheckDefinitionList);
|
||||
transferData.setBackgroundImage(bgImage);
|
||||
transferData.setTransferData(checkClickImageCheckDefinitionList);
|
||||
transferData.setResourceImage(resourceImage);
|
||||
captchaExchange.setBackgroundImage(bgImage);
|
||||
captchaExchange.setTransferData(checkClickImageCheckDefinitionList);
|
||||
captchaExchange.setResourceImage(resourceImage);
|
||||
|
||||
|
||||
// // wrap
|
||||
@@ -123,5 +124,7 @@ public abstract class AbstractClickImageCaptchaGenerator extends AbstractImageCa
|
||||
private BufferedImage image;
|
||||
/** 提示. */
|
||||
private Resource tip;
|
||||
/** 图片颜色. */
|
||||
private Color imageColor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
package cloud.tianai.captcha.generator.impl;
|
||||
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.common.util.ObjectUtils;
|
||||
import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import cloud.tianai.captcha.generator.impl.provider.StandardConcatImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.impl.provider.StandardWordClickImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.impl.provider.StandardRotateImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.impl.provider.StandardSliderImageImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.impl.provider.CommonImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -21,6 +17,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static cloud.tianai.captcha.common.constant.CaptchaTypeConstant.*;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/4/24 9:27
|
||||
@@ -33,7 +31,7 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private String defaultCaptcha = CaptchaTypeConstant.SLIDER;
|
||||
private String defaultCaptcha = SLIDER;
|
||||
|
||||
protected boolean initDefaultResource = false;
|
||||
|
||||
@@ -49,14 +47,15 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
@Override
|
||||
protected void doInit(boolean initDefaultResource) {
|
||||
this.initDefaultResource = initDefaultResource;
|
||||
|
||||
// 滑块验证码
|
||||
addImageCaptchaGeneratorProvider(new StandardSliderImageImageCaptchaGeneratorProvider());
|
||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(SLIDER, StandardSliderImageCaptchaGenerator::new));
|
||||
// 旋转验证码
|
||||
addImageCaptchaGeneratorProvider(new StandardRotateImageCaptchaGeneratorProvider());
|
||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(ROTATE, StandardRotateImageCaptchaGenerator::new));
|
||||
// 拼接验证码
|
||||
addImageCaptchaGeneratorProvider(new StandardConcatImageCaptchaGeneratorProvider());
|
||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(CONCAT, StandardConcatImageCaptchaGenerator::new));
|
||||
// 点选文字验证码
|
||||
addImageCaptchaGeneratorProvider(new StandardWordClickImageCaptchaGeneratorProvider());
|
||||
addImageCaptchaGeneratorProvider(new CommonImageCaptchaGeneratorProvider(WORD_IMAGE_CLICK, StandardWordClickImageCaptchaGenerator::new));
|
||||
}
|
||||
|
||||
public void addImageCaptchaGeneratorProvider(ImageCaptchaGeneratorProvider provider) {
|
||||
@@ -96,12 +95,12 @@ public class MultiImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
|
||||
@Override
|
||||
protected void doGenerateCaptchaImage(CaptchaTransferData transferData) {
|
||||
protected void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) {
|
||||
protected ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+14
-18
@@ -11,15 +11,11 @@ import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH;
|
||||
import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG;
|
||||
import static cloud.tianai.captcha.generator.common.util.CaptchaImageUtils.*;
|
||||
import static cloud.tianai.captcha.generator.impl.StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH;
|
||||
import static cloud.tianai.captcha.generator.common.util.CaptchaImageUtils.concatImage;
|
||||
import static cloud.tianai.captcha.generator.common.util.CaptchaImageUtils.splitImage;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -51,8 +47,8 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGenerateCaptchaImage(CaptchaTransferData transferData) {
|
||||
GenerateParam param = transferData.getParam();
|
||||
public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
|
||||
GenerateParam param = captchaExchange.getParam();
|
||||
// 拼接验证码不需要模板 只需要背景图
|
||||
Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag());
|
||||
BufferedImage bgImage = getResourceImage(resourceImage);
|
||||
@@ -72,9 +68,9 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
data.x = randomX;
|
||||
data.y = randomY;
|
||||
|
||||
transferData.setTransferData(data);
|
||||
transferData.setBackgroundImage(bgImage);
|
||||
transferData.setResourceImage(resourceImage);
|
||||
captchaExchange.setTransferData(data);
|
||||
captchaExchange.setBackgroundImage(bgImage);
|
||||
captchaExchange.setResourceImage(resourceImage);
|
||||
}
|
||||
|
||||
public static class Data {
|
||||
@@ -84,13 +80,13 @@ public class StandardConcatImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) {
|
||||
GenerateParam param = transferData.getParam();
|
||||
BufferedImage bgImage = transferData.getBackgroundImage();
|
||||
Resource resourceImage = transferData.getResourceImage();
|
||||
CustomData customData = transferData.getCustomData();
|
||||
public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) {
|
||||
GenerateParam param = captchaExchange.getParam();
|
||||
BufferedImage bgImage = captchaExchange.getBackgroundImage();
|
||||
Resource resourceImage = captchaExchange.getResourceImage();
|
||||
CustomData customData = captchaExchange.getCustomData();
|
||||
ImageTransformData transform = getImageTransform().transform(param, bgImage, resourceImage, customData);
|
||||
Data data = (Data) transferData.getTransferData();
|
||||
Data data = (Data) captchaExchange.getTransferData();
|
||||
ImageCaptchaInfo imageCaptchaInfo = ImageCaptchaInfo.of(transform.getBackgroundImageUrl(),
|
||||
null,
|
||||
resourceImage.getTag(),
|
||||
|
||||
+34
-27
@@ -4,7 +4,6 @@ import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.common.constant.CommonConstant;
|
||||
import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.*;
|
||||
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
@@ -15,14 +14,9 @@ import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.Optional;
|
||||
|
||||
import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG;
|
||||
import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant.*;
|
||||
import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant.TEMPLATE_MASK_IMAGE_NAME;
|
||||
import static cloud.tianai.captcha.common.constant.CommonConstant.*;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -31,6 +25,13 @@ import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConsta
|
||||
*/
|
||||
public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
/** 模板滑块固定名称. */
|
||||
public static String TEMPLATE_ACTIVE_IMAGE_NAME = "active.png";
|
||||
/** 模板凹槽固定名称. */
|
||||
public static String TEMPLATE_FIXED_IMAGE_NAME = "fixed.png";
|
||||
/** 模板蒙版. */
|
||||
public static String TEMPLATE_MASK_IMAGE_NAME = "mask.png";
|
||||
|
||||
public StandardRotateImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
|
||||
super(imageCaptchaResourceManager);
|
||||
}
|
||||
@@ -50,18 +51,24 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
public void initDefaultResource() {
|
||||
ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
|
||||
// 添加一些系统的资源文件
|
||||
resourceStore.addResource(CaptchaTypeConstant.ROTATE, new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
|
||||
resourceStore.addResource(CaptchaTypeConstant.ROTATE, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
|
||||
|
||||
// 添加一些系统的 模板文件
|
||||
ResourceMap template1 = new ResourceMap(DEFAULT_TAG, 4);
|
||||
template1.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/active.png")));
|
||||
template1.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, StandardSliderImageCaptchaGenerator.DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/fixed.png")));
|
||||
template1.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/active.png")));
|
||||
template1.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/3/fixed.png")));
|
||||
resourceStore.addTemplate(CaptchaTypeConstant.ROTATE, template1);
|
||||
|
||||
ResourceMap template2 = new ResourceMap(CommonConstant.DEFAULT_TAG + "_obfuscate", 4);
|
||||
template2.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/4/active.png")));
|
||||
template2.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/4/fixed.png")));
|
||||
template2.put(TEMPLATE_MASK_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/4/mask.png")));
|
||||
resourceStore.addTemplate(CaptchaTypeConstant.ROTATE, template2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doGenerateCaptchaImage(CaptchaTransferData transferData) {
|
||||
GenerateParam param = transferData.getParam();
|
||||
public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
|
||||
GenerateParam param = captchaExchange.getParam();
|
||||
CustomData data = new CustomData();
|
||||
ResourceMap templateResource = requiredRandomGetTemplate(param.getType(), param.getTemplateImageTag());
|
||||
Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag());
|
||||
@@ -96,17 +103,17 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
int randomX = randomInt(fixedTemplate.getWidth() + 10, background.getWidth() - 10);
|
||||
double degree = 360d - randomX / ((background.getWidth()) / 360d);
|
||||
// 旋转的透明图片是一张正方形的
|
||||
BufferedImage matrixTemplate = CaptchaImageUtils.createTransparentImage(background.getHeight(), background.getHeight());
|
||||
BufferedImage matrixTemplate = CaptchaImageUtils.createTransparentImage(cutImage.getWidth(), background.getHeight());
|
||||
CaptchaImageUtils.centerOverlayAndRotateImage(matrixTemplate, cutImage, degree);
|
||||
|
||||
RotateData rotateData = new RotateData();
|
||||
rotateData.degree = degree;
|
||||
rotateData.randomX = randomX;
|
||||
transferData.setTransferData(rotateData);
|
||||
transferData.setBackgroundImage(background);
|
||||
transferData.setTemplateImage(matrixTemplate);
|
||||
transferData.setTemplateResource(templateResource);
|
||||
transferData.setResourceImage(resourceImage);
|
||||
captchaExchange.setTransferData(rotateData);
|
||||
captchaExchange.setBackgroundImage(background);
|
||||
captchaExchange.setTemplateImage(matrixTemplate);
|
||||
captchaExchange.setTemplateResource(templateResource);
|
||||
captchaExchange.setResourceImage(resourceImage);
|
||||
|
||||
// return wrapRotateCaptchaInfo(degree, randomX, background, matrixTemplate, param, templateResource, resourceImage, data);
|
||||
}
|
||||
@@ -125,14 +132,14 @@ public class StandardRotateImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) {
|
||||
GenerateParam param = transferData.getParam();
|
||||
BufferedImage backgroundImage = transferData.getBackgroundImage();
|
||||
BufferedImage sliderImage = transferData.getTemplateImage();
|
||||
Resource resourceImage = transferData.getResourceImage();
|
||||
ResourceMap templateResource = transferData.getTemplateResource();
|
||||
CustomData data = transferData.getCustomData();
|
||||
RotateData rotateData = (RotateData) transferData.getTransferData();
|
||||
public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) {
|
||||
GenerateParam param = captchaExchange.getParam();
|
||||
BufferedImage backgroundImage = captchaExchange.getBackgroundImage();
|
||||
BufferedImage sliderImage = captchaExchange.getTemplateImage();
|
||||
Resource resourceImage = captchaExchange.getResourceImage();
|
||||
ResourceMap templateResource = captchaExchange.getTemplateResource();
|
||||
CustomData data = captchaExchange.getCustomData();
|
||||
RotateData rotateData = (RotateData) captchaExchange.getTransferData();
|
||||
ImageTransformData transform = getImageTransform().transform(param, backgroundImage, sliderImage, resourceImage, templateResource, data);
|
||||
RotateImageCaptchaInfo imageCaptchaInfo = RotateImageCaptchaInfo.of(rotateData.degree,
|
||||
rotateData.randomX,
|
||||
|
||||
+30
-33
@@ -3,7 +3,6 @@ package cloud.tianai.captcha.generator.impl;
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.*;
|
||||
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
@@ -16,14 +15,10 @@ import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG;
|
||||
import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant.*;
|
||||
import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConstant.TEMPLATE_FIXED_IMAGE_NAME;
|
||||
import static cloud.tianai.captcha.common.constant.CommonConstant.*;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -33,14 +28,16 @@ import static cloud.tianai.captcha.generator.common.constant.SliderCaptchaConsta
|
||||
@Slf4j
|
||||
public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGenerator {
|
||||
|
||||
/**
|
||||
* 默认的resource资源文件路径.
|
||||
*/
|
||||
public static final String DEFAULT_SLIDER_IMAGE_RESOURCE_PATH = "META-INF/cut-image/resource";
|
||||
/**
|
||||
* 默认的template资源文件路径.
|
||||
*/
|
||||
public static final String DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH = "META-INF/cut-image/template";
|
||||
|
||||
/** 模板滑块固定名称. */
|
||||
public static String TEMPLATE_ACTIVE_IMAGE_NAME = "active.png";
|
||||
/** 模板凹槽固定名称. */
|
||||
public static String TEMPLATE_FIXED_IMAGE_NAME = "fixed.png";
|
||||
/** 模板蒙版. */
|
||||
public static String TEMPLATE_MASK_IMAGE_NAME = "mask.png";
|
||||
/** 混淆的凹槽. */
|
||||
public static String OBFUSCATE_TEMPLATE_FIXED_IMAGE_NAME = "obfuscate_" + TEMPLATE_FIXED_IMAGE_NAME;
|
||||
|
||||
|
||||
public StandardSliderImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
|
||||
super(imageCaptchaResourceManager);
|
||||
@@ -60,8 +57,8 @@ public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void doGenerateCaptchaImage(CaptchaTransferData transferData) {
|
||||
GenerateParam param = transferData.getParam();
|
||||
public void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
|
||||
GenerateParam param = captchaExchange.getParam();
|
||||
Boolean obfuscate = param.getObfuscate();
|
||||
ResourceMap templateResource = requiredRandomGetTemplate(param.getType(), param.getTemplateImageTag());
|
||||
Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag());
|
||||
@@ -93,15 +90,15 @@ public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
XandY xandY = new XandY();
|
||||
xandY.x = randomX;
|
||||
xandY.y = randomY;
|
||||
transferData.setBackgroundImage(background);
|
||||
transferData.setTemplateImage(matrixTemplate);
|
||||
transferData.setTemplateResource(templateResource);
|
||||
transferData.setResourceImage(resourceImage);
|
||||
transferData.setTransferData(xandY);
|
||||
captchaExchange.setBackgroundImage(background);
|
||||
captchaExchange.setTemplateImage(matrixTemplate);
|
||||
captchaExchange.setTemplateResource(templateResource);
|
||||
captchaExchange.setResourceImage(resourceImage);
|
||||
captchaExchange.setTransferData(xandY);
|
||||
// 后处理
|
||||
// applyPostProcessorBeforeWrapImageCaptchaInfo(transferData, this);
|
||||
// imageCaptchaInfo = wrapSliderCaptchaInfo(randomX, randomY, transferData);
|
||||
// applyPostProcessorAfterGenerateCaptchaImage(transferData, imageCaptchaInfo, this);
|
||||
// applyPostProcessorBeforeWrapImageCaptchaInfo(captchaExchange, this);
|
||||
// imageCaptchaInfo = wrapSliderCaptchaInfo(randomX, randomY, captchaExchange);
|
||||
// applyPostProcessorAfterGenerateCaptchaImage(captchaExchange, imageCaptchaInfo, this);
|
||||
// return imageCaptchaInfo;
|
||||
}
|
||||
|
||||
@@ -134,14 +131,14 @@ public class StandardSliderImageCaptchaGenerator extends AbstractImageCaptchaGen
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public SliderImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) {
|
||||
GenerateParam param = transferData.getParam();
|
||||
BufferedImage backgroundImage = transferData.getBackgroundImage();
|
||||
BufferedImage sliderImage = transferData.getTemplateImage();
|
||||
Resource resourceImage = transferData.getResourceImage();
|
||||
ResourceMap templateResource = transferData.getTemplateResource();
|
||||
CustomData customData = transferData.getCustomData();
|
||||
XandY data = (XandY) transferData.getTransferData();
|
||||
public SliderImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) {
|
||||
GenerateParam param = captchaExchange.getParam();
|
||||
BufferedImage backgroundImage = captchaExchange.getBackgroundImage();
|
||||
BufferedImage sliderImage = captchaExchange.getTemplateImage();
|
||||
Resource resourceImage = captchaExchange.getResourceImage();
|
||||
ResourceMap templateResource = captchaExchange.getTemplateResource();
|
||||
CustomData customData = captchaExchange.getCustomData();
|
||||
XandY data = (XandY) captchaExchange.getTransferData();
|
||||
ImageTransformData transform = getImageTransform().transform(param, backgroundImage, sliderImage, resourceImage, templateResource, customData);
|
||||
|
||||
SliderImageCaptchaInfo imageCaptchaInfo = SliderImageCaptchaInfo.of(data.x, data.y,
|
||||
|
||||
+15
-18
@@ -4,13 +4,16 @@ import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.common.util.CollectionUtils;
|
||||
import cloud.tianai.captcha.common.util.FontUtils;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.common.FontWrapper;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.*;
|
||||
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.resource.ResourceStore;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider;
|
||||
import lombok.*;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -22,6 +25,7 @@ import java.util.List;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_SLIDER_IMAGE_RESOURCE_PATH;
|
||||
import static cloud.tianai.captcha.common.constant.CommonConstant.DEFAULT_TAG;
|
||||
|
||||
/**
|
||||
@@ -114,7 +118,7 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
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"), DEFAULT_TAG));
|
||||
resourceStore.addResource(CaptchaTypeConstant.WORD_IMAGE_CLICK, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
|
||||
}
|
||||
|
||||
public ImgWrapper genTipImage(List<ClickImageCheckDefinition> imageCheckDefinitions) {
|
||||
@@ -130,7 +134,7 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
float top = 6 / 2f + font.getSize() - currentFontTopCoef;
|
||||
BufferedImage bufferedImage = CaptchaImageUtils.genSimpleImgCaptcha(tips,
|
||||
font, width, height, left, top, tipImageInterferenceLineNum, tipImageInterferencePointNum);
|
||||
return new ImgWrapper(bufferedImage, new Resource(null, tips));
|
||||
return new ImgWrapper(bufferedImage, new Resource(null, tips), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,7 +154,7 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
clickImgWidth,
|
||||
clickImgHeight,
|
||||
randomDeg);
|
||||
return new ImgWrapper(fontImage, tip);
|
||||
return new ImgWrapper(fontImage, tip, randomColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,12 +171,12 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaTransferData transferData) {
|
||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = (List<ClickImageCheckDefinition>) transferData.getTransferData();
|
||||
BufferedImage bgImage = transferData.getBackgroundImage();
|
||||
GenerateParam param = transferData.getParam();
|
||||
Resource resourceImage = transferData.getResourceImage();
|
||||
CustomData data = transferData.getCustomData();
|
||||
public ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) {
|
||||
List<ClickImageCheckDefinition> checkClickImageCheckDefinitionList = (List<ClickImageCheckDefinition>) captchaExchange.getTransferData();
|
||||
BufferedImage bgImage = captchaExchange.getBackgroundImage();
|
||||
GenerateParam param = captchaExchange.getParam();
|
||||
Resource resourceImage = captchaExchange.getResourceImage();
|
||||
CustomData data = captchaExchange.getCustomData();
|
||||
// 提示图片
|
||||
BufferedImage tipImage = genTipImage(checkClickImageCheckDefinitionList).getImage();
|
||||
ImageTransformData transform = getImageTransform().transform(param, bgImage, tipImage, resourceImage, checkClickImageCheckDefinitionList, data);
|
||||
@@ -191,12 +195,5 @@ public class StandardWordClickImageCaptchaGenerator extends AbstractClickImageCa
|
||||
return clickImageCaptchaInfo;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class FontWrapper {
|
||||
private Font font;
|
||||
private float currentFontTopCoef;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-11
@@ -3,7 +3,7 @@ package cloud.tianai.captcha.generator.impl;
|
||||
import cloud.tianai.captcha.common.exception.ImageCaptchaException;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaPostProcessor;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaTransferData;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.CaptchaExchange;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -20,10 +20,6 @@ public class StaticCaptchaPostProcessorManager {
|
||||
@Getter
|
||||
private static LinkedList<ImageCaptchaPostProcessor> processors = new LinkedList<>();
|
||||
|
||||
static {
|
||||
|
||||
}
|
||||
|
||||
public static void add(ImageCaptchaPostProcessor processor) {
|
||||
processors.add(processor);
|
||||
}
|
||||
@@ -49,10 +45,10 @@ public class StaticCaptchaPostProcessorManager {
|
||||
}
|
||||
|
||||
|
||||
public static ImageCaptchaInfo applyPostProcessorBeforeGenerate(CaptchaTransferData transferData, ImageCaptchaGenerator context) {
|
||||
public static ImageCaptchaInfo applyPostProcessorBeforeGenerate(CaptchaExchange captchaExchange, ImageCaptchaGenerator context) {
|
||||
for (ImageCaptchaPostProcessor processor : processors) {
|
||||
try {
|
||||
ImageCaptchaInfo imageCaptchaInfo = processor.beforeGenerateCaptchaImage(transferData, context);
|
||||
ImageCaptchaInfo imageCaptchaInfo = processor.beforeGenerateCaptchaImage(captchaExchange, context);
|
||||
if (imageCaptchaInfo != null) {
|
||||
return imageCaptchaInfo;
|
||||
}
|
||||
@@ -63,10 +59,10 @@ public class StaticCaptchaPostProcessorManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void applyPostProcessorBeforeWrapImageCaptchaInfo(CaptchaTransferData transferData, ImageCaptchaGenerator context) {
|
||||
public static void applyPostProcessorBeforeWrapImageCaptchaInfo(CaptchaExchange captchaExchange, ImageCaptchaGenerator context) {
|
||||
for (ImageCaptchaPostProcessor processor : processors) {
|
||||
try {
|
||||
processor.beforeWrapImageCaptchaInfo(transferData, context);
|
||||
processor.beforeWrapImageCaptchaInfo(captchaExchange, context);
|
||||
} catch (Exception e) {
|
||||
throw new ImageCaptchaException("apply ImageCaptchaPostProcessor.beforeWrapImageCaptchaInfo error, [" + processor.getClass() + "]", e);
|
||||
}
|
||||
@@ -74,10 +70,10 @@ public class StaticCaptchaPostProcessorManager {
|
||||
}
|
||||
|
||||
|
||||
public static void applyPostProcessorAfterGenerateCaptchaImage(CaptchaTransferData transferData, ImageCaptchaInfo imageCaptchaInfo, ImageCaptchaGenerator context) {
|
||||
public static void applyPostProcessorAfterGenerateCaptchaImage(CaptchaExchange captchaExchange, ImageCaptchaInfo imageCaptchaInfo, ImageCaptchaGenerator context) {
|
||||
for (ImageCaptchaPostProcessor processor : processors) {
|
||||
try {
|
||||
processor.afterGenerateCaptchaImage(transferData, imageCaptchaInfo, context);
|
||||
processor.afterGenerateCaptchaImage(captchaExchange, imageCaptchaInfo, context);
|
||||
} catch (Exception e) {
|
||||
throw new ImageCaptchaException("apply ImageCaptchaPostProcessor.afterGenerateCaptchaImage error, [" + processor.getClass() + "]", e);
|
||||
}
|
||||
|
||||
+13
-5
@@ -1,20 +1,28 @@
|
||||
package cloud.tianai.captcha.generator.impl.provider;
|
||||
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.impl.StandardWordClickImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
|
||||
public class StandardWordClickImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider {
|
||||
public class CommonImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider {
|
||||
|
||||
private String type;
|
||||
private ImageCaptchaGeneratorProvider provider;
|
||||
|
||||
public CommonImageCaptchaGeneratorProvider(String type, ImageCaptchaGeneratorProvider provider) {
|
||||
this.type = type;
|
||||
this.provider = provider;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageCaptchaGenerator get(ImageCaptchaResourceManager resourceManager, ImageTransform imageTransform) {
|
||||
return new StandardWordClickImageCaptchaGenerator(resourceManager, imageTransform);
|
||||
return provider.get(resourceManager, imageTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return CaptchaTypeConstant.WORD_IMAGE_CLICK;
|
||||
return type;
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
package cloud.tianai.captcha.generator.impl.provider;
|
||||
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.impl.StandardConcatImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/5/19 15:12
|
||||
* @Description 滑动还原验证码
|
||||
*/
|
||||
public class StandardConcatImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider {
|
||||
@Override
|
||||
public ImageCaptchaGenerator get(ImageCaptchaResourceManager resourceManager, ImageTransform imageTransform) {
|
||||
return new StandardConcatImageCaptchaGenerator(resourceManager, imageTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return CaptchaTypeConstant.CONCAT;
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
package cloud.tianai.captcha.generator.impl.provider;
|
||||
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.impl.StandardRotateImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/5/19 15:14
|
||||
* @Description 旋转验证码
|
||||
*/
|
||||
public class StandardRotateImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider {
|
||||
@Override
|
||||
public ImageCaptchaGenerator get(ImageCaptchaResourceManager resourceManager, ImageTransform imageTransform) {
|
||||
return new StandardRotateImageCaptchaGenerator(resourceManager, imageTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return CaptchaTypeConstant.ROTATE;
|
||||
}
|
||||
}
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
package cloud.tianai.captcha.generator.impl.provider;
|
||||
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
||||
import cloud.tianai.captcha.generator.ImageTransform;
|
||||
import cloud.tianai.captcha.generator.impl.StandardSliderImageCaptchaGenerator;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/5/19 15:09
|
||||
* @Description 滑动验证码 生成器
|
||||
*/
|
||||
public class StandardSliderImageImageCaptchaGeneratorProvider implements ImageCaptchaGeneratorProvider {
|
||||
@Override
|
||||
public ImageCaptchaGenerator get(ImageCaptchaResourceManager resourceManager, ImageTransform imageTransform) {
|
||||
return new StandardSliderImageCaptchaGenerator(resourceManager, imageTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return CaptchaTypeConstant.SLIDER;
|
||||
}
|
||||
}
|
||||
+1
-7
@@ -6,7 +6,6 @@ import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ImageTransformData;
|
||||
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
|
||||
import cloud.tianai.captcha.generator.common.util.ImgWriter;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
@@ -60,12 +59,7 @@ public class Base64ImageTransform implements ImageTransform {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageTransformData transform(GenerateParam param,
|
||||
BufferedImage backgroundImage,
|
||||
BufferedImage templateImage,
|
||||
Object backgroundResource,
|
||||
Object templateResource,
|
||||
CustomData data) {
|
||||
public ImageTransformData transform(GenerateParam param, BufferedImage backgroundImage, BufferedImage templateImage, Object backgroundResource, Object templateResource, CustomData data) {
|
||||
ImageTransformData imageTransformData = new ImageTransformData();
|
||||
if (backgroundImage != null) {
|
||||
imageTransformData.setBackgroundImageUrl(transform(backgroundImage, param.getBackgroundFormatName()));
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package cloud.tianai.captcha.resource;
|
||||
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
@@ -3,8 +3,6 @@ package cloud.tianai.captcha.resource;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.ResourceMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
* @date 2022/5/7 9:04
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package cloud.tianai.captcha.resource.common.model.dto;
|
||||
|
||||
import cloud.tianai.captcha.resource.ResourceProvider;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@@ -19,7 +18,10 @@ public class Resource {
|
||||
public String data;
|
||||
/** 标签.*/
|
||||
private String tag;
|
||||
|
||||
/** 提示.*/
|
||||
private String tip;
|
||||
/** 扩展.*/
|
||||
private Object extra;
|
||||
public Resource(String type, String data) {
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
@@ -30,4 +32,11 @@ public class Resource {
|
||||
this.data = data;
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
public Resource(String type, String data, String tag, String tip) {
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
this.tag = tag;
|
||||
this.tip = tip;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-5
@@ -1,12 +1,10 @@
|
||||
package cloud.tianai.captcha.resource.impl;
|
||||
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.ResourceMap;
|
||||
import cloud.tianai.captcha.resource.impl.provider.URLResourceProvider;
|
||||
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||
import cloud.tianai.captcha.resource.ResourceProvider;
|
||||
import cloud.tianai.captcha.resource.ResourceStore;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.ResourceMap;
|
||||
import cloud.tianai.captcha.resource.impl.provider.ClassPathResourceProvider;
|
||||
import cloud.tianai.captcha.resource.impl.provider.FileResourceProvider;
|
||||
import cloud.tianai.captcha.resource.impl.provider.URLResourceProvider;
|
||||
@@ -15,7 +13,6 @@ import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: 天爱有情
|
||||
@@ -41,7 +38,7 @@ public class DefaultImageCaptchaResourceManager implements ImageCaptchaResourceM
|
||||
|
||||
private void init() {
|
||||
if (this.resourceStore == null) {
|
||||
this.resourceStore = new DefaultResourceStore();
|
||||
this.resourceStore = new LocalMemoryResourceStore();
|
||||
}
|
||||
// 注入一些默认的提供者
|
||||
registerResourceProvider(new URLResourceProvider());
|
||||
|
||||
+31
-49
@@ -1,5 +1,6 @@
|
||||
package cloud.tianai.captcha.resource.impl;
|
||||
|
||||
import cloud.tianai.captcha.common.constant.CommonConstant;
|
||||
import cloud.tianai.captcha.common.util.CollectionUtils;
|
||||
import cloud.tianai.captcha.common.util.ObjectUtils;
|
||||
import cloud.tianai.captcha.resource.ResourceStore;
|
||||
@@ -14,17 +15,8 @@ import java.util.concurrent.ThreadLocalRandom;
|
||||
* @date 2021/8/7 15:43
|
||||
* @Description 默认的资源存储
|
||||
*/
|
||||
public class DefaultResourceStore implements ResourceStore {
|
||||
public class LocalMemoryResourceStore implements ResourceStore {
|
||||
private static final String TYPE_TAG_SPLIT_FLAG = "|";
|
||||
/**
|
||||
* 模板资源.
|
||||
*/
|
||||
private Map<String, List<ResourceMap>> templateResourceMap = new HashMap<>(2);
|
||||
|
||||
/**
|
||||
* resource.
|
||||
*/
|
||||
private Map<String, List<Resource>> resourceMap = new HashMap<>(2);
|
||||
|
||||
/** 用于检索 type和tag. */
|
||||
private Map<String, List<ResourceMap>> templateResourceTagMap = new HashMap<>(2);
|
||||
@@ -32,32 +24,25 @@ public class DefaultResourceStore implements ResourceStore {
|
||||
|
||||
@Override
|
||||
public void addResource(String type, Resource resource) {
|
||||
resourceMap.computeIfAbsent(type, k -> new ArrayList<>(20)).add(resource);
|
||||
// 添加tag标签字典
|
||||
if (!ObjectUtils.isEmpty(resource.getTag())) {
|
||||
resourceTagMap.computeIfAbsent(mergeTypeAndTag(type, resource.getTag()), k -> new ArrayList<>(20)).add(resource);
|
||||
if (ObjectUtils.isEmpty(resource.getTag())) {
|
||||
resource.setTag(CommonConstant.DEFAULT_TAG);
|
||||
}
|
||||
resourceTagMap.computeIfAbsent(mergeTypeAndTag(type, resource.getTag()), k -> new ArrayList<>(20)).add(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTemplate(String type, ResourceMap template) {
|
||||
templateResourceMap.computeIfAbsent(type, k -> new ArrayList<>(2)).add(template);
|
||||
// 添加tag标签字典
|
||||
if (!ObjectUtils.isEmpty(template.getTag())) {
|
||||
templateResourceTagMap.computeIfAbsent(mergeTypeAndTag(type, template.getTag()), k -> new ArrayList<>(2)).add(template);
|
||||
if (ObjectUtils.isEmpty(template.getTag())) {
|
||||
template.setTag(CommonConstant.DEFAULT_TAG);
|
||||
}
|
||||
templateResourceTagMap.computeIfAbsent(mergeTypeAndTag(type, template.getTag()), k -> new ArrayList<>(2)).add(template);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource randomGetResourceByTypeAndTag(String type, String tag) {
|
||||
List<Resource> resources;
|
||||
if (ObjectUtils.isEmpty(tag)) {
|
||||
resources = resourceMap.get(type);
|
||||
} else {
|
||||
resources = resourceTagMap.get(mergeTypeAndTag(type, tag));
|
||||
}
|
||||
List<Resource> resources = resourceTagMap.get(mergeTypeAndTag(type, tag));
|
||||
if (CollectionUtils.isEmpty(resources)) {
|
||||
throw new IllegalStateException("随机获取资源错误,store中资源为空, type:" + type);
|
||||
throw new IllegalStateException("随机获取资源错误,store中资源为空, type:" + type + ",tag:" + tag);
|
||||
}
|
||||
if (resources.size() == 1) {
|
||||
return resources.get(0);
|
||||
@@ -68,16 +53,10 @@ public class DefaultResourceStore implements ResourceStore {
|
||||
|
||||
@Override
|
||||
public ResourceMap randomGetTemplateByTypeAndTag(String type, String tag) {
|
||||
List<ResourceMap> templateList;
|
||||
if (ObjectUtils.isEmpty(tag)) {
|
||||
templateList = templateResourceMap.get(type);
|
||||
} else {
|
||||
templateList = templateResourceTagMap.get(mergeTypeAndTag(type, tag));
|
||||
}
|
||||
List<ResourceMap> templateList = templateResourceTagMap.get(mergeTypeAndTag(type, tag));
|
||||
if (CollectionUtils.isEmpty(templateList)) {
|
||||
throw new IllegalStateException("随机获取模板错误,store中模板为空, type:" + type);
|
||||
throw new IllegalStateException("随机获取模板错误,store中模板为空, type:" + type + ",tag:" + tag);
|
||||
}
|
||||
|
||||
if (templateList.size() == 1) {
|
||||
return templateList.get(0);
|
||||
}
|
||||
@@ -86,53 +65,56 @@ public class DefaultResourceStore implements ResourceStore {
|
||||
}
|
||||
|
||||
public String mergeTypeAndTag(String type, String tag) {
|
||||
if (tag == null) {
|
||||
tag = CommonConstant.DEFAULT_TAG;
|
||||
}
|
||||
return type + TYPE_TAG_SPLIT_FLAG + tag;
|
||||
}
|
||||
|
||||
|
||||
public void clearResources(String type) {
|
||||
resourceMap.remove(type);
|
||||
public void clearResources(String type, String tag) {
|
||||
resourceTagMap.remove(mergeTypeAndTag(type, tag));
|
||||
}
|
||||
|
||||
public void clearAllResources() {
|
||||
resourceMap.clear();
|
||||
resourceTagMap.clear();
|
||||
}
|
||||
|
||||
public Map<String, List<Resource>> listAllResources() {
|
||||
return resourceMap;
|
||||
return resourceTagMap;
|
||||
}
|
||||
|
||||
public List<Resource> listResourcesByType(String type) {
|
||||
return resourceMap.getOrDefault(type, Collections.emptyList());
|
||||
public List<Resource> listResourcesByType(String type, String tag) {
|
||||
return resourceTagMap.getOrDefault(mergeTypeAndTag(type, tag), Collections.emptyList());
|
||||
}
|
||||
|
||||
public int getAllResourceCount() {
|
||||
int count = 0;
|
||||
for (List<Resource> value : resourceMap.values()) {
|
||||
for (List<Resource> value : resourceTagMap.values()) {
|
||||
count += value.size();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public int getResourceCount(String type) {
|
||||
return resourceMap.getOrDefault(type, Collections.emptyList()).size();
|
||||
public int getResourceCount(String type, String tag) {
|
||||
return resourceTagMap.getOrDefault(mergeTypeAndTag(type, tag), Collections.emptyList()).size();
|
||||
}
|
||||
|
||||
|
||||
public void clearAllTemplates() {
|
||||
templateResourceMap.clear();
|
||||
templateResourceTagMap.clear();
|
||||
}
|
||||
|
||||
public void clearTemplates(String type) {
|
||||
templateResourceMap.remove(type);
|
||||
public void clearTemplates(String type, String tag) {
|
||||
templateResourceTagMap.remove(mergeTypeAndTag(type, tag));
|
||||
}
|
||||
|
||||
public List<ResourceMap> listTemplatesByType(String type) {
|
||||
return templateResourceMap.getOrDefault(type, Collections.emptyList());
|
||||
public List<ResourceMap> listTemplatesByType(String type, String tag) {
|
||||
return templateResourceTagMap.getOrDefault(mergeTypeAndTag(type, tag), Collections.emptyList());
|
||||
}
|
||||
|
||||
public Map<String, List<ResourceMap>> listAllTemplates() {
|
||||
return templateResourceMap;
|
||||
public Map<String, List<ResourceMap>> listAllTemplates() {
|
||||
return templateResourceTagMap;
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
package cloud.tianai.captcha.resource.impl.provider;
|
||||
|
||||
import cloud.tianai.captcha.resource.AbstractResourceProvider;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.resource.AbstractResourceProvider;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package cloud.tianai.captcha.resource.impl.provider;
|
||||
|
||||
import cloud.tianai.captcha.resource.AbstractResourceProvider;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import cloud.tianai.captcha.resource.AbstractResourceProvider;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package cloud.tianai.captcha.resource.impl.provider;
|
||||
|
||||
import cloud.tianai.captcha.resource.AbstractResourceProvider;
|
||||
import cloud.tianai.captcha.resource.AbstractResourceProvider;
|
||||
import cloud.tianai.captcha.resource.common.model.dto.Resource;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
+7
-19
@@ -20,10 +20,10 @@ public class ImageCaptchaTrack {
|
||||
private Integer bgImageWidth;
|
||||
/** 背景图片高度. */
|
||||
private Integer bgImageHeight;
|
||||
/** 滑块图片宽度. */
|
||||
private Integer sliderImageWidth;
|
||||
/** 滑块图片高度. */
|
||||
private Integer sliderImageHeight;
|
||||
/** 模板图片宽度. */
|
||||
private Integer templateImageWidth;
|
||||
/** 模板图片高度. */
|
||||
private Integer templateImageHeight;
|
||||
/** 滑动开始时间. */
|
||||
private Date startSlidingTime;
|
||||
/** 滑动结束时间. */
|
||||
@@ -32,28 +32,16 @@ public class ImageCaptchaTrack {
|
||||
private List<Track> trackList;
|
||||
/** 扩展数据,用户传输加密数据等.*/
|
||||
private Object data;
|
||||
/**
|
||||
* 兼容一下旧版本
|
||||
*
|
||||
* @return Date
|
||||
*/
|
||||
public Date getEntSlidingTime() {
|
||||
return endSlidingTime;
|
||||
}
|
||||
public void setEntSlidingTime(Date entSlidingTime) {
|
||||
this.endSlidingTime = entSlidingTime;
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Track {
|
||||
/** x. */
|
||||
private Integer x;
|
||||
private Float x;
|
||||
/** y. */
|
||||
private Integer y;
|
||||
private Float y;
|
||||
/** 时间. */
|
||||
private Integer t;
|
||||
private Float t;
|
||||
/** 类型. */
|
||||
private String type = TrackTypeConstant.MOVE;
|
||||
}
|
||||
|
||||
@@ -2,13 +2,9 @@ package cloud.tianai.captcha.validator.impl;
|
||||
|
||||
import cloud.tianai.captcha.common.response.ApiResponse;
|
||||
import cloud.tianai.captcha.common.response.CodeDefinition;
|
||||
import cloud.tianai.captcha.common.util.CaptchaUtils;
|
||||
import cloud.tianai.captcha.common.util.CaptchaTypeClassifier;
|
||||
import cloud.tianai.captcha.common.util.CollectionUtils;
|
||||
import cloud.tianai.captcha.common.util.ObjectUtils;
|
||||
import cloud.tianai.captcha.common.util.CaptchaUtils;
|
||||
import cloud.tianai.captcha.common.util.CollectionUtils;
|
||||
import cloud.tianai.captcha.common.util.ObjectUtils;
|
||||
import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack;
|
||||
import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack;
|
||||
|
||||
import java.util.List;
|
||||
@@ -21,6 +17,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator {
|
||||
public static final CodeDefinition DEFINITION = new CodeDefinition(50001, "basic check fail");
|
||||
|
||||
public BasicCaptchaTrackValidator() {
|
||||
}
|
||||
|
||||
@@ -29,15 +26,15 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<?> beforeValid(ImageCaptchaTrack imageCaptchaTrack, Map<String, Object> sliderCaptchaValidData, Float tolerant, String type) {
|
||||
public ApiResponse<?> beforeValid(ImageCaptchaTrack imageCaptchaTrack, Map<String, Object> captchaValidData, Float tolerant, String type) {
|
||||
// 校验参数
|
||||
checkParam(imageCaptchaTrack);
|
||||
return ApiResponse.SUCCESS;
|
||||
return ApiResponse.ofSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResponse<?> afterValid(ImageCaptchaTrack imageCaptchaTrack, Map<String, Object> sliderCaptchaValidData, Float tolerant, String type) {
|
||||
if (!CaptchaUtils.isSliderCaptcha(type)) {
|
||||
public ApiResponse<?> afterValid(ImageCaptchaTrack imageCaptchaTrack, Map<String, Object> captchaValidData, Float tolerant, String type) {
|
||||
if (!CaptchaTypeClassifier.isSliderCaptcha(type)) {
|
||||
// 不是滑动验证码的话暂时跳过,点选验证码行为轨迹还没做
|
||||
return ApiResponse.ofSuccess();
|
||||
}
|
||||
@@ -125,9 +122,9 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator {
|
||||
throw new IllegalArgumentException("trackList must not be null");
|
||||
}
|
||||
for (ImageCaptchaTrack.Track track : imageCaptchaTrack.getTrackList()) {
|
||||
Integer x = track.getX();
|
||||
Integer y = track.getY();
|
||||
Integer t = track.getT();
|
||||
Float x = track.getX();
|
||||
Float y = track.getY();
|
||||
Float t = track.getT();
|
||||
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");
|
||||
|
||||
+31
-16
@@ -3,7 +3,7 @@ package cloud.tianai.captcha.validator.impl;
|
||||
import cloud.tianai.captcha.common.constant.CaptchaTypeConstant;
|
||||
import cloud.tianai.captcha.common.response.ApiResponse;
|
||||
import cloud.tianai.captcha.common.response.ApiResponseStatusConstant;
|
||||
import cloud.tianai.captcha.common.util.CaptchaUtils;
|
||||
import cloud.tianai.captcha.common.util.CaptchaTypeClassifier;
|
||||
import cloud.tianai.captcha.common.util.CollectionUtils;
|
||||
import cloud.tianai.captcha.common.util.ObjectUtils;
|
||||
import cloud.tianai.captcha.generator.common.model.dto.ClickImageCheckDefinition;
|
||||
@@ -38,15 +38,23 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
public static final String TOLERANT_KEY = "tolerant";
|
||||
/** 类型 key, 标识是哪张类型的验证码. */
|
||||
public static final String TYPE_KEY = "type";
|
||||
/** 计算当前验证码用户滑动的百分比率 - 生成时的百分比率, 多个的话取均值. */
|
||||
public static final String USER_CURRENT_PERCENTAGE_STD = "user_current_percentage_std";
|
||||
public static final String USER_CURRENT_PERCENTAGE = "user_current_percentage";
|
||||
/** 容错值. */
|
||||
@Getter
|
||||
@Setter
|
||||
public float defaultTolerant = DEFAULT_TOLERANT;
|
||||
|
||||
public SimpleImageCaptchaValidator() {
|
||||
CaptchaTypeClassifier.addSliderCaptchaType(CaptchaTypeConstant.CONCAT);
|
||||
CaptchaTypeClassifier.addSliderCaptchaType(CaptchaTypeConstant.ROTATE);
|
||||
CaptchaTypeClassifier.addSliderCaptchaType(CaptchaTypeConstant.SLIDER);
|
||||
CaptchaTypeClassifier.addClickCaptchaType(CaptchaTypeConstant.WORD_IMAGE_CLICK);
|
||||
}
|
||||
|
||||
public SimpleImageCaptchaValidator(float defaultTolerant) {
|
||||
this();
|
||||
this.defaultTolerant = defaultTolerant;
|
||||
}
|
||||
|
||||
@@ -106,10 +114,10 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
// type
|
||||
String type = (String) map.getOrDefault(TYPE_KEY, CaptchaTypeConstant.SLIDER);
|
||||
Object expand = imageCaptchaInfo.getData() == null ? null : imageCaptchaInfo.getData().getExpand();
|
||||
if (CaptchaUtils.isSliderCaptcha(type)) {
|
||||
if (CaptchaTypeClassifier.isSliderCaptcha(type)) {
|
||||
// 滑动验证码
|
||||
addPercentage(imageCaptchaInfo, map);
|
||||
} else if (CaptchaUtils.isClickCaptcha(type)) {
|
||||
} else if (CaptchaTypeClassifier.isClickCaptcha(type)) {
|
||||
// 图片点选验证码
|
||||
if (expand == null) {
|
||||
throw new IllegalArgumentException("点选验证码扩展数据转换为 List<ClickImageCheckDefinition> 失败, info=" + imageCaptchaInfo);
|
||||
@@ -139,7 +147,7 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
}
|
||||
// 添加点选验证数据
|
||||
map.put(PERCENTAGE_KEY, sb.toString());
|
||||
} else if (CaptchaUtils.isJigsawCaptcha(type)) {
|
||||
} else if (CaptchaTypeClassifier.isJigsawCaptcha(type)) {
|
||||
// 拼图验证码
|
||||
map.put(PERCENTAGE_KEY, expand);
|
||||
}
|
||||
@@ -173,7 +181,7 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
if (valid) {
|
||||
// 验证后
|
||||
response = afterValid(imageCaptchaTrack, imageCaptchaValidData, tolerant, type);
|
||||
}else {
|
||||
} else {
|
||||
// 缺口位置校验失败
|
||||
response = ApiResponse.ofMessage(ApiResponseStatusConstant.BASIC_CHECK_FAIL);
|
||||
}
|
||||
@@ -202,7 +210,7 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public ApiResponse<?> afterValid(ImageCaptchaTrack imageCaptchaTrack, Map<String, Object> captchaValidData, Float tolerant, String type) {
|
||||
public ApiResponse<?> afterValid(ImageCaptchaTrack imageCaptchaTrack, Map<String, Object> captchaValidData, Float tolerant, String type) {
|
||||
return ApiResponse.ofSuccess();
|
||||
}
|
||||
|
||||
@@ -210,13 +218,13 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
Map<String, Object> imageCaptchaValidData,
|
||||
Float tolerant,
|
||||
String type) {
|
||||
if (CaptchaUtils.isSliderCaptcha(type)) {
|
||||
if (CaptchaTypeClassifier.isSliderCaptcha(type)) {
|
||||
// 滑动类型验证码
|
||||
return doValidSliderCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type);
|
||||
} else if (CaptchaUtils.isClickCaptcha(type)) {
|
||||
} else if (CaptchaTypeClassifier.isClickCaptcha(type)) {
|
||||
// 点选类型验证码
|
||||
return doValidClickCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type);
|
||||
} else if (CaptchaUtils.isJigsawCaptcha(type)) {
|
||||
} else if (CaptchaTypeClassifier.isJigsawCaptcha(type)) {
|
||||
// 拼图类型验证码
|
||||
return doValidJigsawCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type);
|
||||
}
|
||||
@@ -237,10 +245,10 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
/**
|
||||
* 校验点选验证码
|
||||
*
|
||||
* @param imageCaptchaTrack sliderCaptchaTrack
|
||||
* @param imageCaptchaTrack sliderCaptchaTrack
|
||||
* @param imageCaptchaValidData imageCaptchaValidData
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean doValidClickCaptcha(ImageCaptchaTrack imageCaptchaTrack,
|
||||
@@ -292,10 +300,10 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
/**
|
||||
* 校验滑动验证码
|
||||
*
|
||||
* @param imageCaptchaTrack sliderCaptchaTrack
|
||||
* @param imageCaptchaTrack sliderCaptchaTrack
|
||||
* @param imageCaptchaValidData imageCaptchaValidData
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @param tolerant tolerant
|
||||
* @param type type
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean doValidSliderCaptcha(ImageCaptchaTrack imageCaptchaTrack,
|
||||
@@ -313,7 +321,14 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, Slide
|
||||
// 计算百分比
|
||||
float calcPercentage = calcPercentage(lastTrack.getX(), imageCaptchaTrack.getBgImageWidth());
|
||||
// 校验百分比
|
||||
return checkPercentage(calcPercentage, oriPercentage, tolerant);
|
||||
boolean percentage = checkPercentage(calcPercentage, oriPercentage, tolerant);
|
||||
if (percentage) {
|
||||
// 校验成功
|
||||
// 存储一下当前计算出来的值
|
||||
imageCaptchaValidData.put(USER_CURRENT_PERCENTAGE, String.valueOf(calcPercentage));
|
||||
imageCaptchaValidData.put(USER_CURRENT_PERCENTAGE_STD, String.valueOf(calcPercentage - oriPercentage));
|
||||
}
|
||||
return percentage;
|
||||
}
|
||||
|
||||
public Float getFloatParam(String key, Map<String, Object> imageCaptchaValidData) {
|
||||
|
||||
Reference in New Issue
Block a user