mirror of
https://github.com/dromara/tianai-captcha.git
synced 2026-05-07 06:04:34 +08:00
!24 创建tianai-captcha-springboot4-starter模块,以适配springboot4版本。
Merge pull request !24 from lichenpark/master
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
<module>tianai-captcha</module>
|
<module>tianai-captcha</module>
|
||||||
<module>tianai-captcha-springboot-starter</module>
|
<module>tianai-captcha-springboot-starter</module>
|
||||||
<module>tianai-captcha-solon-plugin</module>
|
<module>tianai-captcha-solon-plugin</module>
|
||||||
|
<module>tianai-captcha-springboot4-starter</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cloud.tianai.captcha</groupId>
|
||||||
|
<artifactId>tianai-captcha-parent</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>tianai-captcha-springboot4-starter</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<commons-lang3.version>3.18.0</commons-lang3.version>
|
||||||
|
</properties>
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
<version>4.0.0</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-autoconfigure-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>${commons-lang3.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cloud.tianai.captcha</groupId>
|
||||||
|
<artifactId>tianai-captcha</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<version>4.0.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>17</source>
|
||||||
|
<target>17</target>
|
||||||
|
<compilerArgument>-parameters</compilerArgument>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
package cloud.tianai.captcha.spring4.autoconfiguration;
|
||||||
|
|
||||||
|
import cloud.tianai.captcha.cache.CacheStore;
|
||||||
|
import cloud.tianai.captcha.cache.impl.LocalCacheStore;
|
||||||
|
import cloud.tianai.captcha.spring4.store.impl.RedisCacheStore;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存存储器的自动配置类
|
||||||
|
*
|
||||||
|
* @author lichenpark
|
||||||
|
*/
|
||||||
|
@AutoConfigureAfter({DataRedisAutoConfiguration.class})
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
public class CacheStoreAutoConfiguration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RedisCacheStoreConfiguration
|
||||||
|
*
|
||||||
|
* @author 天爱有情
|
||||||
|
* @since 2020/10/27 14:06
|
||||||
|
*/
|
||||||
|
@Order(1)
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
@ConditionalOnClass(StringRedisTemplate.class)
|
||||||
|
public static class RedisCacheStoreConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnBean(StringRedisTemplate.class)
|
||||||
|
@ConditionalOnMissingBean(CacheStore.class)
|
||||||
|
public CacheStore redis(StringRedisTemplate redisTemplate) {
|
||||||
|
return new RedisCacheStore(redisTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LocalCacheStoreConfiguration
|
||||||
|
*
|
||||||
|
* @author 天爱有情
|
||||||
|
* @since 2020/10/27 14:06
|
||||||
|
*/
|
||||||
|
@Order(2)
|
||||||
|
@Configuration(proxyBeanMethods = false)
|
||||||
|
public static class LocalCacheStoreConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(CacheStore.class)
|
||||||
|
public CacheStore local() {
|
||||||
|
return new LocalCacheStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
package cloud.tianai.captcha.spring4.autoconfiguration;
|
||||||
|
|
||||||
|
|
||||||
|
import cloud.tianai.captcha.application.ImageCaptchaApplication;
|
||||||
|
import cloud.tianai.captcha.application.TACBuilder;
|
||||||
|
import cloud.tianai.captcha.cache.CacheStore;
|
||||||
|
import cloud.tianai.captcha.common.util.CollectionUtils;
|
||||||
|
import cloud.tianai.captcha.generator.ImageCaptchaGenerator;
|
||||||
|
import cloud.tianai.captcha.generator.ImageTransform;
|
||||||
|
import cloud.tianai.captcha.generator.impl.transform.Base64ImageTransform;
|
||||||
|
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
|
||||||
|
import cloud.tianai.captcha.interceptor.CaptchaInterceptorGroup;
|
||||||
|
import cloud.tianai.captcha.interceptor.impl.ParamCheckCaptchaInterceptor;
|
||||||
|
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||||
|
import cloud.tianai.captcha.resource.ResourceProviders;
|
||||||
|
import cloud.tianai.captcha.resource.ResourceStore;
|
||||||
|
import cloud.tianai.captcha.resource.impl.DefaultImageCaptchaResourceManager;
|
||||||
|
import cloud.tianai.captcha.resource.impl.LocalMemoryResourceStore;
|
||||||
|
import cloud.tianai.captcha.spring4.plugins.SpringMultiImageCaptchaGenerator;
|
||||||
|
import cloud.tianai.captcha.spring4.plugins.secondary.SecondaryVerificationApplication;
|
||||||
|
import cloud.tianai.captcha.validator.ImageCaptchaValidator;
|
||||||
|
import cloud.tianai.captcha.validator.impl.SimpleImageCaptchaValidator;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Role;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 天爱有情
|
||||||
|
* @Date 2020/5/29 9:49
|
||||||
|
* @Description 滑块验证码自动装配
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Order
|
||||||
|
@Configuration
|
||||||
|
@AutoConfigureAfter(CacheStoreAutoConfiguration.class)
|
||||||
|
@EnableConfigurationProperties({SpringImageCaptchaProperties.class})
|
||||||
|
public class ImageCaptchaAutoConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ResourceStore resourceStore() {
|
||||||
|
return new LocalMemoryResourceStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ImageCaptchaResourceManager imageCaptchaResourceManager(ResourceStore resourceStore) {
|
||||||
|
ResourceProviders resourceProviders = new ResourceProviders();
|
||||||
|
return new DefaultImageCaptchaResourceManager(resourceStore, resourceProviders);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ImageTransform imageTransform() {
|
||||||
|
return new Base64ImageTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ImageCaptchaGenerator imageCaptchaTemplate(SpringImageCaptchaProperties prop,
|
||||||
|
ImageCaptchaResourceManager captchaResourceManager,
|
||||||
|
ImageTransform imageTransform,
|
||||||
|
BeanFactory beanFactory) {
|
||||||
|
return new SpringMultiImageCaptchaGenerator(captchaResourceManager, imageTransform, beanFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ImageCaptchaValidator imageCaptchaValidator() {
|
||||||
|
return new SimpleImageCaptchaValidator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public CaptchaInterceptor captchaInterceptor() {
|
||||||
|
CaptchaInterceptorGroup group = new CaptchaInterceptorGroup();
|
||||||
|
group.addInterceptor(new ParamCheckCaptchaInterceptor());
|
||||||
|
// group.addInterceptor(new BasicTrackCaptchaInterceptor());
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ImageCaptchaApplication imageCaptchaApplication(ImageCaptchaGenerator captchaGenerator,
|
||||||
|
ImageCaptchaValidator imageCaptchaValidator,
|
||||||
|
CacheStore cacheStore,
|
||||||
|
ResourceStore resourceStore,
|
||||||
|
SpringImageCaptchaProperties prop,
|
||||||
|
CaptchaInterceptor captchaInterceptor,
|
||||||
|
ApplicationContext applicationContext) {
|
||||||
|
TACBuilder tacBuilder = TACBuilder.builder(resourceStore)
|
||||||
|
.setGenerator(captchaGenerator)
|
||||||
|
.setValidator(imageCaptchaValidator)
|
||||||
|
.setCacheStore(cacheStore)
|
||||||
|
.setProp(prop)
|
||||||
|
.setInterceptor(captchaInterceptor);
|
||||||
|
|
||||||
|
if (prop.getInitDefaultResource()) {
|
||||||
|
tacBuilder.addDefaultTemplate(prop.getDefaultResourcePrefix());
|
||||||
|
}
|
||||||
|
if (!CollectionUtils.isEmpty(prop.getFontPath())) {
|
||||||
|
// 读取字体包
|
||||||
|
for (String fontPath : prop.getFontPath()) {
|
||||||
|
int index = fontPath.indexOf(":");
|
||||||
|
String[] split = index > 0 ? new String[]{fontPath.substring(0, index), fontPath.substring(index + 1)} : new String[]{"", fontPath};
|
||||||
|
String type = split[0];
|
||||||
|
String path = split[1];
|
||||||
|
tacBuilder.addFont(new cloud.tianai.captcha.resource.common.model.dto.Resource(type, path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImageCaptchaApplication target = tacBuilder.build();
|
||||||
|
if (prop.getSecondary() != null && Boolean.TRUE.equals(prop.getSecondary().getEnabled())) {
|
||||||
|
// 一个简单的二次验证
|
||||||
|
target = new SecondaryVerificationApplication(target, prop.getSecondary());
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package cloud.tianai.captcha.spring4.autoconfiguration;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class SecondaryVerificationProperties {
|
||||||
|
|
||||||
|
private Boolean enabled = false;
|
||||||
|
private Long expire = 120000L;
|
||||||
|
private String keyPrefix = "captcha:secondary";
|
||||||
|
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package cloud.tianai.captcha.spring4.autoconfiguration;
|
||||||
|
|
||||||
|
import cloud.tianai.captcha.application.ImageCaptchaProperties;
|
||||||
|
import cloud.tianai.captcha.resource.DefaultBuiltInResources;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 天爱有情
|
||||||
|
* @date 2020/10/19 18:41
|
||||||
|
* @Description 滑块验证码属性
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ConfigurationProperties(prefix = "captcha")
|
||||||
|
public class SpringImageCaptchaProperties extends ImageCaptchaProperties {
|
||||||
|
/** 是否初始化默认资源. */
|
||||||
|
private Boolean initDefaultResource = false;
|
||||||
|
/** 默认资源的位置. */
|
||||||
|
private String defaultResourcePrefix = DefaultBuiltInResources.PATH_PREFIX;
|
||||||
|
/** 字体包路径. */
|
||||||
|
private List<String> fontPath;
|
||||||
|
/** 二次验证配置. */
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private SecondaryVerificationProperties secondary;
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
package cloud.tianai.captcha.spring4.exception;
|
||||||
|
|
||||||
|
import cloud.tianai.captcha.common.exception.ImageCaptchaException;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 天爱有情
|
||||||
|
* @Date 2020/6/19 16:36
|
||||||
|
* @Description 验证码验证失败异常
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class CaptchaValidException extends ImageCaptchaException {
|
||||||
|
|
||||||
|
private String captchaType;
|
||||||
|
private Integer code;
|
||||||
|
public CaptchaValidException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public CaptchaValidException(String captchaType,String message) {
|
||||||
|
super(message);
|
||||||
|
this.captchaType = captchaType;
|
||||||
|
}
|
||||||
|
public CaptchaValidException(String captchaType,Integer code, String message) {
|
||||||
|
super(message);
|
||||||
|
this.code = code;
|
||||||
|
this.captchaType = captchaType;
|
||||||
|
}
|
||||||
|
public CaptchaValidException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CaptchaValidException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CaptchaValidException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||||
|
super(message, cause, enableSuppression, writableStackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
package cloud.tianai.captcha.spring4.plugins;
|
||||||
|
|
||||||
|
import cloud.tianai.captcha.generator.ImageCaptchaGeneratorProvider;
|
||||||
|
import cloud.tianai.captcha.generator.ImageTransform;
|
||||||
|
import cloud.tianai.captcha.generator.impl.MultiImageCaptchaGenerator;
|
||||||
|
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 天爱有情
|
||||||
|
* @date 2022/5/19 14:37
|
||||||
|
* @Description 基于spring的 多验证码生成器
|
||||||
|
*/
|
||||||
|
public class SpringMultiImageCaptchaGenerator extends MultiImageCaptchaGenerator {
|
||||||
|
private ListableBeanFactory beanFactory;
|
||||||
|
|
||||||
|
public SpringMultiImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, ImageTransform imageTransform,
|
||||||
|
BeanFactory beanFactory) {
|
||||||
|
super(imageCaptchaResourceManager, imageTransform);
|
||||||
|
this.beanFactory = (ListableBeanFactory) beanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doInit() {
|
||||||
|
super.doInit();
|
||||||
|
String[] beanNamesForType = beanFactory.getBeanNamesForType(ImageCaptchaGeneratorProvider.class);
|
||||||
|
if (!ArrayUtils.isEmpty(beanNamesForType)) {
|
||||||
|
for (String beanName : beanNamesForType) {
|
||||||
|
ImageCaptchaGeneratorProvider provider = beanFactory.getBean(beanName, ImageCaptchaGeneratorProvider.class);
|
||||||
|
addImageCaptchaGeneratorProvider(provider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
package cloud.tianai.captcha.spring4.plugins.secondary;
|
||||||
|
|
||||||
|
import cloud.tianai.captcha.application.FilterImageCaptchaApplication;
|
||||||
|
import cloud.tianai.captcha.application.ImageCaptchaApplication;
|
||||||
|
import cloud.tianai.captcha.common.AnyMap;
|
||||||
|
import cloud.tianai.captcha.common.response.ApiResponse;
|
||||||
|
import cloud.tianai.captcha.spring4.autoconfiguration.SecondaryVerificationProperties;
|
||||||
|
import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 天爱有情
|
||||||
|
* @date 2022/3/2 14:16
|
||||||
|
* @Description 二次验证
|
||||||
|
*/
|
||||||
|
public class SecondaryVerificationApplication extends FilterImageCaptchaApplication {
|
||||||
|
private SecondaryVerificationProperties prop;
|
||||||
|
|
||||||
|
public SecondaryVerificationApplication(ImageCaptchaApplication target, SecondaryVerificationProperties prop) {
|
||||||
|
super(target);
|
||||||
|
this.prop = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiResponse<?> matching(String id, ImageCaptchaTrack imageCaptchaTrack) {
|
||||||
|
ApiResponse<?> match = super.matching(id, imageCaptchaTrack);
|
||||||
|
if (match.isSuccess()) {
|
||||||
|
// 如果匹配成功, 添加二次验证记录
|
||||||
|
addSecondaryVerification(id, imageCaptchaTrack);
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二次缓存验证
|
||||||
|
* @param id id
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean secondaryVerification(String id) {
|
||||||
|
Map<String, Object> cache = target.getCacheStore().getAndRemoveCache(getKey(id));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
package cloud.tianai.captcha.spring4.store.impl;
|
||||||
|
|
||||||
|
import cloud.tianai.captcha.cache.CacheStore;
|
||||||
|
import cloud.tianai.captcha.common.AnyMap;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
|
import org.springframework.data.redis.core.script.RedisScript;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 天爱有情
|
||||||
|
* @date 2022/3/2 14:42
|
||||||
|
* @Description redis实现的缓存
|
||||||
|
*/
|
||||||
|
public class RedisCacheStore implements CacheStore {
|
||||||
|
|
||||||
|
private static final RedisScript<String> SCRIPT_GET_CACHE = new DefaultRedisScript<>("local res = redis.call('get',KEYS[1]) if res == nil then return nil else redis.call('del',KEYS[1]) return res end", String.class);
|
||||||
|
protected StringRedisTemplate redisTemplate;
|
||||||
|
private Gson gson = new Gson();
|
||||||
|
|
||||||
|
public RedisCacheStore(StringRedisTemplate redisTemplate) {
|
||||||
|
this.redisTemplate = redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnyMap getCache(String key) {
|
||||||
|
String jsonData = redisTemplate.opsForValue().get(key);
|
||||||
|
if (StringUtils.isEmpty(jsonData)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return gson.fromJson(jsonData, new TypeToken<AnyMap>() {
|
||||||
|
}.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AnyMap getAndRemoveCache(String key) {
|
||||||
|
String json = redisTemplate.execute(SCRIPT_GET_CACHE, Collections.singletonList(key));
|
||||||
|
if (org.apache.commons.lang3.StringUtils.isBlank(json)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return gson.fromJson(json, new TypeToken<AnyMap>() {
|
||||||
|
}.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setCache(String key, AnyMap data, Long expire, TimeUnit timeUnit) {
|
||||||
|
redisTemplate.opsForValue().set(key, gson.toJson(data), expire, timeUnit);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long incr(String key, long delta, Long expire, TimeUnit timeUnit) {
|
||||||
|
Long increment = redisTemplate.opsForValue().increment(key, delta);
|
||||||
|
redisTemplate.expire(key, expire, timeUnit);
|
||||||
|
return increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getLong(String key) {
|
||||||
|
String value = redisTemplate.opsForValue().get(key);
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return Long.valueOf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||||
|
cloud.tianai.captcha.spring4.autoconfiguration.CacheStoreAutoConfiguration,\
|
||||||
|
cloud.tianai.captcha.spring4.autoconfiguration.ImageCaptchaAutoConfiguration
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
cloud.tianai.captcha.spring4.autoconfiguration.CacheStoreAutoConfiguration
|
||||||
|
cloud.tianai.captcha.spring4.autoconfiguration.ImageCaptchaAutoConfiguration
|
||||||
Reference in New Issue
Block a user