diff --git a/pom.xml b/pom.xml index 23af062..a1a517a 100644 --- a/pom.xml +++ b/pom.xml @@ -12,11 +12,10 @@ tianai-captcha tianai-captcha-springboot-starter - tianai-captcha-solon-plugin - 1.5.4 + 1.5.5 1.8 true diff --git a/tianai-captcha-solon-plugin/pom.xml b/tianai-captcha-solon-plugin/pom.xml deleted file mode 100644 index 965b055..0000000 --- a/tianai-captcha-solon-plugin/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - 4.0.0 - - cloud.tianai.captcha - tianai-captcha-parent - ${revision} - - tianai-captcha-solon-plugin - tianai-captcha-solon-plugin - 行为验证码的solon插件 - https://gitee.com/tianai/tianai-captcha-solon-plugin - - - 3.5.2 - 8 - UTF-8 - - 1.8 - - true - UTF-8 - UTF-8 - - - - - - - org.noear - solon - ${solon.version} - - - - org.noear - solon-web - ${solon.version} - test - - - - cloud.tianai.captcha - tianai-captcha - ${revision} - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - -parameters - - - - - diff --git a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/XPluginImp.java b/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/XPluginImp.java deleted file mode 100644 index 3e83d9e..0000000 --- a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/XPluginImp.java +++ /dev/null @@ -1,21 +0,0 @@ -package cloud.tianai.captcha.solon; - -import cloud.tianai.captcha.solon.config.ImageCaptchaAutoConfiguration; -import cloud.tianai.captcha.solon.properties.CaptchaProperties; -import org.noear.solon.core.AppContext; -import org.noear.solon.core.Plugin; - -/** - * 插件启动类 - * @Author XT - * @Date 2024.09.03 - */ -public class XPluginImp implements Plugin { - - @Override - public void start(AppContext context) { - context.beanMake(CaptchaProperties.class); - context.beanMake(ImageCaptchaAutoConfiguration.class); - } - -} diff --git a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/config/ImageCaptchaAutoConfiguration.java b/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/config/ImageCaptchaAutoConfiguration.java deleted file mode 100644 index d5ece4b..0000000 --- a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/config/ImageCaptchaAutoConfiguration.java +++ /dev/null @@ -1,95 +0,0 @@ -package cloud.tianai.captcha.solon.config; - -import cloud.tianai.captcha.application.ImageCaptchaApplication; -import cloud.tianai.captcha.application.TACBuilder; -import cloud.tianai.captcha.cache.CacheStore; -import cloud.tianai.captcha.cache.impl.LocalCacheStore; -import cloud.tianai.captcha.resource.common.model.dto.Resource; -import cloud.tianai.captcha.solon.plugins.secondary.SecondaryVerificationApplication; -import cloud.tianai.captcha.solon.properties.CaptchaProperties; -import cloud.tianai.captcha.solon.service.CaptchaRedisCacheService; -import org.noear.solon.annotation.Bean; -import org.noear.solon.annotation.Configuration; -import org.noear.solon.annotation.Inject; - -import java.util.List; - -/** - * @Author XT - * @Date 2024.09.03 - */ -@Configuration -public class ImageCaptchaAutoConfiguration { - - @Bean - public ImageCaptchaApplication imageCaptchaApplication(CaptchaProperties captchaProperties, @Inject(required = false) CaptchaRedisCacheService cacheService) { - TACBuilder tacBuilder = TACBuilder.builder(); - tacBuilder.addDefaultTemplate(); - tacBuilder.expire("default", captchaProperties.getExpire()); - tacBuilder.prefix(captchaProperties.getPrefix()); - // 注入背景图资源 - if (captchaProperties.getResources().getAuto()) { - String[] split = captchaProperties.getResources().getAutoType().split(","); - List wordImageClickList = captchaProperties.getResources().getImages(); - for (String type : split) { - for (String path : wordImageClickList) { - tacBuilder.addResource(type, new Resource("classpath", path)); - } - } - } else { - List wordImageClickList = captchaProperties.getResources().getWORD_IMAGE_CLICK(); - if (!wordImageClickList.isEmpty()) { - for (String path : wordImageClickList) { - tacBuilder.addResource("WORD_IMAGE_CLICK", new Resource("classpath", path)); - } - } - List concatList = captchaProperties.getResources().getCONCAT(); - if (!concatList.isEmpty()) { - for (String path : concatList) { - tacBuilder.addResource("CONCAT", new Resource("classpath", path)); - } - } - List sliderList = captchaProperties.getResources().getSLIDER(); - if (!sliderList.isEmpty()) { - for (String path : sliderList) { - tacBuilder.addResource("SLIDER", new Resource("classpath", path)); - } - } - List rotateList = captchaProperties.getResources().getROTATE(); - if (!rotateList.isEmpty()) { - for (String path : rotateList) { - tacBuilder.addResource("ROTATE", new Resource("classpath", path)); - } - } - } - - // 注入字体包 - if (null != captchaProperties.getFontPath()) { - List fontPathList = captchaProperties.getFontPath(); - if (!fontPathList.isEmpty()) { - for (String path : fontPathList) { - try { - tacBuilder.addFont(new Resource("classpath", path)); - } catch (Exception e) { - throw new RuntimeException("读取字体包失败,path=" + path, e); - } - } - } - } - - CacheStore cacheStore = cacheService; - // 注入缓存器 - if (null == cacheStore) { - cacheStore = new LocalCacheStore(); - } - tacBuilder.setCacheStore(cacheStore); - ImageCaptchaApplication target = tacBuilder.build(); - - // 二次验证 - if (captchaProperties.getSecondary().getEnabled()) { - target = new SecondaryVerificationApplication(target, captchaProperties, cacheStore); - } - return target; - } - -} diff --git a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/plugins/secondary/SecondaryVerificationApplication.java b/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/plugins/secondary/SecondaryVerificationApplication.java deleted file mode 100644 index 2db90a3..0000000 --- a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/plugins/secondary/SecondaryVerificationApplication.java +++ /dev/null @@ -1,109 +0,0 @@ -package cloud.tianai.captcha.solon.plugins.secondary; - -import cloud.tianai.captcha.application.FilterImageCaptchaApplication; -import cloud.tianai.captcha.application.ImageCaptchaApplication; -import cloud.tianai.captcha.application.vo.ImageCaptchaVO; -import cloud.tianai.captcha.cache.CacheStore; -import cloud.tianai.captcha.common.AnyMap; -import cloud.tianai.captcha.common.exception.ImageCaptchaException; -import cloud.tianai.captcha.common.response.ApiResponse; -import cloud.tianai.captcha.solon.properties.CaptchaLimit; -import cloud.tianai.captcha.solon.properties.CaptchaProperties; -import cloud.tianai.captcha.solon.properties.CaptchaSecondary; -import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack; -import org.noear.solon.core.handle.Context; - -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** - * @Author XT - * @Date 2024.09.03 - */ -public class SecondaryVerificationApplication extends FilterImageCaptchaApplication { - - private final CaptchaSecondary prop; - private final CaptchaProperties captchaProperties; - private final CacheStore redisCacheService; - - public SecondaryVerificationApplication(ImageCaptchaApplication target, CaptchaProperties captchaProperties, CacheStore redisCacheService) { - super(target); - this.captchaProperties = captchaProperties; - this.prop = captchaProperties.getSecondary(); - this.redisCacheService = redisCacheService; - } - - @Override - public ApiResponse generateCaptcha(String type) { - // 检查是否每分钟超过限制 - CaptchaLimit limit = captchaProperties.getLimit(); - if (null != limit && limit.getEnable()) { - Context current = Context.current(); - String errLimitKey = getLimitKey(current, "error"); - Long errLimit = redisCacheService.getLong(errLimitKey); - if (null != errLimit && errLimit >= limit.getErrorLimit()) { - throw new ImageCaptchaException("验证次数过多,请稍后再试"); - } - String reqLimitKey = getLimitKey(current, "req"); - Long reqLimit = redisCacheService.getLong(reqLimitKey); - if (null != reqLimit && reqLimit >= limit.getReqLimit()) { - throw new ImageCaptchaException("获取验证码频繁,请稍后再试"); - } - redisCacheService.incr(reqLimitKey, 1, 60L, TimeUnit.SECONDS); - } - return super.generateCaptcha(type); - } - - @Override - public ApiResponse matching(String id, ImageCaptchaTrack imageCaptchaTrack) { - ApiResponse match = super.matching(id, imageCaptchaTrack); - if (match.isSuccess()) { - // 如果匹配成功, 添加二次验证记录 - addSecondaryVerification(id + getRemoteId(Context.current()), imageCaptchaTrack); - } else { - CaptchaLimit limit = captchaProperties.getLimit(); - if (null != limit && limit.getEnable()) { - Context current = Context.current(); - String limitKey = getLimitKey(current, "error"); - redisCacheService.incr(limitKey, 1, 60L, TimeUnit.SECONDS); - } - } - return match; - } - - /** - * 二次缓存验证 - * @param id id - * @return boolean - */ - public boolean secondaryVerification(String id) { - Map cache = target.getCacheStore().getAndRemoveCache(getKey(id + getRemoteId(Context.current()))); - return cache != null; - } - - /** - * 添加二次缓存验证记录 - * @param id id - * @param imageCaptchaTrack sliderCaptchaTrack - */ - protected void addSecondaryVerification(String id, ImageCaptchaTrack imageCaptchaTrack) { - target.getCacheStore().setCache(getKey(id), new AnyMap(), prop.getExpire(), TimeUnit.MILLISECONDS); - } - - protected String getKey(String id) { - return prop.getKeyPrefix().concat(":").concat(id); - } - - protected String getLimitKey(Context ctx, String type) { - return prop.getKeyPrefix().concat(":limit:") - .concat(type) - .concat(":") - .concat(getRemoteId(ctx)); - } - - - public static String getRemoteId(Context ctx) { - return ctx.realIp() + ctx.userAgent(); - } - -} diff --git a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaLimit.java b/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaLimit.java deleted file mode 100644 index 721088f..0000000 --- a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaLimit.java +++ /dev/null @@ -1,38 +0,0 @@ -package cloud.tianai.captcha.solon.properties; - -/** - * @Author XT - * @Date 2024.09.04 - */ -public class CaptchaLimit { - - private Boolean enable; - - private Long reqLimit; - - private Long errorLimit; - - public Boolean getEnable() { - return enable; - } - - public void setEnable(Boolean enable) { - this.enable = enable; - } - - public Long getReqLimit() { - return reqLimit; - } - - public void setReqLimit(Long reqLimit) { - this.reqLimit = reqLimit; - } - - public Long getErrorLimit() { - return errorLimit; - } - - public void setErrorLimit(Long errorLimit) { - this.errorLimit = errorLimit; - } -} diff --git a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaProperties.java b/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaProperties.java deleted file mode 100644 index 7c6dc51..0000000 --- a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaProperties.java +++ /dev/null @@ -1,93 +0,0 @@ -package cloud.tianai.captcha.solon.properties; - -import org.noear.solon.annotation.Configuration; -import org.noear.solon.annotation.Inject; - -import java.util.List; - -/** - * @Author XT - * @Date 2024.09.03 - */ -@Inject("${captcha}") -@Configuration -public class CaptchaProperties { - - /** - * redis 前缀 - */ - private String prefix; - - /** - * 有效期 - */ - private Long expire; - - /** - * 字体路径 - */ - private List fontPath; - - /** - * 资源路径 - */ - private CaptchaResource resources; - - /** - * 二次验证 - */ - private CaptchaSecondary secondary; - - /** - * 每分限流 - */ - private CaptchaLimit limit; - - public String getPrefix() { - return prefix; - } - - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - public Long getExpire() { - return expire; - } - - public void setExpire(Long expire) { - this.expire = expire; - } - - public List getFontPath() { - return fontPath; - } - - public void setFontPath(List fontPath) { - this.fontPath = fontPath; - } - - public CaptchaResource getResources() { - return resources; - } - - public void setResources(CaptchaResource resources) { - this.resources = resources; - } - - public CaptchaSecondary getSecondary() { - return secondary; - } - - public void setSecondary(CaptchaSecondary secondary) { - this.secondary = secondary; - } - - public CaptchaLimit getLimit() { - return limit; - } - - public void setLimit(CaptchaLimit limit) { - this.limit = limit; - } -} diff --git a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaResource.java b/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaResource.java deleted file mode 100644 index 07bd55c..0000000 --- a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaResource.java +++ /dev/null @@ -1,80 +0,0 @@ -package cloud.tianai.captcha.solon.properties; - -import java.util.List; - -/** - * @Author XT - * @Date 2024.09.03 - */ -public class CaptchaResource { - - private Boolean auto; - - private String autoType; - - private List images; - - private List SLIDER; - - private List WORD_IMAGE_CLICK; - - private List ROTATE; - - private List CONCAT; - - public List getSLIDER() { - return SLIDER; - } - - public void setSLIDER(List SLIDER) { - this.SLIDER = SLIDER; - } - - public List getWORD_IMAGE_CLICK() { - return WORD_IMAGE_CLICK; - } - - public void setWORD_IMAGE_CLICK(List WORD_IMAGE_CLICK) { - this.WORD_IMAGE_CLICK = WORD_IMAGE_CLICK; - } - - public List getROTATE() { - return ROTATE; - } - - public void setROTATE(List ROTATE) { - this.ROTATE = ROTATE; - } - - public List getCONCAT() { - return CONCAT; - } - - public void setCONCAT(List CONCAT) { - this.CONCAT = CONCAT; - } - - public Boolean getAuto() { - return auto; - } - - public void setAuto(Boolean auto) { - this.auto = auto; - } - - public String getAutoType() { - return autoType; - } - - public void setAutoType(String autoType) { - this.autoType = autoType; - } - - public List getImages() { - return images; - } - - public void setImages(List images) { - this.images = images; - } -} diff --git a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaSecondary.java b/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaSecondary.java deleted file mode 100644 index b821522..0000000 --- a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/properties/CaptchaSecondary.java +++ /dev/null @@ -1,38 +0,0 @@ -package cloud.tianai.captcha.solon.properties; - -/** - * @Author XT - * @Date 2024.09.03 - */ -public class CaptchaSecondary { - - private Boolean enabled; - - private Long expire; - - private String keyPrefix; - - public Boolean getEnabled() { - return enabled; - } - - public void setEnabled(Boolean enabled) { - this.enabled = enabled; - } - - public Long getExpire() { - return expire; - } - - public void setExpire(Long expire) { - this.expire = expire; - } - - public String getKeyPrefix() { - return keyPrefix; - } - - public void setKeyPrefix(String keyPrefix) { - this.keyPrefix = keyPrefix; - } -} diff --git a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/service/CaptchaRedisCacheService.java b/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/service/CaptchaRedisCacheService.java deleted file mode 100644 index 79efc89..0000000 --- a/tianai-captcha-solon-plugin/src/main/java/cloud/tianai/captcha/solon/service/CaptchaRedisCacheService.java +++ /dev/null @@ -1,7 +0,0 @@ -package cloud.tianai.captcha.solon.service; - -import cloud.tianai.captcha.cache.CacheStore; - -public interface CaptchaRedisCacheService extends CacheStore { - -}