diff --git a/pom.xml b/pom.xml index fc3576c..682c3bc 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 cloud.tianai.captcha tianai-captcha - 1.3.3.1 + 1.4.1 tianai-captcha 行为验证码 diff --git a/src/main/java/cloud/tianai/captcha/common/constant/CaptchaTypeConstant.java b/src/main/java/cloud/tianai/captcha/common/constant/CaptchaTypeConstant.java index b2f183a..ee4af2e 100644 --- a/src/main/java/cloud/tianai/captcha/common/constant/CaptchaTypeConstant.java +++ b/src/main/java/cloud/tianai/captcha/common/constant/CaptchaTypeConstant.java @@ -11,10 +11,19 @@ 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"; + + + } diff --git a/src/main/java/cloud/tianai/captcha/common/response/ApiResponse.java b/src/main/java/cloud/tianai/captcha/common/response/ApiResponse.java new file mode 100644 index 0000000..c0c2bf3 --- /dev/null +++ b/src/main/java/cloud/tianai/captcha/common/response/ApiResponse.java @@ -0,0 +1,99 @@ +package cloud.tianai.captcha.common.response; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Author: 天爱有情 + * @date 2023/4/20 9:53 + * @Description 可能是最好用的API统一返回格式类 + */ +@Data +@SuppressWarnings({"unchecked", "rawtypes"}) +public class ApiResponse implements Serializable { + + public static final ApiResponse SUCCESS; + + static { + CodeDefinition definition = ApiResponseStatusConstant.SUCCESS; + SUCCESS = new ApiResponse(definition.getCode(), definition.getMessage(), null); + } + + /** + * code码. + */ + private Integer code; + /** + * 信息. + */ + private String msg; + /** + * 成功时返回的数据. + */ + private T data; + + public ApiResponse(Integer code, String errMsg, T data) { + this.code = code; + this.msg = errMsg; + this.data = data; + } + + public ApiResponse(CodeDefinition definition, T data) { + this.code = definition.getCode(); + this.msg = definition.getMessage(); + this.data = data; + } + + public ApiResponse() { + CodeDefinition definition = ApiResponseStatusConstant.SUCCESS; + this.code = definition.getCode(); + this.msg = definition.getMessage(); + } + + public ApiResponse convert() { + ApiResponse result = new ApiResponse<>(); + result.setCode(this.getCode()); + result.setMsg(this.getMsg()); + return result; + } + + + public boolean isSuccess() { + return ApiResponseStatusConstant.SUCCESS.getCode().equals(getCode()); + } + + public static ApiResponse of(Integer code, String msg, T data) { + return new ApiResponse(code, msg, data); + } + + public static ApiResponse of(CodeDefinition definition, T data) { + return new ApiResponse(definition.getCode(), definition.getMessage(), data); + } + + public static ApiResponse ofMessage(CodeDefinition definition) { + return new ApiResponse(definition.getCode(), definition.getMessage(), null); + } + + public static ApiResponse ofError(String message) { + return new ApiResponse(ApiResponseStatusConstant.INTERNAL_SERVER_ERROR.getCode(), message, null); + } + + public static ApiResponse ofError(String message, Object obj) { + return new ApiResponse(ApiResponseStatusConstant.INTERNAL_SERVER_ERROR.getCode(), message, obj); + } + + public static ApiResponse ofCheckError(String message) { + return new ApiResponse(ApiResponseStatusConstant.NOT_VALID_PARAM.getCode(), message, null); + } + + public static ApiResponse ofSuccess(T data) { + CodeDefinition definition = ApiResponseStatusConstant.SUCCESS; + return new ApiResponse(definition.getCode(), definition.getMessage(), data); + } + + public static ApiResponse ofSuccess() { + return (ApiResponse) SUCCESS; + } + +} diff --git a/src/main/java/cloud/tianai/captcha/common/response/ApiResponseStatusConstant.java b/src/main/java/cloud/tianai/captcha/common/response/ApiResponseStatusConstant.java new file mode 100644 index 0000000..b026e36 --- /dev/null +++ b/src/main/java/cloud/tianai/captcha/common/response/ApiResponseStatusConstant.java @@ -0,0 +1,28 @@ +package cloud.tianai.captcha.common.response; + + +/** + * @Author: 天爱有情 + * @Date 2020/5/26 17:58 + * @Description 统一返回错误码, 详见 阿里巴巴开发规范 错误码列表 + *

+ * 该枚举定义了一些公共的code码,自定义code码数据需在自己业务中编写 + */ +public interface ApiResponseStatusConstant { + + /** + * 成功. + */ + CodeDefinition SUCCESS = new CodeDefinition(200, "OK"); + + CodeDefinition NOT_VALID_PARAM = new CodeDefinition(403, "无效参数"); + + CodeDefinition INTERNAL_SERVER_ERROR = new CodeDefinition(500, "未知的内部错误"); + + CodeDefinition EXPIRED = new CodeDefinition(4000, "已失效"); + + CodeDefinition BASIC_CHECK_FAIL = new CodeDefinition(4001, "基础校验失败"); + + + +} diff --git a/src/main/java/cloud/tianai/captcha/common/response/CodeDefinition.java b/src/main/java/cloud/tianai/captcha/common/response/CodeDefinition.java new file mode 100644 index 0000000..8c68bae --- /dev/null +++ b/src/main/java/cloud/tianai/captcha/common/response/CodeDefinition.java @@ -0,0 +1,17 @@ +package cloud.tianai.captcha.common.response; + +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * @Author: 天爱有情 + * @date 2022/4/13 12:37 + * @Description code 定义 + */ +@Data +@AllArgsConstructor +public class CodeDefinition { + + private Integer code; + private String message; +} diff --git a/src/main/java/cloud/tianai/captcha/common/util/CaptchaUtils.java b/src/main/java/cloud/tianai/captcha/common/util/CaptchaUtils.java index 5320f63..bdf3713 100644 --- a/src/main/java/cloud/tianai/captcha/common/util/CaptchaUtils.java +++ b/src/main/java/cloud/tianai/captcha/common/util/CaptchaUtils.java @@ -32,4 +32,13 @@ public class CaptchaUtils { 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); + } } diff --git a/src/main/java/cloud/tianai/captcha/validator/ImageCaptchaValidator.java b/src/main/java/cloud/tianai/captcha/validator/ImageCaptchaValidator.java index 7b3f091..b54722d 100644 --- a/src/main/java/cloud/tianai/captcha/validator/ImageCaptchaValidator.java +++ b/src/main/java/cloud/tianai/captcha/validator/ImageCaptchaValidator.java @@ -1,5 +1,6 @@ package cloud.tianai.captcha.validator; +import cloud.tianai.captcha.common.response.ApiResponse; import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo; import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack; @@ -12,34 +13,6 @@ import java.util.Map; */ public interface ImageCaptchaValidator { - /** - * 计算滑块要背景图的百分比,基本校验 - * - * @param pos 移动的位置 - * @param maxPos 最大可移动的位置 - * @return float - */ - float calcPercentage(Number pos, Number maxPos); - - /** - * 校验滑块百分比 - * - * @param newPercentage 用户滑动的百分比 - * @param oriPercentage 正确的滑块百分比 - * @return boolean - */ - boolean checkPercentage(Float newPercentage, Float oriPercentage); - - /** - * 校验滑块百分比 - * - * @param newPercentage 用户滑动的百分比 - * @param oriPercentage 正确的滑块百分比 - * @param tolerant 容错值 - * @return boolean - */ - boolean checkPercentage(Float newPercentage, Float oriPercentage, float tolerant); - /** * 用于生成验证码校验时需要的回传参数 * @@ -52,8 +25,8 @@ public interface ImageCaptchaValidator { * 校验用户滑动滑块是否正确 * * @param imageCaptchaTrack 包含了滑动轨迹,展示的图片宽高,滑动时间等参数 - * @param sliderCaptchaValidData generateSliderCaptchaValidData(生成的数据 - * @return boolean + * @param imageCaptchaValidData generateImageCaptchaValidData(生成的数据) + * @return ApiResponse */ - boolean valid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData); + ApiResponse valid(ImageCaptchaTrack imageCaptchaTrack, Map imageCaptchaValidData); } diff --git a/src/main/java/cloud/tianai/captcha/validator/SliderCaptchaPercentageValidator.java b/src/main/java/cloud/tianai/captcha/validator/SliderCaptchaPercentageValidator.java new file mode 100644 index 0000000..876f060 --- /dev/null +++ b/src/main/java/cloud/tianai/captcha/validator/SliderCaptchaPercentageValidator.java @@ -0,0 +1,40 @@ +package cloud.tianai.captcha.validator; + +/** + * @Author: 天爱有情 + * @date 2023/1/19 10:40 + * @Description 滑动类验证码百分比校验 + */ +public interface SliderCaptchaPercentageValidator { + + /** + * 计算滑块要背景图的百分比,基本校验 + * 用于计算滑动类验证码的缺口位置 + * + * @param pos 移动的位置 + * @param maxPos 最大可移动的位置 + * @return float + */ + float calcPercentage(Number pos, Number maxPos); + + /** + * 校验滑块百分比 + * 用于校验滑动类验证码是否滑动到缺口 + * + * @param newPercentage 用户滑动的百分比 + * @param oriPercentage 正确的滑块百分比 + * @return boolean + */ + boolean checkPercentage(Float newPercentage, Float oriPercentage); + + /** + * 校验滑块百分比 + * 用于校验滑动类验证码是否滑动到缺口 + * + * @param newPercentage 用户滑动的百分比 + * @param oriPercentage 正确的滑块百分比 + * @param tolerant 容错值 + * @return boolean + */ + boolean checkPercentage(Float newPercentage, Float oriPercentage, float tolerant); +} diff --git a/src/main/java/cloud/tianai/captcha/validator/impl/BasicCaptchaTrackValidator.java b/src/main/java/cloud/tianai/captcha/validator/impl/BasicCaptchaTrackValidator.java index 4f24c20..df93313 100644 --- a/src/main/java/cloud/tianai/captcha/validator/impl/BasicCaptchaTrackValidator.java +++ b/src/main/java/cloud/tianai/captcha/validator/impl/BasicCaptchaTrackValidator.java @@ -1,5 +1,7 @@ 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.CollectionUtils; import cloud.tianai.captcha.common.util.ObjectUtils; @@ -18,7 +20,7 @@ import java.util.Map; * @Description 基本的行为轨迹校验 */ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator { - + public static final CodeDefinition DEFINITION = new CodeDefinition(50001, "basic check fail"); public BasicCaptchaTrackValidator() { } @@ -27,17 +29,17 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator { } @Override - public boolean beforeValid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData, Float tolerant, String type) { + public ApiResponse beforeValid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData, Float tolerant, String type) { // 校验参数 checkParam(imageCaptchaTrack); - return true; + return ApiResponse.SUCCESS; } @Override - public boolean afterValid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData, Float tolerant, String type) { - if (!CaptchaUtils.isSliderCaptcha(type)){ + public ApiResponse afterValid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData, Float tolerant, String type) { + if (!CaptchaUtils.isSliderCaptcha(type)) { // 不是滑动验证码的话暂时跳过,点选验证码行为轨迹还没做 - return true; + return ApiResponse.ofSuccess(); } // 进行行为轨迹检测 long startSlidingTime = imageCaptchaTrack.getStartSlidingTime().getTime(); @@ -55,23 +57,23 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator { // 检测1 if (startSlidingTime + 300 > endSlidingTime) { - return false; + return ApiResponse.ofMessage(DEFINITION); } // 检测2 if (trackList.size() < 10 || trackList.size() > bgImageWidth * 5) { - return false; + return ApiResponse.ofMessage(DEFINITION); } // 检测3 ImageCaptchaTrack.Track firstTrack = trackList.get(0); if (firstTrack.getX() > 10 || firstTrack.getX() < -10 || firstTrack.getY() > 10 || firstTrack.getY() < -10) { - return false; + return ApiResponse.ofMessage(DEFINITION); } int check4 = 0; int check7 = 0; for (int i = 1; i < trackList.size(); i++) { ImageCaptchaTrack.Track track = trackList.get(i); - int x = track.getX(); - int y = track.getY(); + float x = track.getX(); + float y = track.getY(); // check4 if (firstTrack.getY() == y) { check4++; @@ -83,23 +85,27 @@ public class BasicCaptchaTrackValidator extends SimpleImageCaptchaValidator { // check5 ImageCaptchaTrack.Track preTrack = trackList.get(i - 1); if ((track.getX() - preTrack.getX()) > 50 || (track.getY() - preTrack.getY()) > 50) { - return false; + return ApiResponse.ofMessage(DEFINITION); } } if (check4 == trackList.size() || check7 > 200) { - return false; + return ApiResponse.ofMessage(DEFINITION); } // check6 int splitPos = (int) (trackList.size() * 0.7); ImageCaptchaTrack.Track splitPostTrack = trackList.get(splitPos - 1); - int posTime = splitPostTrack.getT(); + float posTime = splitPostTrack.getT(); float startAvgPosTime = posTime / (float) splitPos; ImageCaptchaTrack.Track lastTrack = trackList.get(trackList.size() - 1); - float endAvgPosTime = lastTrack.getT() / (float) (trackList.size() - splitPos); + double endAvgPosTime = lastTrack.getT() / (float) (trackList.size() - splitPos); - return endAvgPosTime > startAvgPosTime; + boolean check = endAvgPosTime > startAvgPosTime; + if (check) { + return ApiResponse.ofSuccess(); + } + return ApiResponse.ofMessage(DEFINITION); } public void checkParam(ImageCaptchaTrack imageCaptchaTrack) { diff --git a/src/main/java/cloud/tianai/captcha/validator/impl/SimpleImageCaptchaValidator.java b/src/main/java/cloud/tianai/captcha/validator/impl/SimpleImageCaptchaValidator.java index 8b5da06..9fccffc 100644 --- a/src/main/java/cloud/tianai/captcha/validator/impl/SimpleImageCaptchaValidator.java +++ b/src/main/java/cloud/tianai/captcha/validator/impl/SimpleImageCaptchaValidator.java @@ -1,18 +1,22 @@ 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.CollectionUtils; import cloud.tianai.captcha.common.util.ObjectUtils; import cloud.tianai.captcha.generator.common.model.dto.ClickImageCheckDefinition; import cloud.tianai.captcha.generator.common.model.dto.ImageCaptchaInfo; import cloud.tianai.captcha.validator.ImageCaptchaValidator; +import cloud.tianai.captcha.validator.SliderCaptchaPercentageValidator; import cloud.tianai.captcha.validator.common.constant.TrackTypeConstant; import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -24,7 +28,7 @@ import java.util.stream.Collectors; * @Description 基本的滑块验证校验 , 值进行基本校验, 目前只校验用户是否滑动到缺口处,不校验行为轨迹 */ @Slf4j -public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { +public class SimpleImageCaptchaValidator implements ImageCaptchaValidator, SliderCaptchaPercentageValidator { /** 默认的容错值. */ public static float DEFAULT_TOLERANT = 0.02f; @@ -34,7 +38,6 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { public static final String TOLERANT_KEY = "tolerant"; /** 类型 key, 标识是哪张类型的验证码. */ public static final String TYPE_KEY = "type"; - /** 容错值. */ @Getter @Setter @@ -136,95 +139,115 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { } // 添加点选验证数据 map.put(PERCENTAGE_KEY, sb.toString()); + } else if (CaptchaUtils.isJigsawCaptcha(type)) { + // 拼图验证码 + map.put(PERCENTAGE_KEY, expand); } } @Override - public boolean valid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData) { + public ApiResponse valid(ImageCaptchaTrack imageCaptchaTrack, Map imageCaptchaValidData) { // 读容错值 - Float tolerant = getFloatParam(TOLERANT_KEY, sliderCaptchaValidData, defaultTolerant); + Float tolerant = getFloatParam(TOLERANT_KEY, imageCaptchaValidData, defaultTolerant); // 读验证码类型 - String type = getStringParam(TYPE_KEY, sliderCaptchaValidData, CaptchaTypeConstant.SLIDER); + String type = getStringParam(TYPE_KEY, imageCaptchaValidData, CaptchaTypeConstant.SLIDER); // 验证前 // 在验证前必须读取 容错值 和验证码类型 - if (!beforeValid(imageCaptchaTrack, sliderCaptchaValidData, tolerant, type)) { - return false; + ApiResponse beforeValid = beforeValid(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); + if (!beforeValid.isSuccess()) { + return beforeValid; } Integer bgImageWidth = imageCaptchaTrack.getBgImageWidth(); if (bgImageWidth == null || bgImageWidth < 1) { // 没有背景图片宽度 - return false; + return ApiResponse.ofCheckError("验证码背景图片宽度参数错误"); } List trackList = imageCaptchaTrack.getTrackList(); if (CollectionUtils.isEmpty(trackList)) { // 没有滑动轨迹 - return false; + return ApiResponse.ofCheckError("没有解析到滑动轨迹"); } // 验证 - boolean valid = doValid(imageCaptchaTrack, sliderCaptchaValidData, tolerant, type); + ApiResponse response; + boolean valid = doValid(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); if (valid) { // 验证后 - valid = afterValid(imageCaptchaTrack, sliderCaptchaValidData, tolerant, type); + response = afterValid(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); + }else { + // 缺口位置校验失败 + response = ApiResponse.ofMessage(ApiResponseStatusConstant.BASIC_CHECK_FAIL); } - return valid; + return response; } /** * 验证前 * - * @param imageCaptchaTrack sliderCaptchaTrack - * @param sliderCaptchaValidData sliderCaptchaValidData - * @param tolerant tolerant - * @param type type + * @param imageCaptchaTrack sliderCaptchaTrack + * @param captchaValidData captchaValidData + * @param tolerant tolerant + * @param type type * @return boolean */ - public boolean beforeValid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData, Float tolerant, String type) { - return true; + public ApiResponse beforeValid(ImageCaptchaTrack imageCaptchaTrack, Map captchaValidData, Float tolerant, String type) { + return ApiResponse.ofSuccess(); } /** * 验证后 * - * @param imageCaptchaTrack sliderCaptchaTrack - * @param sliderCaptchaValidData sliderCaptchaValidData - * @param tolerant tolerant - * @param type type + * @param imageCaptchaTrack sliderCaptchaTrack + * @param captchaValidData captchaValidData + * @param tolerant tolerant + * @param type type * @return boolean */ - public boolean afterValid(ImageCaptchaTrack imageCaptchaTrack, Map sliderCaptchaValidData, Float tolerant, String type) { - return true; + public ApiResponse afterValid(ImageCaptchaTrack imageCaptchaTrack, Map captchaValidData, Float tolerant, String type) { + return ApiResponse.ofSuccess(); } public boolean doValid(ImageCaptchaTrack imageCaptchaTrack, - Map sliderCaptchaValidData, + Map imageCaptchaValidData, Float tolerant, String type) { if (CaptchaUtils.isSliderCaptcha(type)) { // 滑动类型验证码 - return doValidSliderCaptcha(imageCaptchaTrack, sliderCaptchaValidData, tolerant, type); + return doValidSliderCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); } else if (CaptchaUtils.isClickCaptcha(type)) { // 点选类型验证码 - return doValidClickCaptcha(imageCaptchaTrack, sliderCaptchaValidData, tolerant, type); + return doValidClickCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); + } else if (CaptchaUtils.isJigsawCaptcha(type)) { + // 拼图类型验证码 + return doValidJigsawCaptcha(imageCaptchaTrack, imageCaptchaValidData, tolerant, type); } // 不支持的类型 log.warn("校验验证码警告, 不支持的验证码类型:{}, 请手动扩展 cloud.tianai.captcha.validator.impl.SimpleImageCaptchaValidator.doValid 进行校验扩展", type); return false; } + public boolean doValidJigsawCaptcha(ImageCaptchaTrack imageCaptchaTrack, Map imageCaptchaValidData, Float tolerant, String type) { + if (imageCaptchaTrack.getData() == null || !(imageCaptchaTrack.getData() instanceof String)) { + throw new IllegalArgumentException("拼图验证码必须传data数据,且必须是字符串类型逗号分隔数据"); + } + String posArr = (String) imageCaptchaTrack.getData(); + String successPosStr = getStringParam(PERCENTAGE_KEY, imageCaptchaValidData, null); + return successPosStr.equals(posArr); + } + /** * 校验点选验证码 * * @param imageCaptchaTrack sliderCaptchaTrack - * @param sliderCaptchaValidData sliderCaptchaValidData + * @param imageCaptchaValidData imageCaptchaValidData * @param tolerant tolerant * @param type type * @return boolean */ public boolean doValidClickCaptcha(ImageCaptchaTrack imageCaptchaTrack, - Map sliderCaptchaValidData, + Map imageCaptchaValidData, Float tolerant, String type) { - String validStr = getStringParam(PERCENTAGE_KEY, sliderCaptchaValidData, null); + String validStr = getStringParam(PERCENTAGE_KEY, imageCaptchaValidData, null); if (ObjectUtils.isEmpty(validStr)) { return false; } @@ -241,6 +264,8 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { if (clickTrackList.size() != splitArr.length) { return false; } + StringBuilder sb = new StringBuilder(); + List percentages = new ArrayList<>(); for (int i = 0; i < splitArr.length; i++) { ImageCaptchaTrack.Track track = clickTrackList.get(i); String posStr = splitArr[i]; @@ -250,12 +275,17 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { float calcXPercentage = calcPercentage(track.getX(), imageCaptchaTrack.getBgImageWidth()); float calcYPercentage = calcPercentage(track.getY(), imageCaptchaTrack.getBgImageHeight()); - if (!checkPercentage(calcXPercentage, xPercentage, tolerant) || !checkPercentage(calcYPercentage, yPercentage, tolerant)) { return false; } + if (i > 0) { + sb.append("|"); + } + sb.append(calcXPercentage).append(",").append(calcYPercentage); + percentages.add((double) ((calcXPercentage - xPercentage) + (calcYPercentage - yPercentage))); } + // 存储一下当前计算出来的值 return true; } @@ -263,16 +293,16 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { * 校验滑动验证码 * * @param imageCaptchaTrack sliderCaptchaTrack - * @param sliderCaptchaValidData sliderCaptchaValidData + * @param imageCaptchaValidData imageCaptchaValidData * @param tolerant tolerant * @param type type * @return boolean */ public boolean doValidSliderCaptcha(ImageCaptchaTrack imageCaptchaTrack, - Map sliderCaptchaValidData, + Map imageCaptchaValidData, Float tolerant, String type) { - Float oriPercentage = getFloatParam(PERCENTAGE_KEY, sliderCaptchaValidData); + Float oriPercentage = getFloatParam(PERCENTAGE_KEY, imageCaptchaValidData); if (oriPercentage == null) { // 没读取到百分比 return false; @@ -286,12 +316,12 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { return checkPercentage(calcPercentage, oriPercentage, tolerant); } - public Float getFloatParam(String key, Map sliderCaptchaValidData) { - return getFloatParam(key, sliderCaptchaValidData, null); + public Float getFloatParam(String key, Map imageCaptchaValidData) { + return getFloatParam(key, imageCaptchaValidData, null); } - public Float getFloatParam(String key, Map sliderCaptchaValidData, Float defaultData) { - Object data = sliderCaptchaValidData.get(key); + public Float getFloatParam(String key, Map imageCaptchaValidData, Float defaultData) { + Object data = imageCaptchaValidData.get(key); if (data != null) { if (data instanceof Number) { return ((Number) data).floatValue(); @@ -301,18 +331,18 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { return Float.parseFloat((String) data); } } catch (NumberFormatException e) { - log.error("从 sliderCaptchaValidData 读取到的 " + key + "无法转换成float类型, [{}]", data); + log.error("从 imageCaptchaValidData 读取到的 " + key + "无法转换成float类型, [{}]", data); throw e; } } return defaultData; } - public String getStringParam(String key, Map sliderCaptchaValidData, String defaultData) { - if (CollectionUtils.isEmpty(sliderCaptchaValidData)) { + public String getStringParam(String key, Map imageCaptchaValidData, String defaultData) { + if (CollectionUtils.isEmpty(imageCaptchaValidData)) { return defaultData; } - Object data = sliderCaptchaValidData.get(key); + Object data = imageCaptchaValidData.get(key); if (data != null) { if (data instanceof String) { return (String) data; @@ -320,7 +350,7 @@ public class SimpleImageCaptchaValidator implements ImageCaptchaValidator { try { return String.valueOf(data); } catch (NumberFormatException e) { - log.error("从 sliderCaptchaValidData 读取到的 " + key + "无法转换成String类型, [{}]", data); + log.error("从 imageCaptchaValidData 读取到的 " + key + "无法转换成String类型, [{}]", data); throw e; } } diff --git a/src/main/test/java/example/readme/Test2.java b/src/main/test/java/example/readme/Test2.java index 5af11c8..5ffb6de 100644 --- a/src/main/test/java/example/readme/Test2.java +++ b/src/main/test/java/example/readme/Test2.java @@ -16,10 +16,10 @@ public class Test2 { // 用户传来的行为轨迹和进行校验 // - imageCaptchaTrack为前端传来的滑动轨迹数据 // - map 为生成验证码时缓存的map数据 - boolean check = sliderCaptchaValidator.valid(imageCaptchaTrack, map); - // 如果只想校验用户是否滑到指定凹槽即可,也可以使用 - // - 参数1 用户传来的百分比数据 - // - 参数2 生成滑块是真实的百分比数据 - check = sliderCaptchaValidator.checkPercentage(0.2f, percentage); +// boolean check = sliderCaptchaValidator.valid(imageCaptchaTrack, map); +// // 如果只想校验用户是否滑到指定凹槽即可,也可以使用 +// // - 参数1 用户传来的百分比数据 +// // - 参数2 生成滑块是真实的百分比数据 +// check = sliderCaptchaValidator.checkPercentage(0.2f, percentage); } }