Browse Source

!376 重构 滑块验证码实现 vue3 自动引入
Merge pull request !376 from xingyu/dev

芋道源码 2 năm trước cách đây
mục cha
commit
2a332a95f9
100 tập tin đã thay đổi với 723 bổ sung3802 xóa
  1. 10 3
      yudao-dependencies/pom.xml
  2. 0 1
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/validation/ValidationUtils.java
  3. 1 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml
  4. 4 7
      yudao-framework/yudao-spring-boot-starter-captcha/pom.xml
  5. 1 1
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java
  6. 1 4
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/core/enums/CaptchaRedisKeyConstants.java
  7. 1 2
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/core/service/RedisCaptchaServiceImpl.java
  8. 0 14
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/config/AjCaptchaAutoConfiguration.java
  9. 0 89
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/config/AjCaptchaServiceAutoConfiguration.java
  10. 0 20
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/config/AjCaptchaStorageAutoConfiguration.java
  11. 0 50
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/CaptchaBaseMapEnum.java
  12. 0 56
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/CaptchaTypeEnum.java
  13. 0 112
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/Const.java
  14. 0 68
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/RepCodeEnum.java
  15. 0 76
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/RequestModel.java
  16. 0 93
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/ResponseModel.java
  17. 0 104
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/vo/CaptchaVO.java
  18. 0 74
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/vo/PointVO.java
  19. 0 141
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/properties/AjCaptchaProperties.java
  20. 0 43
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/CaptchaCacheService.java
  21. 0 63
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/CaptchaService.java
  22. 0 269
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/AbstractCaptchaService.java
  23. 0 425
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/BlockPuzzleCaptchaServiceImpl.java
  24. 0 50
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/CaptchaCacheServiceMemImpl.java
  25. 0 58
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/CaptchaServiceFactory.java
  26. 0 321
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/ClickWordCaptchaServiceImpl.java
  27. 0 100
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/DefaultCaptchaServiceImpl.java
  28. 0 154
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/FrequencyLimitHandler.java
  29. 0 150
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/AESUtil.java
  30. 0 111
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/CacheUtil.java
  31. 0 120
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/FileCopyUtils.java
  32. 0 169
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/ImageUtils.java
  33. 0 73
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/JsonUtil.java
  34. 0 42
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/MD5Util.java
  35. 0 96
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/RandomUtils.java
  36. 0 138
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/StreamUtils.java
  37. 0 3
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaService
  38. 0 0
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/services/com.xingyuv.captcha.service.CaptchaCacheService
  39. 0 1
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  40. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/1.png
  41. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/2.png
  42. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/3.png
  43. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/4.png
  44. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/5.png
  45. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/6.png
  46. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/bg8.png
  47. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/1.png
  48. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/2.png
  49. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/3.png
  50. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/4.png
  51. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/5.png
  52. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/6.png
  53. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/1.png
  54. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/2.png
  55. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/3.png
  56. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/4.png
  57. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/5.png
  58. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/6.png
  59. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg10.png
  60. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg11.png
  61. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg12.png
  62. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg13.png
  63. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg14.png
  64. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg15.png
  65. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg16.png
  66. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg17.png
  67. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg18.png
  68. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg19.png
  69. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg20.png
  70. BIN
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/fonts/WenQuanZhengHei.ttf
  71. 0 55
      yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/fonts/license.txt
  72. 8 1
      yudao-framework/yudao-spring-boot-starter-web/pom.xml
  73. 18 11
      yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java
  74. 1 2
      yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/core/SpringFoxHandlerProviderBeanPostProcessor.java
  75. 1 5
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm
  76. 0 5
      yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm
  77. 5 16
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java
  78. 3 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
  79. 259 0
      yudao-ui-admin-vue3/.eslintrc-auto-import.json
  80. 2 1
      yudao-ui-admin-vue3/.eslintrc.js
  81. 43 21
      yudao-ui-admin-vue3/build/vite/index.ts
  82. 1 0
      yudao-ui-admin-vue3/build/vite/optimize.ts
  83. 0 18
      yudao-ui-admin-vue3/build/vite/styleImport.ts
  84. 13 11
      yudao-ui-admin-vue3/package.json
  85. 290 250
      yudao-ui-admin-vue3/pnpm-lock.yaml
  86. 0 2
      yudao-ui-admin-vue3/src/App.vue
  87. 1 1
      yudao-ui-admin-vue3/src/api/login/index.ts
  88. 1 3
      yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue
  89. 1 4
      yudao-ui-admin-vue3/src/components/ContentDetailWrap/src/ContentDetailWrap.vue
  90. 1 1
      yudao-ui-admin-vue3/src/components/CountTo/src/CountTo.vue
  91. 2 15
      yudao-ui-admin-vue3/src/components/Crontab/src/Crontab.vue
  92. 0 4
      yudao-ui-admin-vue3/src/components/Cropper/src/CopperModal.vue
  93. 2 11
      yudao-ui-admin-vue3/src/components/Cropper/src/Cropper.vue
  94. 1 2
      yudao-ui-admin-vue3/src/components/Cropper/src/CropperAvatar.vue
  95. 2 3
      yudao-ui-admin-vue3/src/components/Descriptions/src/Descriptions.vue
  96. 0 2
      yudao-ui-admin-vue3/src/components/Dialog/src/Dialog.vue
  97. 48 51
      yudao-ui-admin-vue3/src/components/DictTag/src/DictTag.vue
  98. 1 1
      yudao-ui-admin-vue3/src/components/Echart/src/Echart.vue
  99. 1 1
      yudao-ui-admin-vue3/src/components/Editor/src/Editor.vue
  100. 0 0
      yudao-ui-admin-vue3/src/components/Error/src/Error.vue

+ 10 - 3
yudao-dependencies/pom.xml

@@ -18,7 +18,7 @@
         <!-- 统一依赖管理 -->
         <spring.boot.version>2.7.7</spring.boot.version>
         <!-- Web 相关 -->
-        <knife4j.version>3.0.3</knife4j.version>
+        <knife4j.version>4.0.0</knife4j.version>
         <swagger-annotations.version>1.6.8</swagger-annotations.version>
         <servlet.versoin>2.5</servlet.versoin>
         <!-- DB 相关 -->
@@ -41,6 +41,7 @@
         <!-- Bpm 工作流相关 -->
         <flowable.version>6.8.0</flowable.version>
         <!-- 工具类相关 -->
+        <captcha-plus.version>1.0.1</captcha-plus.version>
         <jsoup.version>1.15.3</jsoup.version>
         <lombok.version>1.18.24</lombok.version>
         <mapstruct.version>1.5.3.Final</mapstruct.version>
@@ -63,7 +64,7 @@
         <minio.version>8.5.1</minio.version>
         <aliyun-java-sdk-core.version>4.6.3</aliyun-java-sdk-core.version>
         <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
-        <tencentcloud-sdk-java.version>3.1.667</tencentcloud-sdk-java.version>
+        <tencentcloud-sdk-java.version>3.1.676</tencentcloud-sdk-java.version>
         <justauth.version>1.4.0</justauth.version>
         <jimureport.version>1.5.6</jimureport.version>
         <xercesImpl.version>2.12.2</xercesImpl.version>
@@ -166,7 +167,7 @@
 
             <dependency>
                 <groupId>com.github.xiaoymin</groupId>
-                <artifactId>knife4j-spring-boot-starter</artifactId>
+                <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
                 <version>${knife4j.version}</version>
                 <exclusions>
                     <exclusion>
@@ -512,6 +513,12 @@
             </dependency>
 
             <dependency>
+                <groupId>com.xingyuv</groupId>
+                <artifactId>spring-boot-starter-captcha-plus</artifactId>
+                <version>${captcha-plus.version}</version>
+            </dependency>
+
+            <dependency>
                 <groupId>org.lionsoul</groupId>
                 <artifactId>ip2region</artifactId>
                 <version>${ip2region.version}</version>

+ 0 - 1
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/validation/ValidationUtils.java

@@ -1,7 +1,6 @@
 package cn.iocoder.yudao.framework.common.util.validation;
 
 import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.StrUtil;
 import org.springframework.util.StringUtils;
 
 import javax.validation.ConstraintViolation;

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/pom.xml

@@ -52,7 +52,7 @@
         <dependency>
             <groupId>com.alipay.sdk</groupId>
             <artifactId>alipay-sdk-java</artifactId>
-            <version>4.35.9.ALL</version>
+            <version>4.35.32.ALL</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.bouncycastle</groupId>

+ 4 - 7
yudao-framework/yudao-spring-boot-starter-captcha/pom.xml

@@ -17,17 +17,14 @@
     </description>
 
     <dependencies>
-        <!-- Spring 核心 -->
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
-            <scope>provided</scope>
+            <groupId>com.xingyuv</groupId>
+            <artifactId>spring-boot-starter-captcha-plus</artifactId>
         </dependency>
-
+        <!-- Spring 核心 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-            <scope>provided</scope>
+            <artifactId>spring-boot-starter</artifactId>
         </dependency>
 
         <!-- DB 相关 -->

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/config/YudaoCaptchaConfiguration.java

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.captcha.config;
 import cn.hutool.core.util.ClassUtil;
 import cn.iocoder.yudao.framework.captcha.core.enums.CaptchaRedisKeyConstants;
 import cn.iocoder.yudao.framework.captcha.core.service.RedisCaptchaServiceImpl;
-import com.anji.captcha.service.CaptchaCacheService;
+import com.xingyuv.captcha.service.CaptchaCacheService;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
 import org.springframework.context.annotation.Bean;
 import org.springframework.data.redis.core.StringRedisTemplate;

+ 1 - 4
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/core/enums/CaptchaRedisKeyConstants.java

@@ -1,13 +1,10 @@
 package cn.iocoder.yudao.framework.captcha.core.enums;
 
 import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
-import com.anji.captcha.model.vo.PointVO;
-import org.redisson.api.RLock;
+import com.xingyuv.captcha.model.vo.PointVO;
 
 import java.time.Duration;
-import java.util.Map;
 
-import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.HASH;
 import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
 
 /**

+ 1 - 2
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/cn/iocoder/yudao/framework/captcha/core/service/RedisCaptchaServiceImpl.java

@@ -1,9 +1,8 @@
 package cn.iocoder.yudao.framework.captcha.core.service;
 
-import com.anji.captcha.service.CaptchaCacheService;
+import com.xingyuv.captcha.service.CaptchaCacheService;
 import lombok.AllArgsConstructor;
 import lombok.NoArgsConstructor;
-import lombok.RequiredArgsConstructor;
 import org.springframework.data.redis.core.StringRedisTemplate;
 
 import javax.annotation.Resource;

+ 0 - 14
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/config/AjCaptchaAutoConfiguration.java

@@ -1,14 +0,0 @@
-package com.anji.captcha.config;
-
-import com.anji.captcha.properties.AjCaptchaProperties;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-
-@Configuration
-@EnableConfigurationProperties(AjCaptchaProperties.class)
-@ComponentScan("com.anji.captcha")
-@Import({AjCaptchaServiceAutoConfiguration.class, AjCaptchaStorageAutoConfiguration.class})
-public class AjCaptchaAutoConfiguration {
-}

+ 0 - 89
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/config/AjCaptchaServiceAutoConfiguration.java

@@ -1,89 +0,0 @@
-package com.anji.captcha.config;
-
-import cn.hutool.core.util.StrUtil;
-import com.anji.captcha.model.common.Const;
-import com.anji.captcha.properties.AjCaptchaProperties;
-import com.anji.captcha.service.CaptchaService;
-import com.anji.captcha.service.impl.CaptchaServiceFactory;
-import com.anji.captcha.util.ImageUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
-import org.springframework.core.io.support.ResourcePatternResolver;
-import org.springframework.util.Base64Utils;
-import org.springframework.util.FileCopyUtils;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-@Slf4j
-@Configuration
-public class AjCaptchaServiceAutoConfiguration {
-
-    @Bean
-    @ConditionalOnMissingBean
-    public CaptchaService captchaService(AjCaptchaProperties prop) {
-        log.info("自定义配置项:{}", prop.toString());
-        Properties config = new Properties();
-        config.put(Const.CAPTCHA_CACHETYPE, prop.getCacheType().name());
-        config.put(Const.CAPTCHA_WATER_MARK, prop.getWaterMark());
-        config.put(Const.CAPTCHA_FONT_TYPE, prop.getFontType());
-        config.put(Const.CAPTCHA_TYPE, prop.getType().getCodeValue());
-        config.put(Const.CAPTCHA_INTERFERENCE_OPTIONS, prop.getInterferenceOptions());
-        config.put(Const.ORIGINAL_PATH_JIGSAW, prop.getJigsaw());
-        config.put(Const.ORIGINAL_PATH_PIC_CLICK, prop.getPicClick());
-        config.put(Const.CAPTCHA_SLIP_OFFSET, prop.getSlipOffset());
-        config.put(Const.CAPTCHA_AES_STATUS, String.valueOf(prop.getAesStatus()));
-        config.put(Const.CAPTCHA_WATER_FONT, prop.getWaterFont());
-        config.put(Const.CAPTCHA_CACAHE_MAX_NUMBER, prop.getCacheNumber());
-        config.put(Const.CAPTCHA_TIMING_CLEAR_SECOND, prop.getTimingClear());
-
-        config.put(Const.HISTORY_DATA_CLEAR_ENABLE, prop.isHistoryDataClearEnable() ? "1" : "0");
-
-        config.put(Const.REQ_FREQUENCY_LIMIT_ENABLE, prop.getReqFrequencyLimitEnable() ? "1" : "0");
-        config.put(Const.REQ_GET_LOCK_LIMIT, prop.getReqGetLockLimit() + "");
-        config.put(Const.REQ_GET_LOCK_SECONDS, prop.getReqGetLockSeconds() + "");
-        config.put(Const.REQ_GET_MINUTE_LIMIT, prop.getReqGetMinuteLimit() + "");
-        config.put(Const.REQ_CHECK_MINUTE_LIMIT, prop.getReqCheckMinuteLimit() + "");
-        config.put(Const.REQ_VALIDATE_MINUTE_LIMIT, prop.getReqVerifyMinuteLimit() + "");
-
-        config.put(Const.CAPTCHA_FONT_SIZE, prop.getFontSize() + "");
-        config.put(Const.CAPTCHA_FONT_STYLE, prop.getFontStyle() + "");
-        config.put(Const.CAPTCHA_WORD_COUNT, prop.getClickWordCount() + "");
-
-        if ((StrUtil.isNotBlank(prop.getJigsaw()) && prop.getJigsaw().startsWith("classpath:"))
-                || (StrUtil.isNotBlank(prop.getPicClick()) && prop.getPicClick().startsWith("classpath:"))) {
-            //自定义resources目录下初始化底图
-            config.put(Const.CAPTCHA_INIT_ORIGINAL, "true");
-            initializeBaseMap(prop.getJigsaw(), prop.getPicClick());
-        }
-        return CaptchaServiceFactory.getInstance(config);
-    }
-
-    private static void initializeBaseMap(String jigsaw, String picClick) {
-        ImageUtils.cacheBootImage(getResourcesImagesFile(jigsaw + "/original/*.png"),
-                getResourcesImagesFile(jigsaw + "/slidingBlock/*.png"),
-                getResourcesImagesFile(picClick + "/*.png"));
-    }
-
-    public static Map<String, String> getResourcesImagesFile(String path) {
-        Map<String, String> imgMap = new HashMap<>();
-        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
-        try {
-            Resource[] resources = resolver.getResources(path);
-            for (Resource resource : resources) {
-                byte[] bytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
-                String string = Base64Utils.encodeToString(bytes);
-                String filename = resource.getFilename();
-                imgMap.put(filename, string);
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return imgMap;
-    }
-}

+ 0 - 20
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/config/AjCaptchaStorageAutoConfiguration.java

@@ -1,20 +0,0 @@
-package com.anji.captcha.config;
-
-import com.anji.captcha.properties.AjCaptchaProperties;
-import com.anji.captcha.service.CaptchaCacheService;
-import com.anji.captcha.service.impl.CaptchaServiceFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * 存储策略自动配置.
- */
-@Configuration
-public class AjCaptchaStorageAutoConfiguration {
-
-    @Bean(name = "AjCaptchaCacheService")
-    public CaptchaCacheService captchaCacheService(AjCaptchaProperties ajCaptchaProperties) {
-        // 缓存类型redis/local/....
-        return CaptchaServiceFactory.getCache(ajCaptchaProperties.getCacheType().name());
-    }
-}

+ 0 - 50
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/CaptchaBaseMapEnum.java

@@ -1,50 +0,0 @@
-package com.anji.captcha.model.common;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * 底图类型枚举
- */
-@Getter
-@AllArgsConstructor
-public enum CaptchaBaseMapEnum {
-    ORIGINAL("ORIGINAL", "滑动拼图底图"),
-    SLIDING_BLOCK("SLIDING_BLOCK", "滑动拼图滑块底图"),
-    PIC_CLICK("PIC_CLICK", "文字点选底图");
-
-    private final String codeValue;
-    private final String codeDesc;
-
-    //根据codeValue获取枚举
-    public static CaptchaBaseMapEnum parseFromCodeValue(String codeValue) {
-        for (CaptchaBaseMapEnum e : CaptchaBaseMapEnum.values()) {
-            if (e.codeValue.equals(codeValue)) {
-                return e;
-            }
-        }
-        return null;
-    }
-
-    //根据codeValue获取描述
-    public static String getCodeDescByCodeBalue(String codeValue) {
-        CaptchaBaseMapEnum enumItem = parseFromCodeValue(codeValue);
-        return enumItem == null ? "" : enumItem.getCodeDesc();
-    }
-
-    //验证codeValue是否有效
-    public static boolean validateCodeValue(String codeValue) {
-        return parseFromCodeValue(codeValue) != null;
-    }
-
-    //列出所有值字符串
-    public static String getString() {
-        StringBuffer buffer = new StringBuffer();
-        for (CaptchaBaseMapEnum e : CaptchaBaseMapEnum.values()) {
-            buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", ");
-        }
-        buffer.deleteCharAt(buffer.lastIndexOf(","));
-        return buffer.toString().trim();
-    }
-
-}

+ 0 - 56
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/CaptchaTypeEnum.java

@@ -1,56 +0,0 @@
-package com.anji.captcha.model.common;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-@Getter
-@AllArgsConstructor
-public enum CaptchaTypeEnum {
-    /**
-     * 滑块拼图.
-     */
-    BLOCKPUZZLE("blockPuzzle", "滑块拼图"),
-    /**
-     * 文字点选.
-     */
-    CLICKWORD("clickWord", "文字点选"),
-    /**
-     * 默认.
-     */
-    DEFAULT("default", "默认");
-
-    private final String codeValue;
-    private final String codeDesc;
-
-    //根据codeValue获取枚举
-    public static CaptchaTypeEnum parseFromCodeValue(String codeValue) {
-        for (CaptchaTypeEnum e : CaptchaTypeEnum.values()) {
-            if (e.codeValue.equals(codeValue)) {
-                return e;
-            }
-        }
-        return null;
-    }
-
-    //根据codeValue获取描述
-    public static String getCodeDescByCodeBalue(String codeValue) {
-        CaptchaTypeEnum enumItem = parseFromCodeValue(codeValue);
-        return enumItem == null ? "" : enumItem.getCodeDesc();
-    }
-
-    //验证codeValue是否有效
-    public static boolean validateCodeValue(String codeValue) {
-        return parseFromCodeValue(codeValue) != null;
-    }
-
-    //列出所有值字符串
-    public static String getString() {
-        StringBuilder buffer = new StringBuilder();
-        for (CaptchaTypeEnum e : CaptchaTypeEnum.values()) {
-            buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", ");
-        }
-        buffer.deleteCharAt(buffer.lastIndexOf(","));
-        return buffer.toString().trim();
-    }
-
-}

+ 0 - 112
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/Const.java

@@ -1,112 +0,0 @@
-package com.anji.captcha.model.common;
-
-/***
- * @author wongbin
- */
-public interface Const {
-
-    /**
-     * 滑块底图路径
-     */
-    String ORIGINAL_PATH_JIGSAW = "captcha.captchaOriginalPath.jigsaw";
-
-    /***
-     *点选底图路径
-     */
-    String ORIGINAL_PATH_PIC_CLICK = "captcha.captchaOriginalPath.pic-click";
-
-    /**
-     * 缓存local/redis...
-     */
-    String CAPTCHA_CACHETYPE = "captcha.cacheType";
-
-    /**
-     * 右下角水印文字(我的水印)
-     */
-    String CAPTCHA_WATER_MARK = "captcha.water.mark";
-
-    /**
-     * 点选文字验证码的文字字体(宋体)
-     */
-    String CAPTCHA_FONT_TYPE = "captcha.font.type";
-    String CAPTCHA_FONT_STYLE = "captcha.font.style";
-    String CAPTCHA_FONT_SIZE = "captcha.font.size";
-
-    /**
-     * 验证码类型default两种都实例化。
-     */
-    String CAPTCHA_TYPE = "captcha.type";
-
-    /**
-     * 滑动干扰项(0/1/2)
-     */
-    String CAPTCHA_INTERFERENCE_OPTIONS = "captcha.interference.options";
-
-    /**
-     * 底图自定义初始化
-     */
-    String CAPTCHA_INIT_ORIGINAL = "captcha.init.original";
-
-    /**
-     * 滑动误差偏移量
-     */
-    String CAPTCHA_SLIP_OFFSET = "captcha.slip.offset";
-
-    /**
-     * aes加密开关
-     */
-    String CAPTCHA_AES_STATUS = "captcha.aes.status";
-
-    /**
-     * 右下角水印字体(宋体)
-     */
-    String CAPTCHA_WATER_FONT = "captcha.water.font";
-
-    /**
-     * local缓存的阈值
-     */
-    String CAPTCHA_CACAHE_MAX_NUMBER = "captcha.cache.number";
-
-    /**
-     * 定时清理过期local缓存,秒
-     */
-    String CAPTCHA_TIMING_CLEAR_SECOND = "captcha.timing.clear";
-
-    /**
-     * 历史资源清除开关 0禁用,1 开启
-     */
-    String HISTORY_DATA_CLEAR_ENABLE = "captcha.history.data.clear.enable";
-
-    /**
-     * 接口限流开关 0禁用 1启用
-     */
-    String REQ_FREQUENCY_LIMIT_ENABLE = "captcha.req.frequency.limit.enable";
-
-    /**
-     * get 接口 一分钟请求次数限制
-     */
-    String REQ_GET_MINUTE_LIMIT = "captcha.req.get.minute.limit";
-
-    /**
-     * 验证失败后,get接口锁定时间
-     */
-    String REQ_GET_LOCK_LIMIT = "captcha.req.get.lock.limit";
-    /**
-     * 验证失败后,get接口锁定时间
-     */
-    String REQ_GET_LOCK_SECONDS = "captcha.req.get.lock.seconds";
-
-    /**
-     * verify 接口 一分钟请求次数限制
-     */
-    String REQ_VALIDATE_MINUTE_LIMIT = "captcha.req.verify.minute.limit";
-    /**
-     * check接口 一分钟请求次数限制
-     */
-    String REQ_CHECK_MINUTE_LIMIT = "captcha.req.check.minute.limit";
-
-    /***
-     * 点选文字个数
-     */
-    String CAPTCHA_WORD_COUNT = "captcha.word.count";
-}

+ 0 - 68
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/RepCodeEnum.java

@@ -1,68 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.model.common;
-
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-import java.text.MessageFormat;
-
-/**
- * 返回应答码
- *
- * @author
- */
-@AllArgsConstructor
-@Getter
-public enum RepCodeEnum {
-
-    /**
-     * 0001 - 0099 网关应答码
-     */
-    SUCCESS("0000", "成功"),
-    ERROR("0001", "操作失败"),
-    EXCEPTION("9999", "服务器内部异常"),
-
-    BLANK_ERROR("0011", "{0}不能为空"),
-    NULL_ERROR("0011", "{0}不能为空"),
-    NOT_NULL_ERROR("0012", "{0}必须为空"),
-    NOT_EXIST_ERROR("0013", "{0}数据库中不存在"),
-    EXIST_ERROR("0014", "{0}数据库中已存在"),
-    PARAM_TYPE_ERROR("0015", "{0}类型错误"),
-    PARAM_FORMAT_ERROR("0016", "{0}格式错误"),
-
-    API_CAPTCHA_INVALID("6110", "验证码已失效,请重新获取"),
-    API_CAPTCHA_COORDINATE_ERROR("6111", "验证失败"),
-    API_CAPTCHA_ERROR("6112", "获取验证码失败,请联系管理员"),
-    API_CAPTCHA_BASEMAP_NULL("6113", "底图未初始化成功,请检查路径"),
-
-    API_REQ_LIMIT_GET_ERROR("6201", "get接口请求次数超限,请稍后再试!"),
-    API_REQ_INVALID("6206", "无效请求,请重新获取验证码"),
-    API_REQ_LOCK_GET_ERROR("6202", "接口验证失败数过多,请稍后再试"),
-    API_REQ_LIMIT_CHECK_ERROR("6204", "check接口请求次数超限,请稍后再试!"),
-    API_REQ_LIMIT_VERIFY_ERROR("6205", "verify请求次数超限!");
-    private final String code;
-    private final String desc;
-
-
-    /**
-     * 将入参fieldNames与this.desc组合成错误信息
-     * {fieldName}不能为空
-     *
-     * @param fieldNames
-     * @return
-     */
-    public ResponseModel parseError(Object... fieldNames) {
-        ResponseModel errorMessage = new ResponseModel();
-        String newDesc = MessageFormat.format(this.desc, fieldNames);
-
-        errorMessage.setRepCode(this.code);
-        errorMessage.setRepMsg(newDesc);
-        return errorMessage;
-    }
-
-}

+ 0 - 76
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/RequestModel.java

@@ -1,76 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.model.common;
-
-
-import cn.hutool.core.util.StrUtil;
-import lombok.Data;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.List;
-
-@Data
-public class RequestModel implements Serializable {
-
-    private static final long serialVersionUID = -5800786065305114784L;
-
-    /**
-     * 当前请求接口路径 /business/accessUser/login
-     */
-    private String servletPath;
-
-    /**
-     * {"reqData":{"password":"*****","userName":"admin"},"sign":"a304a7f296f565b6d2009797f68180f0","time":"1542456453355","token":""}
-     */
-    private String requestString;
-
-    /**
-     * {"password":"****","userName":"admin"}
-     */
-    private HashMap reqData;
-
-    private String token;
-
-    private Long userId;
-
-    private String userName;
-
-    private List<Long> projectList;
-
-    //拥有哪些分组
-    private List<Long> groupIdList;
-
-    private String target;
-
-    private String sign;
-
-    private String time;
-
-    private String sourceIP;
-
-    /**
-     * 校验自身参数合法性
-     *
-     * @return
-     */
-    public boolean isVaildateRequest() {
-        if (StrUtil.isBlank(sign) || StrUtil.isBlank(time)) {
-            return false;
-        }
-        return true;
-    }
-
-    public String getServletPath() {
-        return servletPath;
-    }
-
-    public void setServletPath(String servletPath) {
-        this.servletPath = servletPath;
-    }
-
-}

+ 0 - 93
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/ResponseModel.java

@@ -1,93 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.model.common;
-
-import cn.hutool.core.util.StrUtil;
-import lombok.Data;
-
-import java.io.Serializable;
-
-@Data
-public class ResponseModel implements Serializable {
-
-    private static final long serialVersionUID = 8445617032523881407L;
-
-    private String repCode;
-
-    private String repMsg;
-
-    private Object repData;
-
-    public ResponseModel() {
-        this.repCode = RepCodeEnum.SUCCESS.getCode();
-    }
-
-    public ResponseModel(RepCodeEnum repCodeEnum) {
-        this.setRepCodeEnum(repCodeEnum);
-    }
-
-    //成功
-    public static ResponseModel success() {
-        return ResponseModel.successMsg("成功");
-    }
-
-    public static ResponseModel successMsg(String message) {
-        ResponseModel responseModel = new ResponseModel();
-        responseModel.setRepMsg(message);
-        return responseModel;
-    }
-
-    public static ResponseModel successData(Object data) {
-        ResponseModel responseModel = new ResponseModel();
-        responseModel.setRepCode(RepCodeEnum.SUCCESS.getCode());
-        responseModel.setRepData(data);
-        return responseModel;
-    }
-
-    //失败
-    public static ResponseModel errorMsg(RepCodeEnum message) {
-        ResponseModel responseModel = new ResponseModel();
-        responseModel.setRepCodeEnum(message);
-        return responseModel;
-    }
-
-    public static ResponseModel errorMsg(String message) {
-        ResponseModel responseModel = new ResponseModel();
-        responseModel.setRepCode(RepCodeEnum.ERROR.getCode());
-        responseModel.setRepMsg(message);
-        return responseModel;
-    }
-
-    public static ResponseModel errorMsg(RepCodeEnum repCodeEnum, String message) {
-        ResponseModel responseModel = new ResponseModel();
-        responseModel.setRepCode(repCodeEnum.getCode());
-        responseModel.setRepMsg(message);
-        return responseModel;
-    }
-
-    public static ResponseModel exceptionMsg(String message) {
-        ResponseModel responseModel = new ResponseModel();
-        responseModel.setRepCode(RepCodeEnum.EXCEPTION.getCode());
-        responseModel.setRepMsg(RepCodeEnum.EXCEPTION.getDesc() + ": " + message);
-        return responseModel;
-    }
-
-
-    public boolean isSuccess() {
-        return StrUtil.equals(repCode, RepCodeEnum.SUCCESS.getCode());
-    }
-
-    public String getRepCode() {
-        return repCode;
-    }
-
-    public void setRepCodeEnum(RepCodeEnum repCodeEnum) {
-        this.repCode = repCodeEnum.getCode();
-        this.repMsg = repCodeEnum.getDesc();
-    }
-
-}

+ 0 - 104
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/vo/CaptchaVO.java

@@ -1,104 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.model.vo;
-
-import lombok.Data;
-
-import java.awt.*;
-import java.io.Serializable;
-import java.util.List;
-
-@Data
-public class CaptchaVO implements Serializable {
-
-    /**
-     * 验证码id(后台申请)
-     */
-    private String captchaId;
-
-    private String projectCode;
-
-    /**
-     * 验证码类型:(clickWord,blockPuzzle)
-     */
-    private String captchaType;
-
-    private String captchaOriginalPath;
-
-    private String captchaFontType;
-
-    private Integer captchaFontSize;
-
-    private String secretKey;
-
-    /**
-     * 原生图片base64
-     */
-    private String originalImageBase64;
-
-    /**
-     * 滑块点选坐标
-     */
-    private PointVO point;
-
-    /**
-     * 滑块图片base64
-     */
-    private String jigsawImageBase64;
-
-    /**
-     * 点选文字
-     */
-    private List<String> wordList;
-
-    /**
-     * 点选坐标
-     */
-    private List<Point> pointList;
-
-
-    /**
-     * 点坐标(base64加密传输)
-     */
-    private String pointJson;
-
-
-    /**
-     * UUID(每次请求的验证码唯一标识)
-     */
-    private String token;
-
-    /**
-     * 校验结果
-     */
-    private Boolean result = false;
-
-    /**
-     * 后台二次校验参数
-     */
-    private String captchaVerification;
-
-    /***
-     * 客户端UI组件id,组件初始化时设置一次,UUID
-     */
-    private String clientUid;
-    /***
-     * 客户端的请求时间,预留字段
-     */
-    private Long ts;
-
-    /***
-     * 客户端ip+userAgent
-     */
-    private String browserInfo;
-
-    public void resetClientFlag() {
-        this.browserInfo = null;
-        this.clientUid = null;
-    }
-
-}

+ 0 - 74
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/vo/PointVO.java

@@ -1,74 +0,0 @@
-package com.anji.captcha.model.vo;
-
-import lombok.Data;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.regex.Pattern;
-
-/**
- * Created by raodeming on 2020/5/16.
- */
-@Data
-public class PointVO {
-    private String secretKey;
-
-    public int x;
-
-    public int y;
-
-    public PointVO(int x, int y, String secretKey) {
-        this.secretKey = secretKey;
-        this.x = x;
-        this.y = y;
-    }
-
-    public PointVO() {
-    }
-
-    public PointVO(int x, int y) {
-        this.x = x;
-        this.y = y;
-    }
-
-    public String toJsonString() {
-        return String.format("{\"secretKey\":\"%s\",\"x\":%d,\"y\":%d}", secretKey, x, y);
-    }
-
-    public PointVO parse(String jsonStr) {
-        Map<String, Object> m = new HashMap();
-        Arrays.stream(jsonStr
-                .replaceFirst(",\\{", "\\{")
-                .replaceFirst("\\{", "")
-                .replaceFirst("\\}", "")
-                .replaceAll("\"", "")
-                .split(",")).forEach(item -> {
-            m.put(item.split(":")[0], item.split(":")[1]);
-        });
-        //PointVO d = new PointVO();
-        setX(Double.valueOf("" + m.get("x")).intValue());
-        setY(Double.valueOf("" + m.get("y")).intValue());
-        setSecretKey(m.getOrDefault("secretKey", "") + "");
-        return this;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (o == null || getClass() != o.getClass()) {
-            return false;
-        }
-        PointVO pointVO = (PointVO) o;
-        return x == pointVO.x && y == pointVO.y && Objects.equals(secretKey, pointVO.secretKey);
-    }
-
-    @Override
-    public int hashCode() {
-
-        return Objects.hash(secretKey, x, y);
-    }
-}

+ 0 - 141
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/properties/AjCaptchaProperties.java

@@ -1,141 +0,0 @@
-package com.anji.captcha.properties;
-
-import com.anji.captcha.model.common.CaptchaTypeEnum;
-import lombok.Data;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-import java.awt.*;
-
-import static com.anji.captcha.properties.AjCaptchaProperties.PREFIX;
-import static com.anji.captcha.properties.AjCaptchaProperties.StorageType.local;
-
-@Data
-@ConfigurationProperties(PREFIX)
-public class AjCaptchaProperties {
-    public static final String PREFIX = "aj.captcha";
-
-    /**
-     * 验证码类型.
-     */
-    private CaptchaTypeEnum type = CaptchaTypeEnum.DEFAULT;
-
-    /**
-     * 滑动拼图底图路径.
-     */
-    private String jigsaw = "";
-
-    /**
-     * 点选文字底图路径.
-     */
-    private String picClick = "";
-
-
-    /**
-     * 右下角水印文字(我的水印).
-     */
-    private String waterMark = "我的水印";
-
-    /**
-     * 右下角水印字体(文泉驿正黑).
-     */
-    private String waterFont = "WenQuanZhengHei.ttf";
-
-    /**
-     * 点选文字验证码的文字字体(文泉驿正黑).
-     */
-    private String fontType = "WenQuanZhengHei.ttf";
-
-    /**
-     * 校验滑动拼图允许误差偏移量(默认5像素).
-     */
-    private String slipOffset = "5";
-
-    /**
-     * aes加密坐标开启或者禁用(true|false).
-     */
-    private Boolean aesStatus = true;
-
-    /**
-     * 滑块干扰项(0/1/2)
-     */
-    private String interferenceOptions = "0";
-
-    /**
-     * local缓存的阈值
-     */
-    private String cacheNumber = "1000";
-
-    /**
-     * 定时清理过期local缓存(单位秒)
-     */
-    private String timingClear = "180";
-
-    /**
-     * 缓存类型redis/local/....
-     */
-    private StorageType cacheType = local;
-    /**
-     * 历史数据清除开关
-     */
-    private boolean historyDataClearEnable = false;
-
-    /**
-     * 一分钟内接口请求次数限制 开关
-     */
-    private boolean reqFrequencyLimitEnable = false;
-
-    /***
-     * 一分钟内check接口失败次数
-     */
-    private int reqGetLockLimit = 5;
-    /**
-     *
-     */
-    private int reqGetLockSeconds = 300;
-
-    /***
-     * get接口一分钟内限制访问数
-     */
-    private int reqGetMinuteLimit = 100;
-    private int reqCheckMinuteLimit = 100;
-    private int reqVerifyMinuteLimit = 100;
-
-    /**
-     * 点选字体样式
-     */
-    private int fontStyle = Font.BOLD;
-
-    /**
-     * 点选字体大小
-     */
-    private int fontSize = 25;
-
-    /**
-     * 点选文字个数,存在问题,暂不要使用
-     */
-    private int clickWordCount = 4;
-
-    public boolean getReqFrequencyLimitEnable() {
-        return reqFrequencyLimitEnable;
-    }
-
-    public enum StorageType {
-        /**
-         * 内存.
-         */
-        local,
-        /**
-         * redis.
-         */
-        redis,
-        /**
-         * 其他.
-         */
-        other,
-    }
-
-    public static String getPrefix() {
-        return PREFIX;
-    }
-
-}

+ 0 - 43
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/CaptchaCacheService.java

@@ -1,43 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.service;
-
-/**
- * 验证码缓存接口
- *
- * @author lide1202@hotmail.com
- * @date 2018-08-21
- */
-public interface CaptchaCacheService {
-
-    void set(String key, String value, long expiresInSeconds);
-
-    boolean exists(String key);
-
-    void delete(String key);
-
-    String get(String key);
-
-    /**
-     * 缓存类型-local/redis/memcache/..
-     * 通过java SPI机制,接入方可自定义实现类
-     *
-     * @return
-     */
-    String type();
-
-    /***
-     *
-     * @param key
-     * @param val
-     * @return
-     */
-    default Long increment(String key, long val) {
-        return 0L;
-    }
-
-}

+ 0 - 63
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/CaptchaService.java

@@ -1,63 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.service;
-
-import com.anji.captcha.model.common.ResponseModel;
-import com.anji.captcha.model.vo.CaptchaVO;
-
-import java.util.Properties;
-
-/**
- * 验证码服务接口
- *
- * @author lide1202@hotmail.com
- * @date 2020-05-12
- */
-public interface CaptchaService {
-    /**
-     * 配置初始化
-     */
-    void init(Properties config);
-
-    /**
-     * 获取验证码
-     *
-     * @param captchaVO
-     * @return
-     */
-    ResponseModel get(CaptchaVO captchaVO);
-
-    /**
-     * 核对验证码(前端)
-     *
-     * @param captchaVO
-     * @return
-     */
-    ResponseModel check(CaptchaVO captchaVO);
-
-    /**
-     * 二次校验验证码(后端)
-     *
-     * @param captchaVO
-     * @return
-     */
-    ResponseModel verification(CaptchaVO captchaVO);
-
-    /***
-     * 验证码类型
-     * 通过java SPI机制,接入方可自定义实现类,实现新的验证类型
-     * @return
-     */
-    String captchaType();
-
-    /**
-     * 历史资源清除(过期的图片文件,生成的临时图片...)
-     *
-     * @param config 配置项 控制资源清理的粒度
-     */
-    void destroy(Properties config);
-}

+ 0 - 269
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/AbstractCaptchaService.java

@@ -1,269 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.service.impl;
-
-import cn.hutool.core.util.StrUtil;
-import com.anji.captcha.model.common.Const;
-import com.anji.captcha.model.common.RepCodeEnum;
-import com.anji.captcha.model.common.ResponseModel;
-import com.anji.captcha.model.vo.CaptchaVO;
-import com.anji.captcha.service.CaptchaCacheService;
-import com.anji.captcha.service.CaptchaService;
-import com.anji.captcha.util.*;
-import lombok.extern.slf4j.Slf4j;
-
-import java.awt.*;
-import java.io.File;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.util.Base64;
-import java.util.Objects;
-import java.util.Properties;
-
-/**
- * Created by raodeming on 2019/12/25.
- */
-@Slf4j
-public abstract class AbstractCaptchaService implements CaptchaService {
-
-    protected static final String IMAGE_TYPE_PNG = "png";
-
-    protected static int HAN_ZI_SIZE = 25;
-
-    protected static int HAN_ZI_SIZE_HALF = HAN_ZI_SIZE / 2;
-    //check校验坐标
-    protected static String REDIS_CAPTCHA_KEY = "RUNNING:CAPTCHA:%s";
-
-    //后台二次校验坐标
-    protected static String REDIS_SECOND_CAPTCHA_KEY = "RUNNING:CAPTCHA:second-%s";
-
-    protected static Long EXPIRESIN_SECONDS = 2 * 60L;
-
-    protected static Long EXPIRESIN_THREE = 3 * 60L;
-
-    protected static String waterMark = "我的水印";
-
-    protected static String waterMarkFontStr = "WenQuanZhengHei.ttf";
-
-    protected Font waterMarkFont;//水印字体
-
-    protected static String slipOffset = "5";
-
-    protected static Boolean captchaAesStatus = true;
-
-    protected static String clickWordFontStr = "WenQuanZhengHei.ttf";
-
-    protected Font clickWordFont;//点选文字字体
-
-    protected static String cacheType = "local";
-
-    protected static int captchaInterferenceOptions = 0;
-
-    //判断应用是否实现了自定义缓存,没有就使用内存
-    @Override
-    public void init(final Properties config) {
-        //初始化底图
-        boolean aBoolean = Boolean.parseBoolean(config.getProperty(Const.CAPTCHA_INIT_ORIGINAL));
-        if (!aBoolean) {
-            ImageUtils.cacheImage(config.getProperty(Const.ORIGINAL_PATH_JIGSAW),
-                    config.getProperty(Const.ORIGINAL_PATH_PIC_CLICK));
-        }
-        log.info("--->>>初始化验证码底图<<<---" + captchaType());
-        waterMark = config.getProperty(Const.CAPTCHA_WATER_MARK, "我的水印");
-        slipOffset = config.getProperty(Const.CAPTCHA_SLIP_OFFSET, "5");
-        waterMarkFontStr = config.getProperty(Const.CAPTCHA_WATER_FONT, "WenQuanZhengHei.ttf");
-        captchaAesStatus = Boolean.parseBoolean(config.getProperty(Const.CAPTCHA_AES_STATUS, "true"));
-        clickWordFontStr = config.getProperty(Const.CAPTCHA_FONT_TYPE, "WenQuanZhengHei.ttf");
-        //clickWordFontStr = config.getProperty(Const.CAPTCHA_FONT_TYPE, "SourceHanSansCN-Normal.otf");
-        cacheType = config.getProperty(Const.CAPTCHA_CACHETYPE, "local");
-        captchaInterferenceOptions = Integer.parseInt(
-                config.getProperty(Const.CAPTCHA_INTERFERENCE_OPTIONS, "0"));
-
-        // 部署在linux中,如果没有安装中文字段,水印和点选文字,中文无法显示,
-        // 通过加载resources下的font字体解决,无需在linux中安装字体
-        loadWaterMarkFont();
-
-        if ("local".equals(cacheType)) {
-            log.info("初始化local缓存...");
-            CacheUtil.init(Integer.parseInt(config.getProperty(Const.CAPTCHA_CACAHE_MAX_NUMBER, "1000")),
-                    Long.parseLong(config.getProperty(Const.CAPTCHA_TIMING_CLEAR_SECOND, "180")));
-        }
-        if ("1".equals(config.getProperty(Const.HISTORY_DATA_CLEAR_ENABLE, "0"))) {
-            log.info("历史资源清除开关...开启..." + captchaType());
-            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
-                @Override
-                public void run() {
-                    destroy(config);
-                }
-            }));
-        }
-        if ("1".equals(config.getProperty(Const.REQ_FREQUENCY_LIMIT_ENABLE, "0"))) {
-            if (limitHandler == null) {
-                log.info("接口分钟内限流开关...开启...");
-                limitHandler = new FrequencyLimitHandler.DefaultLimitHandler(config, getCacheService(cacheType));
-            }
-        }
-    }
-
-    protected CaptchaCacheService getCacheService(String cacheType) {
-        return CaptchaServiceFactory.getCache(cacheType);
-    }
-
-    @Override
-    public void destroy(Properties config) {
-
-    }
-
-    private static FrequencyLimitHandler limitHandler;
-
-    @Override
-    public ResponseModel get(CaptchaVO captchaVO) {
-        if (limitHandler != null) {
-            captchaVO.setClientUid(getValidateClientId(captchaVO));
-            return limitHandler.validateGet(captchaVO);
-        }
-        return null;
-    }
-
-    @Override
-    public ResponseModel check(CaptchaVO captchaVO) {
-        if (limitHandler != null) {
-            // 验证客户端
-           /* ResponseModel ret = limitHandler.validateCheck(captchaVO);
-            if(!validatedReq(ret)){
-                return ret;
-            }
-            // 服务端参数验证*/
-            captchaVO.setClientUid(getValidateClientId(captchaVO));
-            return limitHandler.validateCheck(captchaVO);
-        }
-        return null;
-    }
-
-    @Override
-    public ResponseModel verification(CaptchaVO captchaVO) {
-        if (captchaVO == null) {
-            return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
-        }
-        if (StrUtil.isEmpty(captchaVO.getCaptchaVerification())) {
-            return RepCodeEnum.NULL_ERROR.parseError("captchaVerification");
-        }
-        if (limitHandler != null) {
-            return limitHandler.validateVerify(captchaVO);
-        }
-        return null;
-    }
-
-    protected boolean validatedReq(ResponseModel resp) {
-        return resp == null || resp.isSuccess();
-    }
-
-    protected String getValidateClientId(CaptchaVO req) {
-        // 以服务端获取的客户端标识 做识别标志
-        if (StrUtil.isNotEmpty(req.getBrowserInfo())) {
-            return MD5Util.md5(req.getBrowserInfo());
-        }
-        // 以客户端Ui组件id做识别标志
-        if (StrUtil.isNotEmpty(req.getClientUid())) {
-            return req.getClientUid();
-        }
-        return null;
-    }
-
-    protected void afterValidateFail(CaptchaVO data) {
-        if (limitHandler != null) {
-            // 验证失败 分钟内计数
-            String fails = String.format(FrequencyLimitHandler.LIMIT_KEY, "FAIL", data.getClientUid());
-            CaptchaCacheService cs = getCacheService(cacheType);
-            if (!cs.exists(fails)) {
-                cs.set(fails, "1", 60);
-            }
-            cs.increment(fails, 1);
-        }
-    }
-
-    /**
-     * 加载resources下的font字体,add by lide1202@hotmail.com
-     * 部署在linux中,如果没有安装中文字段,水印和点选文字,中文无法显示,
-     * 通过加载resources下的font字体解决,无需在linux中安装字体
-     */
-    private void loadWaterMarkFont() {
-        try {
-            if (waterMarkFontStr.toLowerCase().endsWith(".ttf") || waterMarkFontStr.toLowerCase().endsWith(".ttc")
-                    || waterMarkFontStr.toLowerCase().endsWith(".otf")) {
-                this.waterMarkFont = Font.createFont(Font.TRUETYPE_FONT,
-                                Objects.requireNonNull(getClass().getResourceAsStream("/fonts/" + waterMarkFontStr)))
-                        .deriveFont(Font.BOLD, HAN_ZI_SIZE / 2);
-            } else {
-                this.waterMarkFont = new Font(waterMarkFontStr, Font.BOLD, HAN_ZI_SIZE / 2);
-            }
-
-        } catch (Exception e) {
-            log.error("load font error:{}", e);
-        }
-    }
-
-    public static boolean base64StrToImage(String imgStr, String path) {
-        if (imgStr == null) {
-            return false;
-        }
-
-        Base64.Decoder decoder = Base64.getDecoder();
-        try {
-            // 解密
-            byte[] b = decoder.decode(imgStr);
-            // 处理数据
-            for (int i = 0; i < b.length; ++i) {
-                if (b[i] < 0) {
-                    b[i] += 256;
-                }
-            }
-            //文件夹不存在则自动创建
-            File tempFile = new File(path);
-            if (!tempFile.getParentFile().exists()) {
-                tempFile.getParentFile().mkdirs();
-            }
-            OutputStream out = Files.newOutputStream(tempFile.toPath());
-            out.write(b);
-            out.flush();
-            out.close();
-            return true;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    /**
-     * 解密前端坐标aes加密
-     *
-     * @param point
-     * @return
-     * @throws Exception
-     */
-    public static String decrypt(String point, String key) throws Exception {
-        return AESUtil.aesDecrypt(point, key);
-    }
-
-    protected static int getEnOrChLength(String s) {
-        int enCount = 0;
-        int chCount = 0;
-        for (int i = 0; i < s.length(); i++) {
-            int length = String.valueOf(s.charAt(i)).getBytes(StandardCharsets.UTF_8).length;
-            if (length > 1) {
-                chCount++;
-            } else {
-                enCount++;
-            }
-        }
-        int chOffset = (HAN_ZI_SIZE / 2) * chCount + 5;
-        int enOffset = enCount * 8;
-        return chOffset + enOffset;
-    }
-
-
-}

+ 0 - 425
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/BlockPuzzleCaptchaServiceImpl.java

@@ -1,425 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.service.impl;
-
-import cn.hutool.core.util.StrUtil;
-import com.anji.captcha.model.common.CaptchaTypeEnum;
-import com.anji.captcha.model.common.RepCodeEnum;
-import com.anji.captcha.model.common.ResponseModel;
-import com.anji.captcha.model.vo.CaptchaVO;
-import com.anji.captcha.model.vo.PointVO;
-import com.anji.captcha.util.*;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.imageio.ImageIO;
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.util.Base64;
-import java.util.Objects;
-import java.util.Properties;
-import java.util.Random;
-
-/**
- * 滑动验证码
- * <p>
- * Created by raodeming on 2019/12/25.
- */
-@Slf4j
-public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
-
-    @Override
-    public void init(Properties config) {
-        super.init(config);
-    }
-
-    @Override
-    public void destroy(Properties config) {
-        log.info("start-clear-history-data-", captchaType());
-    }
-
-    @Override
-    public String captchaType() {
-        return CaptchaTypeEnum.BLOCKPUZZLE.getCodeValue();
-    }
-
-    @Override
-    public ResponseModel get(CaptchaVO captchaVO) {
-        ResponseModel r = super.get(captchaVO);
-        if (!validatedReq(r)) {
-            return r;
-        }
-        //原生图片
-        BufferedImage originalImage = ImageUtils.getOriginal();
-        if (null == originalImage) {
-            log.error("滑动底图未初始化成功,请检查路径");
-            return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL);
-        }
-        //设置水印
-        Graphics backgroundGraphics = originalImage.getGraphics();
-        int width = originalImage.getWidth();
-        int height = originalImage.getHeight();
-        backgroundGraphics.setFont(waterMarkFont);
-        backgroundGraphics.setColor(Color.white);
-        backgroundGraphics.drawString(waterMark, width - getEnOrChLength(waterMark), height - (HAN_ZI_SIZE / 2) + 7);
-
-        //抠图图片
-        String jigsawImageBase64 = ImageUtils.getslidingBlock();
-        BufferedImage jigsawImage = ImageUtils.getBase64StrToImage(jigsawImageBase64);
-        if (null == jigsawImage) {
-            log.error("滑动底图未初始化成功,请检查路径");
-            return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL);
-        }
-        CaptchaVO captcha = pictureTemplatesCut(originalImage, jigsawImage, jigsawImageBase64);
-        if (captcha == null
-                || StrUtil.isBlank(captcha.getJigsawImageBase64())
-                || StrUtil.isBlank(captcha.getOriginalImageBase64())) {
-            return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_ERROR);
-        }
-        return ResponseModel.successData(captcha);
-    }
-
-    @Override
-    public ResponseModel check(CaptchaVO captchaVO) {
-        ResponseModel r = super.check(captchaVO);
-        if (!validatedReq(r)) {
-            return r;
-        }
-        //取坐标信息
-        String codeKey = String.format(REDIS_CAPTCHA_KEY, captchaVO.getToken());
-        if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) {
-            return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_INVALID);
-        }
-        String s = CaptchaServiceFactory.getCache(cacheType).get(codeKey);
-        //验证码只用一次,即刻失效
-        CaptchaServiceFactory.getCache(cacheType).delete(codeKey);
-        PointVO point = null;
-        PointVO point1 = null;
-        String pointJson = null;
-        try {
-            point = JsonUtil.parseObject(s, PointVO.class);
-            //aes解密
-            pointJson = decrypt(captchaVO.getPointJson(), point.getSecretKey());
-            point1 = JsonUtil.parseObject(pointJson, PointVO.class);
-        } catch (Exception e) {
-            log.error("验证码坐标解析失败", e);
-            afterValidateFail(captchaVO);
-            return ResponseModel.errorMsg(e.getMessage());
-        }
-        if (point.x - Integer.parseInt(slipOffset) > point1.x
-                || point1.x > point.x + Integer.parseInt(slipOffset)
-                || point.y != point1.y) {
-            afterValidateFail(captchaVO);
-            return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_COORDINATE_ERROR);
-        }
-        //校验成功,将信息存入缓存
-        String secretKey = point.getSecretKey();
-        String value = null;
-        try {
-            value = AESUtil.aesEncrypt(captchaVO.getToken().concat("---").concat(pointJson), secretKey);
-        } catch (Exception e) {
-            log.error("AES加密失败", e);
-            afterValidateFail(captchaVO);
-            return ResponseModel.errorMsg(e.getMessage());
-        }
-        String secondKey = String.format(REDIS_SECOND_CAPTCHA_KEY, value);
-        CaptchaServiceFactory.getCache(cacheType).set(secondKey, captchaVO.getToken(), EXPIRESIN_THREE);
-        captchaVO.setResult(true);
-        captchaVO.resetClientFlag();
-        return ResponseModel.successData(captchaVO);
-    }
-
-    @Override
-    public ResponseModel verification(CaptchaVO captchaVO) {
-        ResponseModel r = super.verification(captchaVO);
-        if (!validatedReq(r)) {
-            return r;
-        }
-        try {
-            String codeKey = String.format(REDIS_SECOND_CAPTCHA_KEY, captchaVO.getCaptchaVerification());
-            if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) {
-                return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_INVALID);
-            }
-            //二次校验取值后,即刻失效
-            CaptchaServiceFactory.getCache(cacheType).delete(codeKey);
-        } catch (Exception e) {
-            log.error("验证码坐标解析失败", e);
-            return ResponseModel.errorMsg(e.getMessage());
-        }
-        return ResponseModel.success();
-    }
-
-    /**
-     * 根据模板切图
-     *
-     * @throws Exception
-     */
-    public CaptchaVO pictureTemplatesCut(BufferedImage originalImage, BufferedImage jigsawImage, String jigsawImageBase64) {
-        try {
-            CaptchaVO dataVO = new CaptchaVO();
-
-            int originalWidth = originalImage.getWidth();
-            int originalHeight = originalImage.getHeight();
-            int jigsawWidth = jigsawImage.getWidth();
-            int jigsawHeight = jigsawImage.getHeight();
-
-            //随机生成拼图坐标
-            PointVO point = generateJigsawPoint(originalWidth, originalHeight, jigsawWidth, jigsawHeight);
-            int x = point.getX();
-            int y = point.getY();
-
-            //生成新的拼图图像
-            BufferedImage newJigsawImage = new BufferedImage(jigsawWidth, jigsawHeight, jigsawImage.getType());
-            Graphics2D graphics = newJigsawImage.createGraphics();
-
-            int bold = 5;
-            //如果需要生成RGB格式,需要做如下配置,Transparency 设置透明
-            newJigsawImage = graphics.getDeviceConfiguration().createCompatibleImage(jigsawWidth, jigsawHeight, Transparency.TRANSLUCENT);
-            // 新建的图像根据模板颜色赋值,源图生成遮罩
-            cutByTemplate(originalImage, jigsawImage, newJigsawImage, x, 0);
-            if (captchaInterferenceOptions > 0) {
-                int position = 0;
-                if (originalWidth - x - 5 > jigsawWidth * 2) {
-                    //在原扣图右边插入干扰图
-                    position = RandomUtils.getRandomInt(x + jigsawWidth + 5, originalWidth - jigsawWidth);
-                } else {
-                    //在原扣图左边插入干扰图
-                    position = RandomUtils.getRandomInt(100, x - jigsawWidth - 5);
-                }
-                while (true) {
-                    String s = ImageUtils.getslidingBlock();
-                    if (!jigsawImageBase64.equals(s)) {
-                        interferenceByTemplate(originalImage, Objects.requireNonNull(ImageUtils.getBase64StrToImage(s)), position, 0);
-                        break;
-                    }
-                }
-            }
-            if (captchaInterferenceOptions > 1) {
-                while (true) {
-                    String s = ImageUtils.getslidingBlock();
-                    if (!jigsawImageBase64.equals(s)) {
-                        Integer randomInt = RandomUtils.getRandomInt(jigsawWidth, 100 - jigsawWidth);
-                        interferenceByTemplate(originalImage, Objects.requireNonNull(ImageUtils.getBase64StrToImage(s)),
-                                randomInt, 0);
-                        break;
-                    }
-                }
-            }
-
-
-            // 设置“抗锯齿”的属性
-            graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
-            graphics.setStroke(new BasicStroke(bold, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
-            graphics.drawImage(newJigsawImage, 0, 0, null);
-            graphics.dispose();
-
-            ByteArrayOutputStream os = new ByteArrayOutputStream();//新建流。
-            ImageIO.write(newJigsawImage, IMAGE_TYPE_PNG, os);//利用ImageIO类提供的write方法,将bi以png图片的数据模式写入流。
-            byte[] jigsawImages = os.toByteArray();
-
-            ByteArrayOutputStream oriImagesOs = new ByteArrayOutputStream();//新建流。
-            ImageIO.write(originalImage, IMAGE_TYPE_PNG, oriImagesOs);//利用ImageIO类提供的write方法,将bi以jpg图片的数据模式写入流。
-            byte[] oriCopyImages = oriImagesOs.toByteArray();
-            Base64.Encoder encoder = Base64.getEncoder();
-            dataVO.setOriginalImageBase64(encoder.encodeToString(oriCopyImages).replaceAll("\r|\n", ""));
-            //point信息不传到前端,只做后端check校验
-//            dataVO.setPoint(point);
-            dataVO.setJigsawImageBase64(encoder.encodeToString(jigsawImages).replaceAll("\r|\n", ""));
-            dataVO.setToken(RandomUtils.getUUID());
-            dataVO.setSecretKey(point.getSecretKey());
-//            base64StrToImage(encoder.encodeToString(oriCopyImages), "D:\\原图.png");
-//            base64StrToImage(encoder.encodeToString(jigsawImages), "D:\\滑动.png");
-
-            //将坐标信息存入redis中
-            String codeKey = String.format(REDIS_CAPTCHA_KEY, dataVO.getToken());
-            CaptchaServiceFactory.getCache(cacheType).set(codeKey, JsonUtil.toJSONString(point), EXPIRESIN_SECONDS);
-            log.debug("token:{},point:{}", dataVO.getToken(), JsonUtil.toJSONString(point));
-            return dataVO;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-
-    /**
-     * 随机生成拼图坐标
-     *
-     * @param originalWidth
-     * @param originalHeight
-     * @param jigsawWidth
-     * @param jigsawHeight
-     * @return
-     */
-    private static PointVO generateJigsawPoint(int originalWidth, int originalHeight, int jigsawWidth, int jigsawHeight) {
-        Random random = new Random();
-        int widthDifference = originalWidth - jigsawWidth;
-        int heightDifference = originalHeight - jigsawHeight;
-        int x, y = 0;
-        if (widthDifference <= 0) {
-            x = 5;
-        } else {
-            x = random.nextInt(originalWidth - jigsawWidth - 100) + 100;
-        }
-        if (heightDifference <= 0) {
-            y = 5;
-        } else {
-            y = random.nextInt(originalHeight - jigsawHeight) + 5;
-        }
-        String key = null;
-        if (captchaAesStatus) {
-            key = AESUtil.getKey();
-        }
-        return new PointVO(x, y, key);
-    }
-
-    /**
-     * @param oriImage      原图
-     * @param templateImage 模板图
-     * @param newImage      新抠出的小图
-     * @param x             随机扣取坐标X
-     * @param y             随机扣取坐标y
-     * @throws Exception
-     */
-    private static void cutByTemplate(BufferedImage oriImage, BufferedImage templateImage, BufferedImage newImage, int x, int y) {
-        //临时数组遍历用于高斯模糊存周边像素值
-        int[][] martrix = new int[3][3];
-        int[] values = new int[9];
-
-        int xLength = templateImage.getWidth();
-        int yLength = templateImage.getHeight();
-        // 模板图像宽度
-        for (int i = 0; i < xLength; i++) {
-            // 模板图片高度
-            for (int j = 0; j < yLength; j++) {
-                // 如果模板图像当前像素点不是透明色 copy源文件信息到目标图片中
-                int rgb = templateImage.getRGB(i, j);
-                if (rgb < 0) {
-                    newImage.setRGB(i, j, oriImage.getRGB(x + i, y + j));
-
-                    //抠图区域高斯模糊
-                    readPixel(oriImage, x + i, y + j, values);
-                    fillMatrix(martrix, values);
-                    oriImage.setRGB(x + i, y + j, avgMatrix(martrix));
-                }
-
-                //防止数组越界判断
-                if (i == (xLength - 1) || j == (yLength - 1)) {
-                    continue;
-                }
-                int rightRgb = templateImage.getRGB(i + 1, j);
-                int downRgb = templateImage.getRGB(i, j + 1);
-                //描边处理,,取带像素和无像素的界点,判断该点是不是临界轮廓点,如果是设置该坐标像素是白色
-                if ((rgb >= 0 && rightRgb < 0) || (rgb < 0 && rightRgb >= 0) || (rgb >= 0 && downRgb < 0) || (rgb < 0 && downRgb >= 0)) {
-                    newImage.setRGB(i, j, Color.white.getRGB());
-                    oriImage.setRGB(x + i, y + j, Color.white.getRGB());
-                }
-            }
-        }
-
-    }
-
-
-    /**
-     * 干扰抠图处理
-     *
-     * @param oriImage      原图
-     * @param templateImage 模板图
-     * @param x             随机扣取坐标X
-     * @param y             随机扣取坐标y
-     * @throws Exception
-     */
-    private static void interferenceByTemplate(BufferedImage oriImage, BufferedImage templateImage, int x, int y) {
-        //临时数组遍历用于高斯模糊存周边像素值
-        int[][] martrix = new int[3][3];
-        int[] values = new int[9];
-
-        int xLength = templateImage.getWidth();
-        int yLength = templateImage.getHeight();
-        // 模板图像宽度
-        for (int i = 0; i < xLength; i++) {
-            // 模板图片高度
-            for (int j = 0; j < yLength; j++) {
-                // 如果模板图像当前像素点不是透明色 copy源文件信息到目标图片中
-                int rgb = templateImage.getRGB(i, j);
-                if (rgb < 0) {
-                    //抠图区域高斯模糊
-                    readPixel(oriImage, x + i, y + j, values);
-                    fillMatrix(martrix, values);
-                    oriImage.setRGB(x + i, y + j, avgMatrix(martrix));
-                }
-                //防止数组越界判断
-                if (i == (xLength - 1) || j == (yLength - 1)) {
-                    continue;
-                }
-                int rightRgb = templateImage.getRGB(i + 1, j);
-                int downRgb = templateImage.getRGB(i, j + 1);
-                //描边处理,,取带像素和无像素的界点,判断该点是不是临界轮廓点,如果是设置该坐标像素是白色
-                if ((rgb >= 0 && rightRgb < 0) || (rgb < 0 && rightRgb >= 0) || (rgb >= 0 && downRgb < 0) || (rgb < 0 && downRgb >= 0)) {
-                    oriImage.setRGB(x + i, y + j, Color.white.getRGB());
-                }
-            }
-        }
-
-    }
-
-    private static void readPixel(BufferedImage img, int x, int y, int[] pixels) {
-        int xStart = x - 1;
-        int yStart = y - 1;
-        int current = 0;
-        for (int i = xStart; i < 3 + xStart; i++) {
-            for (int j = yStart; j < 3 + yStart; j++) {
-                int tx = i;
-                if (tx < 0) {
-                    tx = -tx;
-
-                } else if (tx >= img.getWidth()) {
-                    tx = x;
-                }
-                int ty = j;
-                if (ty < 0) {
-                    ty = -ty;
-                } else if (ty >= img.getHeight()) {
-                    ty = y;
-                }
-                pixels[current++] = img.getRGB(tx, ty);
-
-            }
-        }
-    }
-
-    private static void fillMatrix(int[][] matrix, int[] values) {
-        int filled = 0;
-        for (int i = 0; i < matrix.length; i++) {
-            int[] x = matrix[i];
-            for (int j = 0; j < x.length; j++) {
-                x[j] = values[filled++];
-            }
-        }
-    }
-
-    private static int avgMatrix(int[][] matrix) {
-        int r = 0;
-        int g = 0;
-        int b = 0;
-        for (int i = 0; i < matrix.length; i++) {
-            int[] x = matrix[i];
-            for (int j = 0; j < x.length; j++) {
-                if (j == 1) {
-                    continue;
-                }
-                Color c = new Color(x[j]);
-                r += c.getRed();
-                g += c.getGreen();
-                b += c.getBlue();
-            }
-        }
-        return new Color(r / 8, g / 8, b / 8).getRGB();
-    }
-
-
-}

+ 0 - 50
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/CaptchaCacheServiceMemImpl.java

@@ -1,50 +0,0 @@
-package com.anji.captcha.service.impl;
-
-import com.anji.captcha.service.CaptchaCacheService;
-import com.anji.captcha.util.CacheUtil;
-
-import java.util.Objects;
-
-/**
- * 对于分布式部署的应用,我们建议应用自己实现CaptchaCacheService,比如用Redis,参考service/spring-boot代码示例。
- * 如果应用是单点的,也没有使用redis,那默认使用内存。
- * 内存缓存只适合单节点部署的应用,否则验证码生产与验证在节点之间信息不同步,导致失败。
- *
- * @author lide1202@hotmail.com
- * @Title: 默认使用内存当缓存
- * @date 2020-05-12
- */
-public class CaptchaCacheServiceMemImpl implements CaptchaCacheService {
-    @Override
-    public void set(String key, String value, long expiresInSeconds) {
-
-        CacheUtil.set(key, value, expiresInSeconds);
-    }
-
-    @Override
-    public boolean exists(String key) {
-        return CacheUtil.exists(key);
-    }
-
-    @Override
-    public void delete(String key) {
-        CacheUtil.delete(key);
-    }
-
-    @Override
-    public String get(String key) {
-        return CacheUtil.get(key);
-    }
-
-    @Override
-    public Long increment(String key, long val) {
-        Long ret = Long.parseLong(Objects.requireNonNull(CacheUtil.get(key))) + val;
-        CacheUtil.set(key, ret + "", 0);
-        return ret;
-    }
-
-    @Override
-    public String type() {
-        return "local";
-    }
-}

+ 0 - 58
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/CaptchaServiceFactory.java

@@ -1,58 +0,0 @@
-package com.anji.captcha.service.impl;
-
-import com.anji.captcha.model.common.Const;
-import com.anji.captcha.service.CaptchaCacheService;
-import com.anji.captcha.service.CaptchaService;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.ServiceLoader;
-
-/**
- * Created by raodeming on 2020/5/26.
- */
-@Slf4j
-public class CaptchaServiceFactory {
-
-    public static CaptchaService getInstance(Properties config) {
-        //先把所有CaptchaService初始化,通过init方法,实例字体等,add by lide1202@hotmail.com
-        /*try{
-            for(CaptchaService item: instances.values()){
-                item.init(config);
-            }
-        }catch (Exception e){
-            logger.warn("init captchaService fail:{}", e);
-        }*/
-
-        String captchaType = config.getProperty(Const.CAPTCHA_TYPE, "default");
-        CaptchaService ret = instances.get(captchaType);
-        if (ret == null) {
-            throw new RuntimeException("unsupported-[captcha.type]=" + captchaType);
-        }
-        ret.init(config);
-        return ret;
-    }
-
-    public static CaptchaCacheService getCache(String cacheType) {
-        return cacheService.get(cacheType);
-    }
-
-    public volatile static Map<String, CaptchaService> instances = new HashMap<>();
-    public volatile static Map<String, CaptchaCacheService> cacheService = new HashMap<>();
-
-    static {
-        ServiceLoader<CaptchaCacheService> cacheServices = ServiceLoader.load(CaptchaCacheService.class);
-        for (CaptchaCacheService item : cacheServices) {
-            cacheService.put(item.type(), item);
-        }
-        log.info("supported-captchaCache-service:{}", cacheService.keySet().toString());
-        ServiceLoader<CaptchaService> services = ServiceLoader.load(CaptchaService.class);
-        for (CaptchaService item : services) {
-            instances.put(item.captchaType(), item);
-        }
-        ;
-        log.info("supported-captchaTypes-service:{}", instances.keySet().toString());
-    }
-}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 321
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/ClickWordCaptchaServiceImpl.java


+ 0 - 100
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/DefaultCaptchaServiceImpl.java

@@ -1,100 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.service.impl;
-
-import cn.hutool.core.util.StrUtil;
-import com.anji.captcha.model.common.RepCodeEnum;
-import com.anji.captcha.model.common.ResponseModel;
-import com.anji.captcha.model.vo.CaptchaVO;
-import com.anji.captcha.service.CaptchaService;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Properties;
-
-/**
- * Created by raodeming on 2019/12/25.
- */
-@Slf4j
-public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{
-
-    @Override
-    public String captchaType() {
-        return "default";
-    }
-
-    @Override
-    public void init(Properties config) {
-        for (String s : CaptchaServiceFactory.instances.keySet()) {
-            if(captchaType().equals(s)){
-                continue;
-            }
-            getService(s).init(config);
-        }
-    }
-
-	@Override
-	public void destroy(Properties config) {
-		for (String s : CaptchaServiceFactory.instances.keySet()) {
-			if(captchaType().equals(s)){
-				continue;
-			}
-			getService(s).destroy(config);
-		}
-	}
-
-	private CaptchaService getService(String captchaType){
-        return CaptchaServiceFactory.instances.get(captchaType);
-    }
-
-    @Override
-    public ResponseModel get(CaptchaVO captchaVO) {
-        if (captchaVO == null) {
-            return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
-        }
-        if (StrUtil.isEmpty(captchaVO.getCaptchaType())) {
-            return RepCodeEnum.NULL_ERROR.parseError("类型");
-        }
-        return getService(captchaVO.getCaptchaType()).get(captchaVO);
-    }
-
-    @Override
-    public ResponseModel check(CaptchaVO captchaVO) {
-        if (captchaVO == null) {
-            return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
-        }
-        if (StrUtil.isEmpty(captchaVO.getCaptchaType())) {
-            return RepCodeEnum.NULL_ERROR.parseError("类型");
-        }
-        if (StrUtil.isEmpty(captchaVO.getToken())) {
-            return RepCodeEnum.NULL_ERROR.parseError("token");
-        }
-        return getService(captchaVO.getCaptchaType()).check(captchaVO);
-    }
-
-    @Override
-    public ResponseModel verification(CaptchaVO captchaVO) {
-        if (captchaVO == null) {
-            return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
-        }
-        if (StrUtil.isEmpty(captchaVO.getCaptchaVerification())) {
-            return RepCodeEnum.NULL_ERROR.parseError("二次校验参数");
-        }
-        try {
-            String codeKey = String.format(REDIS_SECOND_CAPTCHA_KEY, captchaVO.getCaptchaVerification());
-            if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) {
-                return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_INVALID);
-            }
-            //二次校验取值后,即刻失效
-            CaptchaServiceFactory.getCache(cacheType).delete(codeKey);
-        } catch (Exception e) {
-            log.error("验证码坐标解析失败", e);
-            return ResponseModel.errorMsg(e.getMessage());
-        }
-        return ResponseModel.success();
-    }
-
-}

+ 0 - 154
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/FrequencyLimitHandler.java

@@ -1,154 +0,0 @@
-package com.anji.captcha.service.impl;
-
-import cn.hutool.core.util.StrUtil;
-import com.anji.captcha.model.common.Const;
-import com.anji.captcha.model.common.RepCodeEnum;
-import com.anji.captcha.model.common.ResponseModel;
-import com.anji.captcha.model.vo.CaptchaVO;
-import com.anji.captcha.service.CaptchaCacheService;
-
-import java.util.Objects;
-import java.util.Properties;
-
-/**
- * @author WongBin
- * @date 2021/1/21
- */
-public interface FrequencyLimitHandler {
-
-    String LIMIT_KEY = "AJ.CAPTCHA.REQ.LIMIT-%s-%s";
-
-    /**
-     * get 接口限流
-     *
-     * @param captchaVO
-     * @return
-     */
-    ResponseModel validateGet(CaptchaVO captchaVO);
-
-    /**
-     * check接口限流
-     *
-     * @param captchaVO
-     * @return
-     */
-    ResponseModel validateCheck(CaptchaVO captchaVO);
-
-    /**
-     * verify接口限流
-     *
-     * @param captchaVO
-     * @return
-     */
-    ResponseModel validateVerify(CaptchaVO captchaVO);
-
-
-    /***
-     * 验证码接口限流:
-     *      客户端ClientUid 组件实例化时设置一次,如:场景码+UUID,客户端可以本地缓存,保证一个组件只有一个值
-     *
-     * 针对同一个客户端的请求,做如下限制:
-     * get
-     * 	 1分钟内check失败5次,锁定5分钟
-     * 	 1分钟内不能超过120次。
-     * check:
-     *   1分钟内不超过600次
-     * verify:
-     *   1分钟内不超过600次
-     */
-    class DefaultLimitHandler implements FrequencyLimitHandler {
-        private Properties config;
-        private CaptchaCacheService cacheService;
-
-        public DefaultLimitHandler(Properties config, CaptchaCacheService cacheService) {
-            this.config = config;
-            this.cacheService = cacheService;
-        }
-
-        private String getClientCId(CaptchaVO input, String type) {
-            return String.format(LIMIT_KEY, type, input.getClientUid());
-        }
-
-        @Override
-        public ResponseModel validateGet(CaptchaVO d) {
-            // 无客户端身份标识,不限制
-            if (StrUtil.isEmpty(d.getClientUid())) {
-                return null;
-            }
-            String getKey = getClientCId(d, "GET");
-            String lockKey = getClientCId(d, "LOCK");
-            // 失败次数过多,锁定
-            if (Objects.nonNull(cacheService.get(lockKey))) {
-                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LOCK_GET_ERROR);
-            }
-            String getCnts = cacheService.get(getKey);
-            if (Objects.isNull(getCnts)) {
-                cacheService.set(getKey, "1", 60);
-                getCnts = "1";
-            }
-            cacheService.increment(getKey, 1);
-            // 1分钟内请求次数过多
-            if (Long.parseLong(getCnts) > Long.parseLong(config.getProperty(Const.REQ_GET_MINUTE_LIMIT, "120"))) {
-                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_GET_ERROR);
-            }
-
-            // 失败次数验证
-            String failKey = getClientCId(d, "FAIL");
-            String failCnts = cacheService.get(failKey);
-            // 没有验证失败,通过校验
-            if (Objects.isNull(failCnts)) {
-                return null;
-            }
-            // 1分钟内失败5次
-            if (Long.parseLong(failCnts) > Long.parseLong(config.getProperty(Const.REQ_GET_LOCK_LIMIT, "5"))) {
-                // get接口锁定5分钟
-                cacheService.set(lockKey, "1", Long.parseLong(config.getProperty(Const.REQ_GET_LOCK_SECONDS, "300")));
-                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LOCK_GET_ERROR);
-            }
-            return null;
-        }
-
-        @Override
-        public ResponseModel validateCheck(CaptchaVO d) {
-            // 无客户端身份标识,不限制
-            if (StrUtil.isEmpty(d.getClientUid())) {
-                return null;
-            }
-            /*String getKey = getClientCId(d, "GET");
-            if(Objects.isNull(cacheService.get(getKey))){
-                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_INVALID);
-            }*/
-            String key = getClientCId(d, "CHECK");
-            String v = cacheService.get(key);
-            if (Objects.isNull(v)) {
-                cacheService.set(key, "1", 60);
-                v = "1";
-            }
-            cacheService.increment(key, 1);
-            if (Long.parseLong(v) > Long.parseLong(config.getProperty(Const.REQ_CHECK_MINUTE_LIMIT, "600"))) {
-                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_CHECK_ERROR);
-            }
-            return null;
-        }
-
-        @Override
-        public ResponseModel validateVerify(CaptchaVO d) {
-            /*String getKey = getClientCId(d, "GET");
-            if(Objects.isNull(cacheService.get(getKey))){
-                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_INVALID);
-            }*/
-            String key = getClientCId(d, "VERIFY");
-            String v = cacheService.get(key);
-            if (Objects.isNull(v)) {
-                cacheService.set(key, "1", 60);
-                v = "1";
-            }
-            cacheService.increment(key, 1);
-            if (Long.parseLong(v) > Long.parseLong(config.getProperty(Const.REQ_VALIDATE_MINUTE_LIMIT, "600"))) {
-                return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_VERIFY_ERROR);
-            }
-            return null;
-        }
-    }
-
-}

+ 0 - 150
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/AESUtil.java

@@ -1,150 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.util;
-
-
-import cn.hutool.core.util.StrUtil;
-
-import javax.crypto.Cipher;
-import javax.crypto.KeyGenerator;
-import javax.crypto.spec.SecretKeySpec;
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-
-
-public class AESUtil {
-    //算法
-    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
-
-    /**
-     * 获取随机key
-     *
-     * @return
-     */
-    public static String getKey() {
-        return RandomUtils.getRandomString(16);
-    }
-
-
-    /**
-     * 将byte[]转为各种进制的字符串
-     *
-     * @param bytes byte[]
-     * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
-     * @return 转换后的字符串
-     */
-    public static String binary(byte[] bytes, int radix) {
-        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
-    }
-
-    /**
-     * base 64 encode
-     *
-     * @param bytes 待编码的byte[]
-     * @return 编码后的base 64 code
-     */
-    public static String base64Encode(byte[] bytes) {
-        //return Base64.encodeBase64String(bytes);
-        return Base64.getEncoder().encodeToString(bytes);
-    }
-
-    /**
-     * base 64 decode
-     *
-     * @param base64Code 待解码的base 64 code
-     * @return 解码后的byte[]
-     * @throws Exception
-     */
-    public static byte[] base64Decode(String base64Code) throws Exception {
-        Base64.Decoder decoder = Base64.getDecoder();
-        return StrUtil.isEmpty(base64Code) ? null : decoder.decode(base64Code);
-    }
-
-
-    /**
-     * AES加密
-     *
-     * @param content    待加密的内容
-     * @param encryptKey 加密密钥
-     * @return 加密后的byte[]
-     * @throws Exception
-     */
-    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {
-        KeyGenerator kgen = KeyGenerator.getInstance("AES");
-        kgen.init(128);
-        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
-        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
-
-        return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
-    }
-
-
-    /**
-     * AES加密为base 64 code
-     *
-     * @param content    待加密的内容
-     * @param encryptKey 加密密钥
-     * @return 加密后的base 64 code
-     * @throws Exception
-     */
-    public static String aesEncrypt(String content, String encryptKey) throws Exception {
-        if (StrUtil.isBlank(encryptKey)) {
-            return content;
-        }
-        return base64Encode(aesEncryptToBytes(content, encryptKey));
-    }
-
-    /**
-     * AES解密
-     *
-     * @param encryptBytes 待解密的byte[]
-     * @param decryptKey   解密密钥
-     * @return 解密后的String
-     * @throws Exception
-     */
-    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {
-        KeyGenerator kgen = KeyGenerator.getInstance("AES");
-        kgen.init(128);
-
-        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
-        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
-        byte[] decryptBytes = cipher.doFinal(encryptBytes);
-        return new String(decryptBytes);
-    }
-
-
-    /**
-     * 将base 64 code AES解密
-     *
-     * @param encryptStr 待解密的base 64 code
-     * @param decryptKey 解密密钥
-     * @return 解密后的string
-     * @throws Exception
-     */
-    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
-        if (StrUtil.isBlank(decryptKey)) {
-            return encryptStr;
-        }
-        return StrUtil.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
-    }
-
-    /**
-     * 测试
-     */
-    public static void main(String[] args) throws Exception {
-        String randomString = RandomUtils.getRandomString(16);
-        String content = "hahhahaahhahni";
-        System.out.println("加密前:" + content);
-        System.out.println("加密密钥和解密密钥:" + randomString);
-        String encrypt = aesEncrypt(content, randomString);
-        System.out.println("加密后:" + encrypt);
-        String decrypt = aesDecrypt(encrypt, randomString);
-        System.out.println("解密后:" + decrypt);
-    }
-
-}

+ 0 - 111
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/CacheUtil.java

@@ -1,111 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.util;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Map;
-import java.util.concurrent.*;
-
-public final class CacheUtil {
-    private static final Logger logger = LoggerFactory.getLogger(CacheUtil.class);
-
-    private static final Map<String, Object> CACHE_MAP = new ConcurrentHashMap<String, Object>();
-
-    /**
-     * 缓存最大个数
-     */
-    private static Integer CACHE_MAX_NUMBER = 1000;
-
-    /**
-     * 初始化
-     *
-     * @param cacheMaxNumber 缓存最大个数
-     * @param second         定时任务 秒执行清除过期缓存
-     */
-    public static void init(int cacheMaxNumber, long second) {
-        CACHE_MAX_NUMBER = cacheMaxNumber;
-        if (second > 0L) {
-            /*Timer timer = new Timer();
-            timer.schedule(new TimerTask() {
-                @Override
-                public void run() {
-                    refresh();
-                }
-            }, 0, second * 1000);*/
-            ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
-                @Override
-                public Thread newThread(Runnable r) {
-                    return new Thread(r, "thd-captcha-cache-clean");
-                }
-            }, new ThreadPoolExecutor.CallerRunsPolicy());
-            scheduledExecutor.scheduleAtFixedRate(new Runnable() {
-                @Override
-                public void run() {
-                    refresh();
-                }
-            }, 10, second, TimeUnit.SECONDS);
-        }
-    }
-
-    /**
-     * 缓存刷新,清除过期数据
-     */
-    public static void refresh() {
-        logger.debug("local缓存刷新,清除过期数据");
-        for (String key : CACHE_MAP.keySet()) {
-            exists(key);
-        }
-    }
-
-
-    public static void set(String key, String value, long expiresInSeconds) {
-        //设置阈值,达到即clear缓存
-        if (CACHE_MAP.size() > CACHE_MAX_NUMBER * 2) {
-            logger.info("CACHE_MAP达到阈值,clear map");
-            clear();
-        }
-        CACHE_MAP.put(key, value);
-        if (expiresInSeconds > 0) {
-            CACHE_MAP.put(key + "_HoldTime", System.currentTimeMillis() + expiresInSeconds * 1000);//缓存失效时间
-        }
-    }
-
-    public static void delete(String key) {
-        CACHE_MAP.remove(key);
-        CACHE_MAP.remove(key + "_HoldTime");
-    }
-
-    public static boolean exists(String key) {
-        Long cacheHoldTime = (Long) CACHE_MAP.get(key + "_HoldTime");
-        if (cacheHoldTime == null || cacheHoldTime == 0L) {
-            return false;
-        }
-        if (cacheHoldTime < System.currentTimeMillis()) {
-            delete(key);
-            return false;
-        }
-        return true;
-    }
-
-
-    public static String get(String key) {
-        if (exists(key)) {
-            return (String) CACHE_MAP.get(key);
-        }
-        return null;
-    }
-
-    /**
-     * 删除所有缓存
-     */
-    public static void clear() {
-        logger.debug("have clean all key !");
-        CACHE_MAP.clear();
-    }
-}

+ 0 - 120
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/FileCopyUtils.java

@@ -1,120 +0,0 @@
-package com.anji.captcha.util;
-//
-// Source code recreated from a .class file by IntelliJ IDEA
-// (powered by Fernflower decompiler)
-//
-
-import java.io.*;
-import java.nio.file.Files;
-
-public abstract class FileCopyUtils {
-    public static final int BUFFER_SIZE = 4096;
-
-    public FileCopyUtils() {
-    }
-
-    public static int copy(File in, File out) throws IOException {
-        return copy(Files.newInputStream(in.toPath()), Files.newOutputStream(out.toPath()));
-    }
-
-    public static void copy(byte[] in, File out) throws IOException {
-        copy((InputStream) (new ByteArrayInputStream(in)), (OutputStream) Files.newOutputStream(out.toPath()));
-    }
-
-    public static byte[] copyToByteArray(File in) throws IOException {
-        return copyToByteArray(Files.newInputStream(in.toPath()));
-    }
-
-    public static int copy(InputStream in, OutputStream out) throws IOException {
-        int var2;
-        try {
-            var2 = StreamUtils.copy(in, out);
-        } finally {
-            try {
-                in.close();
-            } catch (IOException var12) {
-            }
-
-            try {
-                out.close();
-            } catch (IOException var11) {
-            }
-
-        }
-
-        return var2;
-    }
-
-    public static void copy(byte[] in, OutputStream out) throws IOException {
-        try {
-            out.write(in);
-        } finally {
-            try {
-                out.close();
-            } catch (IOException var8) {
-            }
-
-        }
-
-    }
-
-    public static byte[] copyToByteArray(InputStream in) throws IOException {
-        if (in == null) {
-            return new byte[0];
-        } else {
-            ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
-            copy((InputStream) in, (OutputStream) out);
-            return out.toByteArray();
-        }
-    }
-
-    public static int copy(Reader in, Writer out) throws IOException {
-        try {
-            int byteCount = 0;
-            char[] buffer = new char[4096];
-
-            int bytesRead;
-            for (boolean var4 = true; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) {
-                out.write(buffer, 0, bytesRead);
-            }
-
-            out.flush();
-            return byteCount;
-        } finally {
-            try {
-                in.close();
-            } catch (IOException var15) {
-            }
-
-            try {
-                out.close();
-            } catch (IOException var14) {
-            }
-
-        }
-    }
-
-    public static void copy(String in, Writer out) throws IOException {
-        try {
-            out.write(in);
-        } finally {
-            try {
-                out.close();
-            } catch (IOException var8) {
-            }
-
-        }
-
-    }
-
-    public static String copyToString(Reader in) throws IOException {
-        if (in == null) {
-            return "";
-        } else {
-            StringWriter out = new StringWriter();
-            copy((Reader) in, (Writer) out);
-            return out.toString();
-        }
-    }
-}
-

+ 0 - 169
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/ImageUtils.java

@@ -1,169 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.util;
-
-import cn.hutool.core.util.StrUtil;
-import com.anji.captcha.model.common.CaptchaBaseMapEnum;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.Base64Utils;
-
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.*;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-@Slf4j
-public class ImageUtils {
-    private static Map<String, String> originalCacheMap = new ConcurrentHashMap();  //滑块底图
-    private static Map<String, String> slidingBlockCacheMap = new ConcurrentHashMap(); //滑块
-    private static Map<String, String> picClickCacheMap = new ConcurrentHashMap(); //点选文字
-    private static Map<String, String[]> fileNameMap = new ConcurrentHashMap<>();
-
-    public static void cacheImage(String captchaOriginalPathJigsaw, String captchaOriginalPathClick) {
-        //滑动拼图
-        if (StrUtil.isBlank(captchaOriginalPathJigsaw)) {
-            originalCacheMap.putAll(getResourcesImagesFile("defaultImages/jigsaw/original"));
-            slidingBlockCacheMap.putAll(getResourcesImagesFile("defaultImages/jigsaw/slidingBlock"));
-        } else {
-            originalCacheMap.putAll(getImagesFile(captchaOriginalPathJigsaw + File.separator + "original"));
-            slidingBlockCacheMap.putAll(getImagesFile(captchaOriginalPathJigsaw + File.separator + "slidingBlock"));
-        }
-        //点选文字
-        if (StrUtil.isBlank(captchaOriginalPathClick)) {
-            picClickCacheMap.putAll(getResourcesImagesFile("defaultImages/pic-click"));
-        } else {
-            picClickCacheMap.putAll(getImagesFile(captchaOriginalPathClick));
-        }
-        fileNameMap.put(CaptchaBaseMapEnum.ORIGINAL.getCodeValue(), originalCacheMap.keySet().toArray(new String[0]));
-        fileNameMap.put(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue(), slidingBlockCacheMap.keySet().toArray(new String[0]));
-        fileNameMap.put(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue(), picClickCacheMap.keySet().toArray(new String[0]));
-        log.info("初始化底图:{}", JsonUtil.toJSONString(fileNameMap));
-    }
-
-    public static void cacheBootImage(Map<String, String> originalMap, Map<String, String> slidingBlockMap, Map<String, String> picClickMap) {
-        originalCacheMap.putAll(originalMap);
-        slidingBlockCacheMap.putAll(slidingBlockMap);
-        picClickCacheMap.putAll(picClickMap);
-        fileNameMap.put(CaptchaBaseMapEnum.ORIGINAL.getCodeValue(), originalCacheMap.keySet().toArray(new String[0]));
-        fileNameMap.put(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue(), slidingBlockCacheMap.keySet().toArray(new String[0]));
-        fileNameMap.put(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue(), picClickCacheMap.keySet().toArray(new String[0]));
-        log.info("自定义resource底图:{}", JsonUtil.toJSONString(fileNameMap));
-    }
-
-
-    public static BufferedImage getOriginal() {
-        String[] strings = fileNameMap.get(CaptchaBaseMapEnum.ORIGINAL.getCodeValue());
-        if (null == strings || strings.length == 0) {
-            return null;
-        }
-        Integer randomInt = RandomUtils.getRandomInt(0, strings.length);
-        String s = originalCacheMap.get(strings[randomInt]);
-        return getBase64StrToImage(s);
-    }
-
-    public static String getslidingBlock() {
-        String[] strings = fileNameMap.get(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue());
-        if (null == strings || strings.length == 0) {
-            return null;
-        }
-        Integer randomInt = RandomUtils.getRandomInt(0, strings.length);
-        return slidingBlockCacheMap.get(strings[randomInt]);
-    }
-
-    public static BufferedImage getPicClick() {
-        String[] strings = fileNameMap.get(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue());
-        if (null == strings || strings.length == 0) {
-            return null;
-        }
-        Integer randomInt = RandomUtils.getRandomInt(0, strings.length);
-        String s = picClickCacheMap.get(strings[randomInt]);
-        return getBase64StrToImage(s);
-    }
-
-    /**
-     * 图片转base64 字符串
-     *
-     * @param templateImage
-     * @return
-     */
-    public static String getImageToBase64Str(BufferedImage templateImage) {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try {
-            ImageIO.write(templateImage, "png", baos);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        byte[] bytes = baos.toByteArray();
-
-        Base64.Encoder encoder = Base64.getEncoder();
-
-        return encoder.encodeToString(bytes).trim();
-    }
-
-    /**
-     * base64 字符串转图片
-     *
-     * @param base64String
-     * @return
-     */
-    public static BufferedImage getBase64StrToImage(String base64String) {
-        try {
-            Base64.Decoder decoder = Base64.getDecoder();
-            byte[] bytes = decoder.decode(base64String);
-            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
-            return ImageIO.read(inputStream);
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return null;
-    }
-
-
-    private static Map<String, String> getResourcesImagesFile(String path) {
-        //默认提供六张底图
-        Map<String, String> imgMap = new HashMap<>();
-        ClassLoader classLoader = ImageUtils.class.getClassLoader();
-        for (int i = 1; i <= 6; i++) {
-            InputStream resourceAsStream = classLoader.getResourceAsStream(path.concat("/").concat(String.valueOf(i).concat(".png")));
-            byte[] bytes = new byte[0];
-            try {
-                bytes = FileCopyUtils.copyToByteArray(resourceAsStream);
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            String string = Base64Utils.encodeToString(bytes);
-            String filename = String.valueOf(i).concat(".png");
-            imgMap.put(filename, string);
-        }
-        return imgMap;
-    }
-
-    private static Map<String, String> getImagesFile(String path) {
-        Map<String, String> imgMap = new HashMap<>();
-        File file = new File(path);
-        if (!file.exists()) {
-            return new HashMap<>();
-        }
-        File[] files = file.listFiles();
-        Arrays.stream(files).forEach(item -> {
-            try {
-                FileInputStream fileInputStream = new FileInputStream(item);
-                byte[] bytes = FileCopyUtils.copyToByteArray(fileInputStream);
-                String string = Base64Utils.encodeToString(bytes);
-                imgMap.put(item.getName(), string);
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        });
-        return imgMap;
-    }
-
-}

+ 0 - 73
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/JsonUtil.java

@@ -1,73 +0,0 @@
-package com.anji.captcha.util;
-
-import com.anji.captcha.model.vo.PointVO;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 替换掉fastjson,自定义实现相关方法
- * note: 该实现不具有通用性,仅用于本项目。
- *
- * @author WongBin
- * @date 2021/1/8
- */
-@Slf4j
-public class JsonUtil {
-    public static List<PointVO> parseArray(String text, Class<PointVO> clazz) {
-        if (text == null) {
-            return null;
-        } else {
-            String[] arr = text.replaceFirst("\\[", "")
-                    .replaceFirst("\\]", "").split("\\}");
-            List<PointVO> ret = new ArrayList<>(arr.length);
-            for (String s : arr) {
-                ret.add(parseObject(s, PointVO.class));
-            }
-            return ret;
-        }
-    }
-
-    public static PointVO parseObject(String text, Class<PointVO> clazz) {
-        if (text == null) {
-            return null;
-        }
-		/*if(!clazz.isAssignableFrom(PointVO.class)) {
-			throw new UnsupportedOperationException("不支持的输入类型:"
-					+ clazz.getSimpleName());
-		}*/
-        try {
-            PointVO ret = clazz.newInstance();
-            return ret.parse(text);
-        } catch (Exception ex) {
-            log.error("json解析异常", ex);
-
-        }
-        return null;
-    }
-
-    public static String toJSONString(Object object) {
-        if (object == null) {
-            return "{}";
-        }
-        if (object instanceof PointVO) {
-            PointVO t = (PointVO) object;
-            return t.toJsonString();
-        }
-        if (object instanceof List) {
-            List<PointVO> list = (List<PointVO>) object;
-            StringBuilder buf = new StringBuilder("[");
-            list.forEach(t -> {
-                buf.append(t.toJsonString()).append(",");
-            });
-            return buf.deleteCharAt(buf.lastIndexOf(",")).append("]").toString();
-        }
-        if (object instanceof Map) {
-            return ((Map) object).entrySet().toString();
-        }
-        throw new UnsupportedOperationException("不支持的输入类型:"
-                + object.getClass().getSimpleName());
-    }
-}

+ 0 - 42
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/MD5Util.java

@@ -1,42 +0,0 @@
-package com.anji.captcha.util;
-
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-
-/**
- * @Title: MD5工具类
- */
-public abstract class MD5Util {
-    /**
-     * 获取指定字符串的md5值
-     *
-     * @param dataStr 明文
-     * @return String
-     */
-    public static String md5(String dataStr) {
-        try {
-            MessageDigest m = MessageDigest.getInstance("MD5");
-            m.update(dataStr.getBytes(StandardCharsets.UTF_8));
-            byte[] s = m.digest();
-            StringBuilder result = new StringBuilder();
-            for (byte b : s) {
-                result.append(Integer.toHexString((0x000000FF & b) | 0xFFFFFF00).substring(6));
-            }
-            return result.toString();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return "";
-    }
-
-    /**
-     * 获取指定字符串的md5值, md5(str+salt)
-     *
-     * @param dataStr 明文
-     * @return String
-     */
-    public static String md5WithSalt(String dataStr, String salt) {
-        return md5(dataStr + salt);
-    }
-
-}

+ 0 - 96
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/RandomUtils.java

@@ -1,96 +0,0 @@
-/*
- *Copyright © 2018 anji-plus
- *安吉加加信息技术有限公司
- *http://www.anji-plus.com
- *All rights reserved.
- */
-package com.anji.captcha.util;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.ThreadLocalRandom;
-
-
-public class RandomUtils {
-
-    /**
-     * 生成UUID
-     *
-     * @return
-     */
-    public static String getUUID() {
-        String uuid = UUID.randomUUID().toString();
-        uuid = uuid.replace("-", "");
-        return uuid;
-    }
-
-    /**
-     * 获取指定文字的随机中文
-     *
-     * @return
-     */
-    public static String getRandomHan(String hanZi) {
-        return hanZi.charAt(new Random().nextInt(hanZi.length())) + "";
-    }
-
-    public static int getRandomInt(int bound) {
-        return ThreadLocalRandom.current().nextInt(bound);
-    }
-
-    /**
-     * 获取随机中文
-     *
-     * @return
-     */
-    public static String getRandomHan() {
-        String str = "";
-        int highCode;
-        int lowCode;
-
-        Random random = new Random();
-
-        highCode = (176 + Math.abs(random.nextInt(39))); //B0 + 0~39(16~55) 一级汉字所占区
-        lowCode = (161 + Math.abs(random.nextInt(93))); //A1 + 0~93 每区有94个汉字
-
-        byte[] b = new byte[2];
-        b[0] = (Integer.valueOf(highCode)).byteValue();
-        b[1] = (Integer.valueOf(lowCode)).byteValue();
-
-        try {
-            str = new String(b, "GBK");
-        } catch (UnsupportedEncodingException e) {
-            e.printStackTrace();
-        }
-        return str;
-    }
-
-    /**
-     * 随机范围内数字
-     *
-     * @param startNum
-     * @param endNum
-     * @return
-     */
-    public static Integer getRandomInt(int startNum, int endNum) {
-        return ThreadLocalRandom.current().nextInt(endNum - startNum) + startNum;
-    }
-
-    /**
-     * 获取随机字符串
-     *
-     * @param length
-     * @return
-     */
-    public static String getRandomString(int length) {
-        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-        Random random = new Random();
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0; i < length; i++) {
-            int number = random.nextInt(62);
-            sb.append(str.charAt(number));
-        }
-        return sb.toString();
-    }
-
-}

+ 0 - 138
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/StreamUtils.java

@@ -1,138 +0,0 @@
-package com.anji.captcha.util;
-//
-// Source code recreated from a .class file by IntelliJ IDEA
-// (powered by Fernflower decompiler)
-//
-
-import java.io.*;
-import java.nio.charset.Charset;
-
-public abstract class StreamUtils {
-    public static final int BUFFER_SIZE = 4096;
-    private static final byte[] EMPTY_CONTENT = new byte[0];
-
-    public StreamUtils() {
-    }
-
-    public static byte[] copyToByteArray(InputStream in) throws IOException {
-        if (in == null) {
-            return new byte[0];
-        } else {
-            ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
-            copy((InputStream) in, out);
-            return out.toByteArray();
-        }
-    }
-
-    public static String copyToString(InputStream in, Charset charset) throws IOException {
-        if (in == null) {
-            return "";
-        } else {
-            StringBuilder out = new StringBuilder();
-            InputStreamReader reader = new InputStreamReader(in, charset);
-            char[] buffer = new char[4096];
-
-            int bytesRead;
-            while ((bytesRead = reader.read(buffer)) != -1) {
-                out.append(buffer, 0, bytesRead);
-            }
-
-            return out.toString();
-        }
-    }
-
-    public static void copy(byte[] in, OutputStream out) throws IOException {
-        out.write(in);
-    }
-
-    public static void copy(String in, Charset charset, OutputStream out) throws IOException {
-        Writer writer = new OutputStreamWriter(out, charset);
-        writer.write(in);
-        writer.flush();
-    }
-
-    public static int copy(InputStream in, OutputStream out) throws IOException {
-        int byteCount = 0;
-        byte[] buffer = new byte[4096];
-
-        int bytesRead;
-        for (boolean var4 = true; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) {
-            out.write(buffer, 0, bytesRead);
-        }
-
-        out.flush();
-        return byteCount;
-    }
-
-    public static long copyRange(InputStream in, OutputStream out, long start, long end) throws IOException {
-        long skipped = in.skip(start);
-        if (skipped < start) {
-            throw new IOException("Skipped only " + skipped + " bytes out of " + start + " required");
-        } else {
-            long bytesToCopy = end - start + 1L;
-            byte[] buffer = new byte[4096];
-
-            while (bytesToCopy > 0L) {
-                int bytesRead = in.read(buffer);
-                if (bytesRead == -1) {
-                    break;
-                }
-
-                if ((long) bytesRead <= bytesToCopy) {
-                    out.write(buffer, 0, bytesRead);
-                    bytesToCopy -= (long) bytesRead;
-                } else {
-                    out.write(buffer, 0, (int) bytesToCopy);
-                    bytesToCopy = 0L;
-                }
-            }
-
-            return end - start + 1L - bytesToCopy;
-        }
-    }
-
-    public static int drain(InputStream in) throws IOException {
-        byte[] buffer = new byte[4096];
-        int byteCount;
-        int bytesRead;
-        for (byteCount = 0; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) {
-        }
-
-        return byteCount;
-    }
-
-    public static InputStream emptyInput() {
-        return new ByteArrayInputStream(EMPTY_CONTENT);
-    }
-
-    public static InputStream nonClosing(InputStream in) {
-        return new NonClosingInputStream(in);
-    }
-
-    public static OutputStream nonClosing(OutputStream out) {
-        return new NonClosingOutputStream(out);
-    }
-
-    private static class NonClosingOutputStream extends FilterOutputStream {
-        public NonClosingOutputStream(OutputStream out) {
-            super(out);
-        }
-
-        public void write(byte[] b, int off, int let) throws IOException {
-            this.out.write(b, off, let);
-        }
-
-        public void close() throws IOException {
-        }
-    }
-
-    private static class NonClosingInputStream extends FilterInputStream {
-        public NonClosingInputStream(InputStream in) {
-            super(in);
-        }
-
-        public void close() throws IOException {
-        }
-    }
-}
-

+ 0 - 3
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaService

@@ -1,3 +0,0 @@
-com.anji.captcha.service.impl.BlockPuzzleCaptchaServiceImpl
-com.anji.captcha.service.impl.ClickWordCaptchaServiceImpl
-com.anji.captcha.service.impl.DefaultCaptchaServiceImpl

yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/services/com.anji.captcha.service.CaptchaCacheService → yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/services/com.xingyuv.captcha.service.CaptchaCacheService


+ 0 - 1
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -1,2 +1 @@
-com.anji.captcha.config.AjCaptchaAutoConfiguration
 cn.iocoder.yudao.framework.captcha.config.YudaoCaptchaConfiguration

BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/1.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/2.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/3.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/4.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/5.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/6.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/original/bg8.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/1.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/2.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/3.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/4.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/5.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/jigsaw/slidingBlock/6.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/1.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/2.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/3.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/4.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/5.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/6.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg10.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg11.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg12.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg13.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg14.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg15.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg16.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg17.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg18.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg19.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/defaultImages/pic-click/bg20.png


BIN
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/fonts/WenQuanZhengHei.ttf


+ 0 - 55
yudao-framework/yudao-spring-boot-starter-captcha/src/main/resources/fonts/license.txt

@@ -1,55 +0,0 @@
-文泉驿是一个开源汉字字体项目
-
-由旅美学者房骞骞(FangQ)
-
-于2004年10月创建
-
-集中力量解决GNU/Linux
-
-高质量中文字体匮乏的状况
-
-目前,文泉驿已经开发并发布了
-
-第一个完整覆盖GB18030汉字
-
-(包含27000多个汉字)
-
-的多规格点阵汉字字型文件
-
-第一个覆盖GBK字符集的
-
-开源矢量字型文件(文泉驿正黑)
-
-并提供了目前包含字符数目最多的
-
-开源字体——GNU Unifont——中
-
-绝大多数中日韩文相关的符号
-
-这些字型文件已经逐渐成为
-
-主流Linux/Unix发行版
-
-中文桌面的首选中文字体
-
-目前Ubuntu、Fedora、Slackware
-
-Magic Linux、CDLinux
-
-使用文泉驿作为默认中文字体
-
-Debian、Gentoo、Mandriva
-
-ArchLinux、Frugalware
-
-则提供了官方源支持
-
-而FreeBSD则在其ports中有提供
-
-所以,今天我们所要分享的就是
-
-文泉驿正黑体
-
-可在Linux/UNIX,Windows
-
-Mac OS和嵌入式操作系统中使用

+ 8 - 1
yudao-framework/yudao-spring-boot-starter-web/pom.xml

@@ -21,6 +21,12 @@
             <artifactId>yudao-common</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
         <!-- Web 相关 -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -35,7 +41,7 @@
 
         <dependency>
             <groupId>com.github.xiaoymin</groupId>
-            <artifactId>knife4j-spring-boot-starter</artifactId>
+            <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
         </dependency>
         <dependency>
             <groupId>io.swagger</groupId>
@@ -72,6 +78,7 @@
             <groupId>org.jsoup</groupId>
             <artifactId>jsoup</artifactId>
         </dependency>
+
     </dependencies>
 
 </project>

+ 18 - 11
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java

@@ -9,15 +9,16 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
 import org.springframework.context.annotation.Bean;
 import org.springframework.http.HttpHeaders;
 import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.ExampleBuilder;
+import springfox.documentation.builders.ParameterBuilder;
 import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestParameterBuilder;
+import springfox.documentation.schema.ModelRef;
 import springfox.documentation.service.*;
 import springfox.documentation.spi.DocumentationType;
 import springfox.documentation.spi.service.contexts.SecurityContext;
 import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
+import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -30,7 +31,7 @@ import static springfox.documentation.builders.RequestHandlerSelectors.basePacka
  * @author 芋道源码
  */
 @AutoConfiguration
-@EnableSwagger2
+@EnableSwagger2WebMvc
 @EnableKnife4j
 @ConditionalOnClass({Docket.class, ApiInfoBuilder.class})
 // 允许使用 swagger.enable=false 禁用 Swagger
@@ -59,7 +60,7 @@ public class YudaoSwaggerAutoConfiguration {
                 .securitySchemes(securitySchemes())
                 .securityContexts(securityContexts())
                 // ④ 全局参数(多租户 header)
-                .globalRequestParameters(globalRequestParameters());
+                .globalOperationParameters(globalRequestParameters());
     }
 
     // ========== apiInfo ==========
@@ -95,7 +96,7 @@ public class YudaoSwaggerAutoConfiguration {
         return Collections.singletonList(SecurityContext.builder()
                 .securityReferences(securityReferences())
                 // 通过 PathSelectors.regex("^(?!auth).*$"),排除包含 "auth" 的接口不需要使用securitySchemes
-                .operationSelector(o -> o.requestMappingPattern().matches("^(?!auth).*$"))
+                .forPaths(PathSelectors.regex("^(?!auth).*$"))
                 .build());
     }
 
@@ -109,11 +110,17 @@ public class YudaoSwaggerAutoConfiguration {
 
     // ========== globalRequestParameters ==========
 
-    private static List<RequestParameter> globalRequestParameters() {
-        RequestParameterBuilder tenantParameter = new RequestParameterBuilder()
-                .name(HEADER_TENANT_ID).description("租户编号")
-                .in(ParameterType.HEADER).example(new ExampleBuilder().value(1L).build());
-        return Collections.singletonList(tenantParameter.build());
+    private static List<Parameter> globalRequestParameters() {
+        List<Parameter> tenantParameter = new ArrayList<>();
+        tenantParameter.add(new ParameterBuilder()
+                .name(HEADER_TENANT_ID)
+                .description("租户编号")
+                .modelRef(new ModelRef("long"))
+                .defaultValue("1")
+                .parameterType("header")
+                .required(true)
+                .build());
+        return tenantParameter;
     }
 
 }

+ 1 - 2
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/core/SpringFoxHandlerProviderBeanPostProcessor.java

@@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.config.BeanPostProcessor;
 import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
-import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
 import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
 
 import java.util.List;
@@ -20,7 +19,7 @@ public class SpringFoxHandlerProviderBeanPostProcessor implements BeanPostProces
 
     @Override
     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
-        if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
+        if (bean instanceof WebMvcRequestHandlerProvider) {
             customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
         }
         return bean;

+ 1 - 5
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/data.ts.vm

@@ -1,8 +1,4 @@
-import { reactive } from 'vue'
-import { useI18n } from '@/hooks/web/useI18n'
-import { DICT_TYPE } from '@/utils/dict'
-import { required } from '@/utils/formRules'
-import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
+import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
 const { t } = useI18n() // 国际化
 // 表单校验
 export const rules = reactive({

+ 0 - 5
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm

@@ -75,11 +75,6 @@
   </XModal>
 </template>
 <script setup lang="ts" name="${simpleClassName}">
-// 全局相关的 import
-import { ref, unref } from 'vue'
-import { useI18n } from '@/hooks/web/useI18n'
-import { useMessage } from '@/hooks/web/useMessage'
-import { useXTable } from '@/hooks/web/useXTable'
 import { FormExpose } from '@/components/Form'
 // 业务相关的 import
 import { rules, allSchemas } from './${classNameVar}.data'

+ 5 - 16
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java

@@ -1,10 +1,11 @@
 package cn.iocoder.yudao.module.system.controller.admin.captcha;
 
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.servlet.ServletUtil;
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
-import com.anji.captcha.model.common.ResponseModel;
-import com.anji.captcha.model.vo.CaptchaVO;
-import com.anji.captcha.service.CaptchaService;
+import com.xingyuv.captcha.model.common.ResponseModel;
+import com.xingyuv.captcha.model.vo.CaptchaVO;
+import com.xingyuv.captcha.service.CaptchaService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -19,9 +20,6 @@ import javax.servlet.http.HttpServletRequest;
 /**
  * 验证码
  *
- * 问题:为什么不直接使用 anji 提供的 CaptchaController,而要另外继承?
- * 回答:管理使用 /admin-api/* 作为前缀,所以需要继承!
- *
  * @author 芋道源码
  */
 @Api(tags = "管理后台 - 验证码")
@@ -52,8 +50,7 @@ public class CaptchaController {
     }
 
     public static String getRemoteId(HttpServletRequest request) {
-        String xfwd = request.getHeader("X-Forwarded-For");
-        String ip = getRemoteIpFromXfwd(xfwd);
+        String ip = ServletUtil.getClientIP(request);
         String ua = request.getHeader("user-agent");
         if (StrUtil.isNotBlank(ip)) {
             return ip + ua;
@@ -61,12 +58,4 @@ public class CaptchaController {
         return request.getRemoteAddr() + ua;
     }
 
-    private static String getRemoteIpFromXfwd(String xfwd) {
-        if (StrUtil.isNotBlank(xfwd)) {
-            String[] ipList = xfwd.split(",");
-            return StrUtil.trim(ipList[0]);
-        }
-        return null;
-    }
-
 }

+ 3 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java

@@ -22,9 +22,9 @@ import cn.iocoder.yudao.module.system.service.member.MemberService;
 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
 import cn.iocoder.yudao.module.system.service.social.SocialUserService;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
-import com.anji.captcha.model.common.ResponseModel;
-import com.anji.captcha.model.vo.CaptchaVO;
-import com.anji.captcha.service.CaptchaService;
+import com.xingyuv.captcha.model.common.ResponseModel;
+import com.xingyuv.captcha.model.vo.CaptchaVO;
+import com.xingyuv.captcha.service.CaptchaService;
 import com.google.common.annotations.VisibleForTesting;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;

+ 259 - 0
yudao-ui-admin-vue3/.eslintrc-auto-import.json

@@ -0,0 +1,259 @@
+{
+  "globals": {
+    "EffectScope": true,
+    "ElMessage": true,
+    "ElMessageBox": true,
+    "ElTag": true,
+    "asyncComputed": true,
+    "autoResetRef": true,
+    "computed": true,
+    "computedAsync": true,
+    "computedEager": true,
+    "computedInject": true,
+    "computedWithControl": true,
+    "controlledComputed": true,
+    "controlledRef": true,
+    "createApp": true,
+    "createEventHook": true,
+    "createGlobalState": true,
+    "createInjectionState": true,
+    "createReactiveFn": true,
+    "createSharedComposable": true,
+    "createUnrefFn": true,
+    "customRef": true,
+    "debouncedRef": true,
+    "debouncedWatch": true,
+    "defineAsyncComponent": true,
+    "defineComponent": true,
+    "eagerComputed": true,
+    "effectScope": true,
+    "extendRef": true,
+    "getCurrentInstance": true,
+    "getCurrentScope": true,
+    "h": true,
+    "ignorableWatch": true,
+    "inject": true,
+    "isDefined": true,
+    "isProxy": true,
+    "isReactive": true,
+    "isReadonly": true,
+    "isRef": true,
+    "makeDestructurable": true,
+    "markRaw": true,
+    "nextTick": true,
+    "onActivated": true,
+    "onBeforeMount": true,
+    "onBeforeUnmount": true,
+    "onBeforeUpdate": true,
+    "onClickOutside": true,
+    "onDeactivated": true,
+    "onErrorCaptured": true,
+    "onKeyStroke": true,
+    "onLongPress": true,
+    "onMounted": true,
+    "onRenderTracked": true,
+    "onRenderTriggered": true,
+    "onScopeDispose": true,
+    "onServerPrefetch": true,
+    "onStartTyping": true,
+    "onUnmounted": true,
+    "onUpdated": true,
+    "pausableWatch": true,
+    "provide": true,
+    "reactify": true,
+    "reactifyObject": true,
+    "reactive": true,
+    "reactiveComputed": true,
+    "reactiveOmit": true,
+    "reactivePick": true,
+    "readonly": true,
+    "ref": true,
+    "refAutoReset": true,
+    "refDebounced": true,
+    "refDefault": true,
+    "refThrottled": true,
+    "refWithControl": true,
+    "resolveComponent": true,
+    "resolveRef": true,
+    "resolveUnref": true,
+    "shallowReactive": true,
+    "shallowReadonly": true,
+    "shallowRef": true,
+    "syncRef": true,
+    "syncRefs": true,
+    "templateRef": true,
+    "throttledRef": true,
+    "throttledWatch": true,
+    "toRaw": true,
+    "toReactive": true,
+    "toRef": true,
+    "toRefs": true,
+    "triggerRef": true,
+    "tryOnBeforeMount": true,
+    "tryOnBeforeUnmount": true,
+    "tryOnMounted": true,
+    "tryOnScopeDispose": true,
+    "tryOnUnmounted": true,
+    "unref": true,
+    "unrefElement": true,
+    "until": true,
+    "useActiveElement": true,
+    "useArrayEvery": true,
+    "useArrayFilter": true,
+    "useArrayFind": true,
+    "useArrayFindIndex": true,
+    "useArrayJoin": true,
+    "useArrayMap": true,
+    "useArrayReduce": true,
+    "useArraySome": true,
+    "useAsyncQueue": true,
+    "useAsyncState": true,
+    "useAttrs": true,
+    "useBase64": true,
+    "useBattery": true,
+    "useBluetooth": true,
+    "useBreakpoints": true,
+    "useBroadcastChannel": true,
+    "useBrowserLocation": true,
+    "useCached": true,
+    "useClipboard": true,
+    "useColorMode": true,
+    "useConfirmDialog": true,
+    "useCounter": true,
+    "useCssModule": true,
+    "useCssVar": true,
+    "useCssVars": true,
+    "useCurrentElement": true,
+    "useCycleList": true,
+    "useDark": true,
+    "useDateFormat": true,
+    "useDebounce": true,
+    "useDebounceFn": true,
+    "useDebouncedRefHistory": true,
+    "useDeviceMotion": true,
+    "useDeviceOrientation": true,
+    "useDevicePixelRatio": true,
+    "useDevicesList": true,
+    "useDisplayMedia": true,
+    "useDocumentVisibility": true,
+    "useDraggable": true,
+    "useDropZone": true,
+    "useElementBounding": true,
+    "useElementByPoint": true,
+    "useElementHover": true,
+    "useElementSize": true,
+    "useElementVisibility": true,
+    "useEventBus": true,
+    "useEventListener": true,
+    "useEventSource": true,
+    "useEyeDropper": true,
+    "useFavicon": true,
+    "useFetch": true,
+    "useFileDialog": true,
+    "useFileSystemAccess": true,
+    "useFocus": true,
+    "useFocusWithin": true,
+    "useFps": true,
+    "useFullscreen": true,
+    "useGamepad": true,
+    "useGeolocation": true,
+    "useIdle": true,
+    "useImage": true,
+    "useInfiniteScroll": true,
+    "useIntersectionObserver": true,
+    "useInterval": true,
+    "useIntervalFn": true,
+    "useKeyModifier": true,
+    "useLastChanged": true,
+    "useLocalStorage": true,
+    "useMagicKeys": true,
+    "useManualRefHistory": true,
+    "useMediaControls": true,
+    "useMediaQuery": true,
+    "useMemoize": true,
+    "useMemory": true,
+    "useMounted": true,
+    "useMouse": true,
+    "useMouseInElement": true,
+    "useMousePressed": true,
+    "useMutationObserver": true,
+    "useNavigatorLanguage": true,
+    "useNetwork": true,
+    "useNow": true,
+    "useObjectUrl": true,
+    "useOffsetPagination": true,
+    "useOnline": true,
+    "usePageLeave": true,
+    "useParallax": true,
+    "usePermission": true,
+    "usePointer": true,
+    "usePointerSwipe": true,
+    "usePreferredColorScheme": true,
+    "usePreferredDark": true,
+    "usePreferredLanguages": true,
+    "useRafFn": true,
+    "useRefHistory": true,
+    "useResizeObserver": true,
+    "useRoute": true,
+    "useRouter": true,
+    "useScreenOrientation": true,
+    "useScreenSafeArea": true,
+    "useScriptTag": true,
+    "useScroll": true,
+    "useScrollLock": true,
+    "useSessionStorage": true,
+    "useShare": true,
+    "useSlots": true,
+    "useSpeechRecognition": true,
+    "useSpeechSynthesis": true,
+    "useStepper": true,
+    "useStorage": true,
+    "useStorageAsync": true,
+    "useStyleTag": true,
+    "useSupported": true,
+    "useSwipe": true,
+    "useTemplateRefsList": true,
+    "useTextDirection": true,
+    "useTextSelection": true,
+    "useTextareaAutosize": true,
+    "useThrottle": true,
+    "useThrottleFn": true,
+    "useThrottledRefHistory": true,
+    "useTimeAgo": true,
+    "useTimeout": true,
+    "useTimeoutFn": true,
+    "useTimeoutPoll": true,
+    "useTimestamp": true,
+    "useTitle": true,
+    "useToggle": true,
+    "useTransition": true,
+    "useUrlSearchParams": true,
+    "useUserMedia": true,
+    "useVModel": true,
+    "useVModels": true,
+    "useVibrate": true,
+    "useVirtualList": true,
+    "useWakeLock": true,
+    "useWebNotification": true,
+    "useWebSocket": true,
+    "useWebWorker": true,
+    "useWebWorkerFn": true,
+    "useWindowFocus": true,
+    "useWindowScroll": true,
+    "useWindowSize": true,
+    "watch": true,
+    "watchArray": true,
+    "watchAtMost": true,
+    "watchDebounced": true,
+    "watchEffect": true,
+    "watchIgnorable": true,
+    "watchOnce": true,
+    "watchPausable": true,
+    "watchPostEffect": true,
+    "watchSyncEffect": true,
+    "watchThrottled": true,
+    "watchTriggerable": true,
+    "watchWithFilter": true,
+    "whenever": true
+  }
+}

+ 2 - 1
yudao-ui-admin-vue3/.eslintrc.js

@@ -21,7 +21,8 @@ module.exports = defineConfig({
     'plugin:vue/vue3-recommended',
     'plugin:@typescript-eslint/recommended',
     'prettier',
-    'plugin:prettier/recommended'
+    'plugin:prettier/recommended',
+    './.eslintrc-auto-import.json'
   ],
   rules: {
     'vue/script-setup-uses-vars': 'error',

+ 43 - 21
yudao-ui-admin-vue3/build/vite/index.ts

@@ -6,15 +6,14 @@ import progress from 'vite-plugin-progress'
 import EslintPlugin from 'vite-plugin-eslint'
 import PurgeIcons from 'vite-plugin-purge-icons'
 import { ViteEjsPlugin } from 'vite-plugin-ejs'
+import ElementPlus from 'unplugin-element-plus/vite'
+import AutoImport from 'unplugin-auto-import/vite'
+import Components from 'unplugin-vue-components/vite'
+import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
 import viteCompression from 'vite-plugin-compression'
 import vueSetupExtend from 'vite-plugin-vue-setup-extend'
 import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
 import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
-import {
-  createStyleImportPlugin,
-  ElementPlusResolve,
-  VxeTableResolve
-} from 'vite-plugin-style-import'
 export function createVitePlugins(VITE_APP_TITLE: string) {
   const root = process.cwd()
   // 路径查找
@@ -28,24 +27,47 @@ export function createVitePlugins(VITE_APP_TITLE: string) {
     progress(),
     PurgeIcons(),
     vueSetupExtend(),
-    createStyleImportPlugin({
-      resolves: [ElementPlusResolve(), VxeTableResolve()],
-      libs: [
+    ElementPlus(),
+    AutoImport({
+      include: [
+        /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
+        /\.vue$/,
+        /\.vue\?vue/, // .vue
+        /\.md$/ // .md
+      ],
+      imports: [
+        'vue',
+        'vue-router',
         {
-          libraryName: 'element-plus',
-          esModule: true,
-          resolveStyle: (name) => {
-            return `element-plus/es/components/${name.substring(3)}/style/css`
-          }
-        },
-        {
-          libraryName: 'vxe-table',
-          esModule: true,
-          resolveStyle: (name) => {
-            return `vxe-table/es/${name}/style.css`
-          }
+          '@/hooks/web/useI18n': ['useI18n'],
+          '@/hooks/web/useXTable': ['useXTable'],
+          '@/hooks/web/useMessage': ['useMessage'],
+          '@/hooks/web/useVxeCrudSchemas': ['useVxeCrudSchemas'],
+          '@/utils/formRules': ['required'],
+          '@/utils/dict': ['DICT_TYPE']
         }
-      ]
+      ],
+      dts: 'src/types/auto-imports.d.ts',
+      resolvers: [ElementPlusResolver()],
+      eslintrc: {
+        enabled: false, // Default `false`
+        filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
+        globalsPropValue: true // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
+      }
+    }),
+    Components({
+      // 要搜索组件的目录的相对路径
+      dirs: ['src/components'],
+      // 组件的有效文件扩展名
+      extensions: ['vue', 'md'],
+      // 搜索子目录
+      deep: true,
+      include: [/\.vue$/, /\.vue\?vue/],
+      // 生成自定义 `auto-components.d.ts` 全局声明
+      dts: 'src/types/auto-components.d.ts',
+      // 自定义组件的解析器
+      resolvers: [ElementPlusResolver()],
+      exclude: [/[\\/]node_modules[\\/]/]
     }),
     EslintPlugin({
       cache: false,

+ 1 - 0
yudao-ui-admin-vue3/build/vite/optimize.ts

@@ -21,6 +21,7 @@ const include = [
   'vxe-table/es/style',
   'web-storage-cache',
   'element-plus',
+  'element-plus/es',
   'element-plus/es/locale/lang/zh-cn',
   'element-plus/es/locale/lang/en',
   '@iconify/iconify',

+ 0 - 18
yudao-ui-admin-vue3/build/vite/styleImport.ts

@@ -1,18 +0,0 @@
-export const styleImportPlugin = {
-  libs: [
-    {
-      libraryName: 'element-plus',
-      esModule: true,
-      resolveStyle: (name) => {
-        return `element-plus/es/components/${name.substring(3)}/style/css`
-      }
-    },
-    {
-      libraryName: 'vxe-table',
-      esModule: true,
-      resolveStyle: (name) => {
-        return `vxe-table/es/${name}/style.css`
-      }
-    }
-  ]
-}

+ 13 - 11
yudao-ui-admin-vue3/package.json

@@ -1,6 +1,6 @@
 {
   "name": "yudao-ui-admin-vue3",
-  "version": "1.6.6-snapshot.1912",
+  "version": "1.6.6-snapshot.1925",
   "description": "基于vue3、vite4、element-plus、typesScript",
   "author": "xingyu",
   "private": false,
@@ -25,12 +25,12 @@
   },
   "dependencies": {
     "@iconify/iconify": "^3.0.1",
-    "@vueuse/core": "^9.10.0",
+    "@vueuse/core": "^9.11.0",
     "@wangeditor/editor": "^5.1.23",
     "@wangeditor/editor-for-vue": "^5.1.10",
     "@zxcvbn-ts/core": "^2.1.0",
     "animate.css": "^4.1.1",
-    "axios": "^1.2.2",
+    "axios": "^1.2.3",
     "cropperjs": "^1.5.13",
     "crypto-js": "^4.1.1",
     "dayjs": "^1.11.7",
@@ -42,7 +42,7 @@
     "lodash-es": "^4.17.21",
     "mitt": "^3.0.0",
     "nprogress": "^0.2.0",
-    "pinia": "^2.0.28",
+    "pinia": "^2.0.29",
     "qrcode": "^1.5.1",
     "qs": "^6.11.0",
     "url": "^0.11.0",
@@ -57,7 +57,7 @@
   "devDependencies": {
     "@commitlint/cli": "^17.4.2",
     "@commitlint/config-conventional": "^17.4.2",
-    "@iconify/json": "^2.2.6",
+    "@iconify/json": "^2.2.8",
     "@intlify/unplugin-vue-i18n": "^0.8.1",
     "@purge-icons/generated": "^0.9.0",
     "@types/intro.js": "^5.1.0",
@@ -66,14 +66,14 @@
     "@types/nprogress": "^0.2.0",
     "@types/qrcode": "^1.5.0",
     "@types/qs": "^6.9.7",
-    "@typescript-eslint/eslint-plugin": "^5.48.1",
-    "@typescript-eslint/parser": "^5.48.1",
+    "@typescript-eslint/eslint-plugin": "^5.48.2",
+    "@typescript-eslint/parser": "^5.48.2",
     "@vitejs/plugin-legacy": "^3.0.1",
     "@vitejs/plugin-vue": "^4.0.0",
     "@vitejs/plugin-vue-jsx": "^3.0.0",
     "autoprefixer": "^10.4.13",
     "consola": "^2.15.3",
-    "eslint": "^8.31.0",
+    "eslint": "^8.32.0",
     "eslint-config-prettier": "^8.6.0",
     "eslint-define-config": "^1.14.0",
     "eslint-plugin-prettier": "^4.2.1",
@@ -82,8 +82,8 @@
     "postcss": "^8.4.21",
     "postcss-html": "^1.5.0",
     "postcss-scss": "^4.0.6",
-    "prettier": "^2.8.2",
-    "rimraf": "^4.0.4",
+    "prettier": "^2.8.3",
+    "rimraf": "^4.1.1",
     "rollup": "^3.10.0",
     "sass": "^1.57.1",
     "stylelint": "^14.16.1",
@@ -94,13 +94,15 @@
     "stylelint-order": "^6.0.1",
     "terser": "^5.16.1",
     "typescript": "4.9.4",
+    "unplugin-auto-import": "^0.12.1",
+    "unplugin-element-plus": "^0.4.1",
+    "unplugin-vue-components": "^0.22.12",
     "vite": "4.0.4",
     "vite-plugin-compression": "^0.5.1",
     "vite-plugin-ejs": "^1.6.4",
     "vite-plugin-eslint": "^1.8.1",
     "vite-plugin-progress": "^0.0.6",
     "vite-plugin-purge-icons": "^0.9.2",
-    "vite-plugin-style-import": "2.0.0",
     "vite-plugin-svg-icons": "^2.0.1",
     "vite-plugin-vue-setup-extend": "^0.4.0",
     "vite-plugin-windicss": "^1.8.10",

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 290 - 250
yudao-ui-admin-vue3/pnpm-lock.yaml


+ 0 - 2
yudao-ui-admin-vue3/src/App.vue

@@ -1,9 +1,7 @@
 <script setup lang="ts">
-import { computed } from 'vue'
 import { isDark } from '@/utils/is'
 import { useAppStore } from '@/store/modules/app'
 import { useDesign } from '@/hooks/web/useDesign'
-import { ConfigGlobal } from '@/components/ConfigGlobal'
 import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
 
 const { getPrefixCls } = useDesign()

+ 1 - 1
yudao-ui-admin-vue3/src/api/login/index.ts

@@ -33,7 +33,7 @@ export const getTenantIdByNameApi = (name: string) => {
 
 // 登出
 export const loginOutApi = () => {
-  return request.delete({ url: '/system/auth/logout' })
+  return request.post({ url: '/system/auth/logout' })
 }
 
 // 获取用户权限信息

+ 1 - 3
yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue

@@ -1,13 +1,11 @@
 <script setup lang="ts">
-import { provide, computed, watch, onMounted } from 'vue'
 import { propTypes } from '@/utils/propTypes'
-import { ElConfigProvider } from 'element-plus'
 import { useLocaleStore } from '@/store/modules/locale'
-import { useWindowSize } from '@vueuse/core'
 import { useAppStore } from '@/store/modules/app'
 import { setCssVar } from '@/utils'
 import { useDesign } from '@/hooks/web/useDesign'
 import { ElementPlusSize } from '@/types/elementPlus'
+import { useWindowSize } from '@vueuse/core'
 
 const { variables } = useDesign()
 

+ 1 - 4
yudao-ui-admin-vue3/src/components/ContentDetailWrap/src/ContentDetailWrap.vue

@@ -1,10 +1,7 @@
 <script setup lang="ts">
-import { ElCard } from 'element-plus'
 import { propTypes } from '@/utils/propTypes'
 import { useDesign } from '@/hooks/web/useDesign'
-import { ref, onMounted } from 'vue'
-import { Sticky } from '@/components/Sticky'
-import { useI18n } from '@/hooks/web/useI18n'
+
 const { t } = useI18n()
 
 const { getPrefixCls } = useDesign()

+ 1 - 1
yudao-ui-admin-vue3/src/components/CountTo/src/CountTo.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { reactive, computed, watch, onMounted, unref, toRef, PropType } from 'vue'
+import { PropType } from 'vue'
 import { isNumber } from '@/utils/is'
 import { propTypes } from '@/utils/propTypes'
 import { useDesign } from '@/hooks/web/useDesign'

+ 2 - 15
yudao-ui-admin-vue3/src/components/Crontab/src/Crontab.vue

@@ -1,19 +1,6 @@
 <script setup lang="ts">
-import {
-  ElInput,
-  ElInputNumber,
-  ElDialog,
-  ElTabs,
-  ElTabPane,
-  ElSelect,
-  ElOption,
-  ElForm,
-  ElFormItem,
-  ElRadioGroup,
-  ElRadioButton,
-  ElMessage
-} from 'element-plus'
-import { ref, computed, onMounted, reactive, watch, PropType } from 'vue'
+import { ElMessage } from 'element-plus'
+import { PropType } from 'vue'
 interface shortcutsType {
   text: string
   value: string

+ 0 - 4
yudao-ui-admin-vue3/src/components/Cropper/src/CopperModal.vue

@@ -116,11 +116,7 @@
 <script setup lang="ts">
 import { useDesign } from '@/hooks/web/useDesign'
 import { dataURLtoBlob } from '@/utils/filt'
-import { ref } from 'vue'
 import { useI18n } from 'vue-i18n'
-import { ElUpload, ElAvatar, ElTooltip, ElSpace } from 'element-plus'
-import { Dialog } from '@/components/Dialog'
-import { CropperImage } from '@/components/Cropper'
 import type { CropendResult, Cropper } from './types'
 import { propTypes } from '@/utils/propTypes'
 

+ 2 - 11
yudao-ui-admin-vue3/src/components/Cropper/src/Cropper.vue

@@ -11,21 +11,12 @@
   </div>
 </template>
 <script setup lang="ts">
-import {
-  computed,
-  CSSProperties,
-  onMounted,
-  onUnmounted,
-  PropType,
-  ref,
-  unref,
-  useAttrs
-} from 'vue'
+import { CSSProperties, PropType } from 'vue'
 import Cropper from 'cropperjs'
 import 'cropperjs/dist/cropper.css'
 import { useDesign } from '@/hooks/web/useDesign'
-import { useDebounceFn } from '@vueuse/core'
 import { propTypes } from '@/utils/propTypes'
+import { useDebounceFn } from '@vueuse/core'
 
 type Options = Cropper.Options
 

+ 1 - 2
yudao-ui-admin-vue3/src/components/Cropper/src/CropperAvatar.vue

@@ -13,9 +13,8 @@
 </template>
 <script setup lang="ts">
 import { useDesign } from '@/hooks/web/useDesign'
-import { useMessage } from '@/hooks/web/useMessage'
+
 import { propTypes } from '@/utils/propTypes'
-import { ref, watch, watchEffect } from 'vue'
 import { useI18n } from 'vue-i18n'
 import CopperModal from './CopperModal.vue'
 

+ 2 - 3
yudao-ui-admin-vue3/src/components/Descriptions/src/Descriptions.vue

@@ -1,9 +1,8 @@
 <script setup lang="ts">
+import { PropType } from 'vue'
 import dayjs from 'dayjs'
-import { ElCollapseTransition, ElDescriptions, ElDescriptionsItem, ElTooltip } from 'element-plus'
 import { useDesign } from '@/hooks/web/useDesign'
 import { propTypes } from '@/utils/propTypes'
-import { ref, unref, PropType, computed, useAttrs, useSlots } from 'vue'
 import { useAppStore } from '@/store/modules/app'
 import { DescriptionsSchema } from '@/types/descriptions'
 
@@ -25,7 +24,7 @@ const props = defineProps({
     default: () => []
   },
   data: {
-    type: Object as PropType<Recordable>,
+    type: Object as PropType<any>,
     default: () => ({})
   }
 })

+ 0 - 2
yudao-ui-admin-vue3/src/components/Dialog/src/Dialog.vue

@@ -1,7 +1,5 @@
 <script setup lang="ts">
-import { ElDialog, ElScrollbar } from 'element-plus'
 import { propTypes } from '@/utils/propTypes'
-import { computed, useAttrs, ref, unref, useSlots, watch, nextTick } from 'vue'
 import { isNumber } from '@/utils/is'
 
 const slots = useSlots()

+ 48 - 51
yudao-ui-admin-vue3/src/components/DictTag/src/DictTag.vue

@@ -1,56 +1,53 @@
-<script setup lang="ts">
-import { onMounted, onUpdated, PropType, ref } from 'vue'
-import { getDictOptions, DictDataType } from '@/utils/dict'
+<script lang="tsx">
+import { defineComponent, PropType, ref } from 'vue'
+import { isHexColor } from '@/utils/color'
 import { ElTag } from 'element-plus'
-const props = defineProps({
-  type: {
-    type: String as PropType<string>,
-    required: true
+import { DictDataType, getDictOptions } from '@/utils/dict'
+
+export default defineComponent({
+  name: 'DictTag',
+  props: {
+    type: {
+      type: String as PropType<string>,
+      required: true
+    },
+    value: {
+      type: [String, Number, Boolean] as PropType<string | number | boolean>,
+      required: true
+    }
   },
-  value: {
-    type: [String, Number, Boolean] as PropType<string | number | boolean>,
-    required: true
-  }
-})
-const dictData = ref<DictDataType>()
-const getDictObj = (dictType: string, value: string) => {
-  const dictOptions = getDictOptions(dictType)
-  dictOptions.forEach((dict: DictDataType) => {
-    if (dict.value === value) {
-      dictData.value = dict
+  setup(props) {
+    const dictData = ref<DictDataType>()
+    const getDictObj = (dictType: string, value: string) => {
+      const dictOptions = getDictOptions(dictType)
+      dictOptions.forEach((dict: DictDataType) => {
+        if (dict.value === value) {
+          if (dict.colorType + '' === 'primary' || dict.colorType + '' === 'default') {
+            dict.colorType = ''
+          }
+          dictData.value = dict
+        }
+      })
     }
-  })
-}
-
-onMounted(() => {
-  return getDictObj(props.type, props.value?.toString())
-})
-
-onUpdated(() => {
-  getDictObj(props.type, props.value?.toString())
+    const rederDictTag = () => {
+      if (!props.type) {
+        return null
+      }
+      getDictObj(props.type, props.value.toString())
+      return (
+        <ElTag
+          type={dictData.value?.colorType}
+          color={
+            dictData.value?.cssClass && isHexColor(dictData.value?.cssClass)
+              ? dictData.value?.cssClass
+              : ''
+          }
+        >
+          {dictData.value?.label}
+        </ElTag>
+      )
+    }
+    return () => rederDictTag()
+  }
 })
 </script>
-<template>
-  <!-- 默认样式 -->
-  <span
-    v-if="
-      dictData?.colorType === 'default' ||
-      dictData?.colorType === '' ||
-      dictData?.colorType === undefined
-    "
-    :key="dictData?.value.toString()"
-    :class="dictData?.cssClass"
-  >
-    {{ dictData?.label }}
-  </span>
-  <!-- Tag 样式 -->
-  <ElTag
-    v-else
-    :disable-transitions="true"
-    :key="dictData?.value + ''"
-    :type="dictData?.colorType === 'primary' ? 'success' : dictData?.colorType"
-    :class="dictData?.cssClass"
-  >
-    {{ dictData?.label }}
-  </ElTag>
-</template>

+ 1 - 1
yudao-ui-admin-vue3/src/components/Echart/src/Echart.vue

@@ -4,7 +4,7 @@ import echarts from '@/plugins/echarts'
 import { debounce } from 'lodash-es'
 import 'echarts-wordcloud'
 import { propTypes } from '@/utils/propTypes'
-import { computed, PropType, ref, unref, watch, onMounted, onBeforeUnmount, onActivated } from 'vue'
+import { PropType } from 'vue'
 import { useAppStore } from '@/store/modules/app'
 import { isString } from '@/utils/is'
 import { useDesign } from '@/hooks/web/useDesign'

+ 1 - 1
yudao-ui-admin-vue3/src/components/Editor/src/Editor.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { onBeforeUnmount, computed, PropType, unref, nextTick, ref, watch, shallowRef } from 'vue'
+import { PropType } from 'vue'
 import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
 import { IDomEditor, IEditorConfig, i18nChangeLanguage } from '@wangeditor/editor'
 import { propTypes } from '@/utils/propTypes'

+ 0 - 0
yudao-ui-admin-vue3/src/components/Error/src/Error.vue


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác