Commit aaf62982e277f573a0c7b271aa4e2ba7faee21ce

Authored by xingyu
1 parent 865f1010

feat: 优化 captcha 代码

Showing 33 changed files with 476 additions and 2759 deletions
yudao-framework/yudao-spring-boot-starter-captcha/pom.xml
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 <dependency> 21 <dependency>
22 <groupId>org.springframework.boot</groupId> 22 <groupId>org.springframework.boot</groupId>
23 <artifactId>spring-boot-starter</artifactId> 23 <artifactId>spring-boot-starter</artifactId>
  24 + <scope>provided</scope>
24 </dependency> 25 </dependency>
25 26
26 <dependency> 27 <dependency>
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/config/AjCaptchaServiceAutoConfiguration.java
1 package com.anji.captcha.config; 1 package com.anji.captcha.config;
2 2
  3 +import cn.hutool.core.util.StrUtil;
3 import com.anji.captcha.model.common.Const; 4 import com.anji.captcha.model.common.Const;
4 import com.anji.captcha.properties.AjCaptchaProperties; 5 import com.anji.captcha.properties.AjCaptchaProperties;
5 import com.anji.captcha.service.CaptchaService; 6 import com.anji.captcha.service.CaptchaService;
6 import com.anji.captcha.service.impl.CaptchaServiceFactory; 7 import com.anji.captcha.service.impl.CaptchaServiceFactory;
7 import com.anji.captcha.util.ImageUtils; 8 import com.anji.captcha.util.ImageUtils;
8 -import com.anji.captcha.util.StringUtils;  
9 -import org.slf4j.Logger;  
10 -import org.slf4j.LoggerFactory; 9 +import lombok.extern.slf4j.Slf4j;
11 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 10 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
12 import org.springframework.context.annotation.Bean; 11 import org.springframework.context.annotation.Bean;
13 import org.springframework.context.annotation.Configuration; 12 import org.springframework.context.annotation.Configuration;
@@ -21,15 +20,14 @@ import java.util.HashMap; @@ -21,15 +20,14 @@ import java.util.HashMap;
21 import java.util.Map; 20 import java.util.Map;
22 import java.util.Properties; 21 import java.util.Properties;
23 22
  23 +@Slf4j
24 @Configuration 24 @Configuration
25 public class AjCaptchaServiceAutoConfiguration { 25 public class AjCaptchaServiceAutoConfiguration {
26 26
27 - private static Logger logger = LoggerFactory.getLogger(AjCaptchaServiceAutoConfiguration.class);  
28 -  
29 @Bean 27 @Bean
30 @ConditionalOnMissingBean 28 @ConditionalOnMissingBean
31 public CaptchaService captchaService(AjCaptchaProperties prop) { 29 public CaptchaService captchaService(AjCaptchaProperties prop) {
32 - logger.info("自定义配置项:{}", prop.toString()); 30 + log.info("自定义配置项:{}", prop.toString());
33 Properties config = new Properties(); 31 Properties config = new Properties();
34 config.put(Const.CAPTCHA_CACHETYPE, prop.getCacheType().name()); 32 config.put(Const.CAPTCHA_CACHETYPE, prop.getCacheType().name());
35 config.put(Const.CAPTCHA_WATER_MARK, prop.getWaterMark()); 33 config.put(Const.CAPTCHA_WATER_MARK, prop.getWaterMark());
@@ -57,14 +55,13 @@ public class AjCaptchaServiceAutoConfiguration { @@ -57,14 +55,13 @@ public class AjCaptchaServiceAutoConfiguration {
57 config.put(Const.CAPTCHA_FONT_STYLE, prop.getFontStyle() + ""); 55 config.put(Const.CAPTCHA_FONT_STYLE, prop.getFontStyle() + "");
58 config.put(Const.CAPTCHA_WORD_COUNT, prop.getClickWordCount() + ""); 56 config.put(Const.CAPTCHA_WORD_COUNT, prop.getClickWordCount() + "");
59 57
60 - if ((StringUtils.isNotBlank(prop.getJigsaw()) && prop.getJigsaw().startsWith("classpath:"))  
61 - || (StringUtils.isNotBlank(prop.getPicClick()) && prop.getPicClick().startsWith("classpath:"))) { 58 + if ((StrUtil.isNotBlank(prop.getJigsaw()) && prop.getJigsaw().startsWith("classpath:"))
  59 + || (StrUtil.isNotBlank(prop.getPicClick()) && prop.getPicClick().startsWith("classpath:"))) {
62 //自定义resources目录下初始化底图 60 //自定义resources目录下初始化底图
63 config.put(Const.CAPTCHA_INIT_ORIGINAL, "true"); 61 config.put(Const.CAPTCHA_INIT_ORIGINAL, "true");
64 initializeBaseMap(prop.getJigsaw(), prop.getPicClick()); 62 initializeBaseMap(prop.getJigsaw(), prop.getPicClick());
65 } 63 }
66 - CaptchaService s = CaptchaServiceFactory.getInstance(config);  
67 - return s; 64 + return CaptchaServiceFactory.getInstance(config);
68 } 65 }
69 66
70 private static void initializeBaseMap(String jigsaw, String picClick) { 67 private static void initializeBaseMap(String jigsaw, String picClick) {
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/config/AjCaptchaStorageAutoConfiguration.java
@@ -8,14 +8,13 @@ import org.springframework.context.annotation.Configuration; @@ -8,14 +8,13 @@ import org.springframework.context.annotation.Configuration;
8 8
9 /** 9 /**
10 * 存储策略自动配置. 10 * 存储策略自动配置.
11 - *  
12 */ 11 */
13 @Configuration 12 @Configuration
14 public class AjCaptchaStorageAutoConfiguration { 13 public class AjCaptchaStorageAutoConfiguration {
15 14
16 @Bean(name = "AjCaptchaCacheService") 15 @Bean(name = "AjCaptchaCacheService")
17 - public CaptchaCacheService captchaCacheService(AjCaptchaProperties ajCaptchaProperties){  
18 - //缓存类型redis/local/.... 16 + public CaptchaCacheService captchaCacheService(AjCaptchaProperties ajCaptchaProperties) {
  17 + // 缓存类型redis/local/....
19 return CaptchaServiceFactory.getCache(ajCaptchaProperties.getCacheType().name()); 18 return CaptchaServiceFactory.getCache(ajCaptchaProperties.getCacheType().name());
20 } 19 }
21 } 20 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/controller/CaptchaController.java deleted
1 -/*  
2 - *Copyright © 2018 anji-plus  
3 - *安吉加加信息技术有限公司  
4 - *http://www.anji-plus.com  
5 - *All rights reserved.  
6 - */  
7 -package com.anji.captcha.controller;  
8 -  
9 -import com.anji.captcha.model.common.ResponseModel;  
10 -import com.anji.captcha.model.vo.CaptchaVO;  
11 -import com.anji.captcha.service.CaptchaService;  
12 -import com.anji.captcha.util.StringUtils;  
13 -import org.springframework.beans.factory.annotation.Autowired;  
14 -import org.springframework.web.bind.annotation.PostMapping;  
15 -import org.springframework.web.bind.annotation.RequestBody;  
16 -import org.springframework.web.bind.annotation.RequestMapping;  
17 -import org.springframework.web.bind.annotation.RestController;  
18 -  
19 -import javax.servlet.http.HttpServletRequest;  
20 -  
21 -  
22 -@RestController  
23 -@RequestMapping("/captcha")  
24 -public class CaptchaController {  
25 -  
26 - @Autowired  
27 - private CaptchaService captchaService;  
28 -  
29 - @PostMapping("/get")  
30 - public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {  
31 - assert request.getRemoteHost()!=null;  
32 - data.setBrowserInfo(getRemoteId(request));  
33 - return captchaService.get(data);  
34 - }  
35 -  
36 - @PostMapping("/check")  
37 - public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {  
38 - data.setBrowserInfo(getRemoteId(request));  
39 - return captchaService.check(data);  
40 - }  
41 -  
42 - //@PostMapping("/verify")  
43 - public ResponseModel verify(@RequestBody CaptchaVO data, HttpServletRequest request) {  
44 - return captchaService.verification(data);  
45 - }  
46 -  
47 - public static final String getRemoteId(HttpServletRequest request) {  
48 - String xfwd = request.getHeader("X-Forwarded-For");  
49 - String ip = getRemoteIpFromXfwd(xfwd);  
50 - String ua = request.getHeader("user-agent");  
51 - if (StringUtils.isNotBlank(ip)) {  
52 - return ip + ua;  
53 - }  
54 - return request.getRemoteAddr() + ua;  
55 - }  
56 -  
57 - private static String getRemoteIpFromXfwd(String xfwd) {  
58 - if (StringUtils.isNotBlank(xfwd)) {  
59 - String[] ipList = xfwd.split(",");  
60 - return StringUtils.trim(ipList[0]);  
61 - }  
62 - return null;  
63 - }  
64 -  
65 -}  
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/CaptchaBaseMapEnum.java
1 package com.anji.captcha.model.common; 1 package com.anji.captcha.model.common;
2 2
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
3 /** 6 /**
4 * 底图类型枚举 7 * 底图类型枚举
5 */ 8 */
  9 +@Getter
  10 +@AllArgsConstructor
6 public enum CaptchaBaseMapEnum { 11 public enum CaptchaBaseMapEnum {
7 - ORIGINAL("ORIGINAL","滑动拼图底图"),  
8 - SLIDING_BLOCK("SLIDING_BLOCK","滑动拼图滑块底图"),  
9 - PIC_CLICK("PIC_CLICK","文字点选底图");  
10 -  
11 - private String codeValue;  
12 - private String codeDesc;  
13 -  
14 - private CaptchaBaseMapEnum(String codeValue, String codeDesc) {  
15 - this.codeValue = codeValue;  
16 - this.codeDesc = codeDesc;  
17 - }  
18 -  
19 - public String getCodeValue(){ return this.codeValue;} 12 + ORIGINAL("ORIGINAL", "滑动拼图底图"),
  13 + SLIDING_BLOCK("SLIDING_BLOCK", "滑动拼图滑块底图"),
  14 + PIC_CLICK("PIC_CLICK", "文字点选底图");
20 15
21 - public String getCodeDesc(){ return this.codeDesc;} 16 + private final String codeValue;
  17 + private final String codeDesc;
22 18
23 //根据codeValue获取枚举 19 //根据codeValue获取枚举
24 - public static CaptchaBaseMapEnum parseFromCodeValue(String codeValue){  
25 - for (CaptchaBaseMapEnum e : CaptchaBaseMapEnum.values()){  
26 - if(e.codeValue.equals(codeValue)){ return e;} 20 + public static CaptchaBaseMapEnum parseFromCodeValue(String codeValue) {
  21 + for (CaptchaBaseMapEnum e : CaptchaBaseMapEnum.values()) {
  22 + if (e.codeValue.equals(codeValue)) {
  23 + return e;
  24 + }
27 } 25 }
28 return null; 26 return null;
29 } 27 }
30 28
31 //根据codeValue获取描述 29 //根据codeValue获取描述
32 - public static String getCodeDescByCodeBalue(String codeValue){ 30 + public static String getCodeDescByCodeBalue(String codeValue) {
33 CaptchaBaseMapEnum enumItem = parseFromCodeValue(codeValue); 31 CaptchaBaseMapEnum enumItem = parseFromCodeValue(codeValue);
34 return enumItem == null ? "" : enumItem.getCodeDesc(); 32 return enumItem == null ? "" : enumItem.getCodeDesc();
35 } 33 }
36 34
37 //验证codeValue是否有效 35 //验证codeValue是否有效
38 - public static boolean validateCodeValue(String codeValue){ return parseFromCodeValue(codeValue)!=null;} 36 + public static boolean validateCodeValue(String codeValue) {
  37 + return parseFromCodeValue(codeValue) != null;
  38 + }
39 39
40 //列出所有值字符串 40 //列出所有值字符串
41 - public static String getString(){ 41 + public static String getString() {
42 StringBuffer buffer = new StringBuffer(); 42 StringBuffer buffer = new StringBuffer();
43 - for (CaptchaBaseMapEnum e : CaptchaBaseMapEnum.values()){ 43 + for (CaptchaBaseMapEnum e : CaptchaBaseMapEnum.values()) {
44 buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", "); 44 buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", ");
45 } 45 }
46 buffer.deleteCharAt(buffer.lastIndexOf(",")); 46 buffer.deleteCharAt(buffer.lastIndexOf(","));
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/CaptchaTypeEnum.java
1 package com.anji.captcha.model.common; 1 package com.anji.captcha.model.common;
2 2
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +@Getter
  7 +@AllArgsConstructor
3 public enum CaptchaTypeEnum { 8 public enum CaptchaTypeEnum {
4 /** 9 /**
5 * 滑块拼图. 10 * 滑块拼图.
6 */ 11 */
7 - BLOCKPUZZLE("blockPuzzle","滑块拼图"), 12 + BLOCKPUZZLE("blockPuzzle", "滑块拼图"),
8 /** 13 /**
9 * 文字点选. 14 * 文字点选.
10 */ 15 */
11 - CLICKWORD("clickWord","文字点选"), 16 + CLICKWORD("clickWord", "文字点选"),
12 /** 17 /**
13 * 默认. 18 * 默认.
14 */ 19 */
15 - DEFAULT("default","默认");  
16 -  
17 - private String codeValue;  
18 - private String codeDesc;  
19 -  
20 - private CaptchaTypeEnum(String codeValue, String codeDesc) {  
21 - this.codeValue = codeValue;  
22 - this.codeDesc = codeDesc;  
23 - }  
24 -  
25 - public String getCodeValue(){ return this.codeValue;} 20 + DEFAULT("default", "默认");
26 21
27 - public String getCodeDesc(){ return this.codeDesc;} 22 + private final String codeValue;
  23 + private final String codeDesc;
28 24
29 //根据codeValue获取枚举 25 //根据codeValue获取枚举
30 - public static CaptchaTypeEnum parseFromCodeValue(String codeValue){  
31 - for (CaptchaTypeEnum e : CaptchaTypeEnum.values()){  
32 - if(e.codeValue.equals(codeValue)){ return e;} 26 + public static CaptchaTypeEnum parseFromCodeValue(String codeValue) {
  27 + for (CaptchaTypeEnum e : CaptchaTypeEnum.values()) {
  28 + if (e.codeValue.equals(codeValue)) {
  29 + return e;
  30 + }
33 } 31 }
34 return null; 32 return null;
35 } 33 }
36 34
37 //根据codeValue获取描述 35 //根据codeValue获取描述
38 - public static String getCodeDescByCodeBalue(String codeValue){ 36 + public static String getCodeDescByCodeBalue(String codeValue) {
39 CaptchaTypeEnum enumItem = parseFromCodeValue(codeValue); 37 CaptchaTypeEnum enumItem = parseFromCodeValue(codeValue);
40 return enumItem == null ? "" : enumItem.getCodeDesc(); 38 return enumItem == null ? "" : enumItem.getCodeDesc();
41 } 39 }
42 40
43 //验证codeValue是否有效 41 //验证codeValue是否有效
44 - public static boolean validateCodeValue(String codeValue){ return parseFromCodeValue(codeValue)!=null;} 42 + public static boolean validateCodeValue(String codeValue) {
  43 + return parseFromCodeValue(codeValue) != null;
  44 + }
45 45
46 //列出所有值字符串 46 //列出所有值字符串
47 - public static String getString(){  
48 - StringBuffer buffer = new StringBuffer();  
49 - for (CaptchaTypeEnum e : CaptchaTypeEnum.values()){ 47 + public static String getString() {
  48 + StringBuilder buffer = new StringBuilder();
  49 + for (CaptchaTypeEnum e : CaptchaTypeEnum.values()) {
50 buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", "); 50 buffer.append(e.codeValue).append("--").append(e.getCodeDesc()).append(", ");
51 } 51 }
52 buffer.deleteCharAt(buffer.lastIndexOf(",")); 52 buffer.deleteCharAt(buffer.lastIndexOf(","));
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/Const.java
@@ -6,7 +6,7 @@ package com.anji.captcha.model.common; @@ -6,7 +6,7 @@ package com.anji.captcha.model.common;
6 public interface Const { 6 public interface Const {
7 7
8 /** 8 /**
9 - *滑块底图路径 9 + * 滑块底图路径
10 */ 10 */
11 String ORIGINAL_PATH_JIGSAW = "captcha.captchaOriginalPath.jigsaw"; 11 String ORIGINAL_PATH_JIGSAW = "captcha.captchaOriginalPath.jigsaw";
12 12
@@ -29,8 +29,8 @@ public interface Const { @@ -29,8 +29,8 @@ public interface Const {
29 * 点选文字验证码的文字字体(宋体) 29 * 点选文字验证码的文字字体(宋体)
30 */ 30 */
31 String CAPTCHA_FONT_TYPE = "captcha.font.type"; 31 String CAPTCHA_FONT_TYPE = "captcha.font.type";
32 - String CAPTCHA_FONT_STYLE = "captcha.font.style";  
33 - String CAPTCHA_FONT_SIZE = "captcha.font.size"; 32 + String CAPTCHA_FONT_STYLE = "captcha.font.style";
  33 + String CAPTCHA_FONT_SIZE = "captcha.font.size";
34 34
35 /** 35 /**
36 * 验证码类型default两种都实例化。 36 * 验证码类型default两种都实例化。
@@ -72,41 +72,41 @@ public interface Const { @@ -72,41 +72,41 @@ public interface Const {
72 */ 72 */
73 String CAPTCHA_TIMING_CLEAR_SECOND = "captcha.timing.clear"; 73 String CAPTCHA_TIMING_CLEAR_SECOND = "captcha.timing.clear";
74 74
75 - /**  
76 - * 历史资源清除开关 0禁用,1 开启  
77 - */  
78 - String HISTORY_DATA_CLEAR_ENABLE = "captcha.history.data.clear.enable";  
79 -  
80 - /**  
81 - * 接口限流开关 0禁用 1启用  
82 - */  
83 - String REQ_FREQUENCY_LIMIT_ENABLE = "captcha.req.frequency.limit.enable";  
84 -  
85 - /**  
86 - * get 接口 一分钟请求次数限制  
87 - */  
88 - String REQ_GET_MINUTE_LIMIT = "captcha.req.get.minute.limit";  
89 -  
90 - /**  
91 - * 验证失败后,get接口锁定时间  
92 - */  
93 - String REQ_GET_LOCK_LIMIT = "captcha.req.get.lock.limit";  
94 - /**  
95 - * 验证失败后,get接口锁定时间  
96 - */  
97 - String REQ_GET_LOCK_SECONDS = "captcha.req.get.lock.seconds";  
98 -  
99 - /**  
100 - * verify 接口 一分钟请求次数限制  
101 - */  
102 - String REQ_VALIDATE_MINUTE_LIMIT = "captcha.req.verify.minute.limit";  
103 - /**  
104 - * check接口 一分钟请求次数限制  
105 - */  
106 - String REQ_CHECK_MINUTE_LIMIT = "captcha.req.check.minute.limit";  
107 -  
108 - /***  
109 - * 点选文字个数  
110 - */  
111 - String CAPTCHA_WORD_COUNT = "captcha.word.count"; 75 + /**
  76 + * 历史资源清除开关 0禁用,1 开启
  77 + */
  78 + String HISTORY_DATA_CLEAR_ENABLE = "captcha.history.data.clear.enable";
  79 +
  80 + /**
  81 + * 接口限流开关 0禁用 1启用
  82 + */
  83 + String REQ_FREQUENCY_LIMIT_ENABLE = "captcha.req.frequency.limit.enable";
  84 +
  85 + /**
  86 + * get 接口 一分钟请求次数限制
  87 + */
  88 + String REQ_GET_MINUTE_LIMIT = "captcha.req.get.minute.limit";
  89 +
  90 + /**
  91 + * 验证失败后,get接口锁定时间
  92 + */
  93 + String REQ_GET_LOCK_LIMIT = "captcha.req.get.lock.limit";
  94 + /**
  95 + * 验证失败后,get接口锁定时间
  96 + */
  97 + String REQ_GET_LOCK_SECONDS = "captcha.req.get.lock.seconds";
  98 +
  99 + /**
  100 + * verify 接口 一分钟请求次数限制
  101 + */
  102 + String REQ_VALIDATE_MINUTE_LIMIT = "captcha.req.verify.minute.limit";
  103 + /**
  104 + * check接口 一分钟请求次数限制
  105 + */
  106 + String REQ_CHECK_MINUTE_LIMIT = "captcha.req.check.minute.limit";
  107 +
  108 + /***
  109 + * 点选文字个数
  110 + */
  111 + String CAPTCHA_WORD_COUNT = "captcha.word.count";
112 } 112 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/RepCodeEnum.java
@@ -6,16 +6,23 @@ @@ -6,16 +6,23 @@
6 */ 6 */
7 package com.anji.captcha.model.common; 7 package com.anji.captcha.model.common;
8 8
  9 +import lombok.AllArgsConstructor;
  10 +import lombok.Getter;
  11 +
9 import java.text.MessageFormat; 12 import java.text.MessageFormat;
10 13
11 /** 14 /**
12 * 返回应答码 15 * 返回应答码
13 - * @author  
14 * 16 *
  17 + * @author
15 */ 18 */
  19 +@AllArgsConstructor
  20 +@Getter
16 public enum RepCodeEnum { 21 public enum RepCodeEnum {
17 22
18 - /** 0001 - 0099 网关应答码 */ 23 + /**
  24 + * 0001 - 0099 网关应答码
  25 + */
19 SUCCESS("0000", "成功"), 26 SUCCESS("0000", "成功"),
20 ERROR("0001", "操作失败"), 27 ERROR("0001", "操作失败"),
21 EXCEPTION("9999", "服务器内部异常"), 28 EXCEPTION("9999", "服务器内部异常"),
@@ -33,36 +40,24 @@ public enum RepCodeEnum { @@ -33,36 +40,24 @@ public enum RepCodeEnum {
33 API_CAPTCHA_ERROR("6112", "获取验证码失败,请联系管理员"), 40 API_CAPTCHA_ERROR("6112", "获取验证码失败,请联系管理员"),
34 API_CAPTCHA_BASEMAP_NULL("6113", "底图未初始化成功,请检查路径"), 41 API_CAPTCHA_BASEMAP_NULL("6113", "底图未初始化成功,请检查路径"),
35 42
36 - API_REQ_LIMIT_GET_ERROR("6201", "get接口请求次数超限,请稍后再试!"), 43 + API_REQ_LIMIT_GET_ERROR("6201", "get接口请求次数超限,请稍后再试!"),
37 API_REQ_INVALID("6206", "无效请求,请重新获取验证码"), 44 API_REQ_INVALID("6206", "无效请求,请重新获取验证码"),
38 - API_REQ_LOCK_GET_ERROR("6202", "接口验证失败数过多,请稍后再试"),  
39 - API_REQ_LIMIT_CHECK_ERROR("6204", "check接口请求次数超限,请稍后再试!"),  
40 - API_REQ_LIMIT_VERIFY_ERROR("6205", "verify请求次数超限!"),  
41 - ;  
42 - private String code;  
43 - private String desc; 45 + API_REQ_LOCK_GET_ERROR("6202", "接口验证失败数过多,请稍后再试"),
  46 + API_REQ_LIMIT_CHECK_ERROR("6204", "check接口请求次数超限,请稍后再试!"),
  47 + API_REQ_LIMIT_VERIFY_ERROR("6205", "verify请求次数超限!");
  48 + private final String code;
  49 + private final String desc;
44 50
45 - RepCodeEnum(String code, String desc) {  
46 - this.code = code;  
47 - this.desc = desc;  
48 - }  
49 - public String getCode() {  
50 - return code;  
51 - }  
52 - public String getDesc() {  
53 - return desc;  
54 - }  
55 - public String getName(){  
56 - return this.name();  
57 - }  
58 51
59 - /** 将入参fieldNames与this.desc组合成错误信息  
60 - * {fieldName}不能为空 52 + /**
  53 + * 将入参fieldNames与this.desc组合成错误信息
  54 + * {fieldName}不能为空
  55 + *
61 * @param fieldNames 56 * @param fieldNames
62 * @return 57 * @return
63 */ 58 */
64 public ResponseModel parseError(Object... fieldNames) { 59 public ResponseModel parseError(Object... fieldNames) {
65 - ResponseModel errorMessage=new ResponseModel(); 60 + ResponseModel errorMessage = new ResponseModel();
66 String newDesc = MessageFormat.format(this.desc, fieldNames); 61 String newDesc = MessageFormat.format(this.desc, fieldNames);
67 62
68 errorMessage.setRepCode(this.code); 63 errorMessage.setRepCode(this.code);
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/RequestModel.java
@@ -6,23 +6,32 @@ @@ -6,23 +6,32 @@
6 */ 6 */
7 package com.anji.captcha.model.common; 7 package com.anji.captcha.model.common;
8 8
9 -import com.anji.captcha.util.StringUtils; 9 +
  10 +import cn.hutool.core.util.StrUtil;
  11 +import lombok.Data;
10 12
11 import java.io.Serializable; 13 import java.io.Serializable;
12 import java.util.HashMap; 14 import java.util.HashMap;
13 import java.util.List; 15 import java.util.List;
14 16
  17 +@Data
15 public class RequestModel implements Serializable { 18 public class RequestModel implements Serializable {
16 19
17 private static final long serialVersionUID = -5800786065305114784L; 20 private static final long serialVersionUID = -5800786065305114784L;
18 21
19 - /**当前请求接口路径 /business/accessUser/login */ 22 + /**
  23 + * 当前请求接口路径 /business/accessUser/login
  24 + */
20 private String servletPath; 25 private String servletPath;
21 26
22 - /** {"reqData":{"password":"*****","userName":"admin"},"sign":"a304a7f296f565b6d2009797f68180f0","time":"1542456453355","token":""} */ 27 + /**
  28 + * {"reqData":{"password":"*****","userName":"admin"},"sign":"a304a7f296f565b6d2009797f68180f0","time":"1542456453355","token":""}
  29 + */
23 private String requestString; 30 private String requestString;
24 31
25 - /** {"password":"****","userName":"admin"} */ 32 + /**
  33 + * {"password":"****","userName":"admin"}
  34 + */
26 private HashMap reqData; 35 private HashMap reqData;
27 36
28 private String token; 37 private String token;
@@ -46,10 +55,11 @@ public class RequestModel implements Serializable { @@ -46,10 +55,11 @@ public class RequestModel implements Serializable {
46 55
47 /** 56 /**
48 * 校验自身参数合法性 57 * 校验自身参数合法性
  58 + *
49 * @return 59 * @return
50 */ 60 */
51 public boolean isVaildateRequest() { 61 public boolean isVaildateRequest() {
52 - if (StringUtils.isBlank(sign) || StringUtils.isBlank(time)) { 62 + if (StrUtil.isBlank(sign) || StrUtil.isBlank(time)) {
53 return false; 63 return false;
54 } 64 }
55 return true; 65 return true;
@@ -63,95 +73,4 @@ public class RequestModel implements Serializable { @@ -63,95 +73,4 @@ public class RequestModel implements Serializable {
63 this.servletPath = servletPath; 73 this.servletPath = servletPath;
64 } 74 }
65 75
66 - public String getToken() {  
67 - return token;  
68 - }  
69 -  
70 - public void setToken(String token) {  
71 - this.token = token;  
72 - }  
73 -  
74 - public Long getUserId() {  
75 - return userId;  
76 - }  
77 -  
78 - public void setUserId(Long userId) {  
79 - this.userId = userId;  
80 - }  
81 -  
82 - public String getUserName() {  
83 - return userName;  
84 - }  
85 -  
86 - public void setUserName(String userName) {  
87 - this.userName = userName;  
88 - }  
89 -  
90 - public static long getSerialVersionUID() {  
91 - return serialVersionUID;  
92 - }  
93 -  
94 - public List<Long> getProjectList() {  
95 - return projectList;  
96 - }  
97 -  
98 - public void setProjectList(List<Long> projectList) {  
99 - this.projectList = projectList;  
100 - }  
101 -  
102 - public List<Long> getGroupIdList() {  
103 - return groupIdList;  
104 - }  
105 -  
106 - public void setGroupIdList(List<Long> groupIdList) {  
107 - this.groupIdList = groupIdList;  
108 - }  
109 -  
110 - public String getSign() {  
111 - return sign;  
112 - }  
113 -  
114 - public void setSign(String sign) {  
115 - this.sign = sign;  
116 - }  
117 -  
118 - public String getTime() {  
119 - return time;  
120 - }  
121 -  
122 - public void setTime(String time) {  
123 - this.time = time;  
124 - }  
125 -  
126 - public String getSourceIP() {  
127 - return sourceIP;  
128 - }  
129 -  
130 - public void setSourceIP(String sourceIP) {  
131 - this.sourceIP = sourceIP;  
132 - }  
133 -  
134 - public String getRequestString() {  
135 - return requestString;  
136 - }  
137 -  
138 - public void setRequestString(String requestString) {  
139 - this.requestString = requestString;  
140 - }  
141 -  
142 - public HashMap getReqData() {  
143 - return reqData;  
144 - }  
145 -  
146 - public void setReqData(HashMap reqData) {  
147 - this.reqData = reqData;  
148 - }  
149 -  
150 - public String getTarget() {  
151 - return target;  
152 - }  
153 -  
154 - public void setTarget(String target) {  
155 - this.target = target;  
156 - }  
157 } 76 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/common/ResponseModel.java
@@ -6,38 +6,42 @@ @@ -6,38 +6,42 @@
6 */ 6 */
7 package com.anji.captcha.model.common; 7 package com.anji.captcha.model.common;
8 8
9 -import com.anji.captcha.util.StringUtils; 9 +import cn.hutool.core.util.StrUtil;
  10 +import lombok.Data;
10 11
11 import java.io.Serializable; 12 import java.io.Serializable;
12 13
  14 +@Data
13 public class ResponseModel implements Serializable { 15 public class ResponseModel implements Serializable {
14 16
15 private static final long serialVersionUID = 8445617032523881407L; 17 private static final long serialVersionUID = 8445617032523881407L;
16 18
17 - private String repCode; 19 + private String repCode;
18 20
19 - private String repMsg; 21 + private String repMsg;
20 22
21 - private Object repData; 23 + private Object repData;
22 24
23 public ResponseModel() { 25 public ResponseModel() {
24 this.repCode = RepCodeEnum.SUCCESS.getCode(); 26 this.repCode = RepCodeEnum.SUCCESS.getCode();
25 } 27 }
26 28
27 public ResponseModel(RepCodeEnum repCodeEnum) { 29 public ResponseModel(RepCodeEnum repCodeEnum) {
28 - this.setRepCodeEnum(repCodeEnum); 30 + this.setRepCodeEnum(repCodeEnum);
29 } 31 }
30 32
31 //成功 33 //成功
32 - public static ResponseModel success(){ 34 + public static ResponseModel success() {
33 return ResponseModel.successMsg("成功"); 35 return ResponseModel.successMsg("成功");
34 } 36 }
35 - public static ResponseModel successMsg(String message){ 37 +
  38 + public static ResponseModel successMsg(String message) {
36 ResponseModel responseModel = new ResponseModel(); 39 ResponseModel responseModel = new ResponseModel();
37 responseModel.setRepMsg(message); 40 responseModel.setRepMsg(message);
38 return responseModel; 41 return responseModel;
39 } 42 }
40 - public static ResponseModel successData(Object data){ 43 +
  44 + public static ResponseModel successData(Object data) {
41 ResponseModel responseModel = new ResponseModel(); 45 ResponseModel responseModel = new ResponseModel();
42 responseModel.setRepCode(RepCodeEnum.SUCCESS.getCode()); 46 responseModel.setRepCode(RepCodeEnum.SUCCESS.getCode());
43 responseModel.setRepData(data); 47 responseModel.setRepData(data);
@@ -45,67 +49,45 @@ public class ResponseModel implements Serializable { @@ -45,67 +49,45 @@ public class ResponseModel implements Serializable {
45 } 49 }
46 50
47 //失败 51 //失败
48 - public static ResponseModel errorMsg(RepCodeEnum message){ 52 + public static ResponseModel errorMsg(RepCodeEnum message) {
49 ResponseModel responseModel = new ResponseModel(); 53 ResponseModel responseModel = new ResponseModel();
50 responseModel.setRepCodeEnum(message); 54 responseModel.setRepCodeEnum(message);
51 return responseModel; 55 return responseModel;
52 } 56 }
53 - public static ResponseModel errorMsg(String message){ 57 +
  58 + public static ResponseModel errorMsg(String message) {
54 ResponseModel responseModel = new ResponseModel(); 59 ResponseModel responseModel = new ResponseModel();
55 responseModel.setRepCode(RepCodeEnum.ERROR.getCode()); 60 responseModel.setRepCode(RepCodeEnum.ERROR.getCode());
56 responseModel.setRepMsg(message); 61 responseModel.setRepMsg(message);
57 return responseModel; 62 return responseModel;
58 } 63 }
59 - public static ResponseModel errorMsg(RepCodeEnum repCodeEnum, String message){ 64 +
  65 + public static ResponseModel errorMsg(RepCodeEnum repCodeEnum, String message) {
60 ResponseModel responseModel = new ResponseModel(); 66 ResponseModel responseModel = new ResponseModel();
61 responseModel.setRepCode(repCodeEnum.getCode()); 67 responseModel.setRepCode(repCodeEnum.getCode());
62 responseModel.setRepMsg(message); 68 responseModel.setRepMsg(message);
63 return responseModel; 69 return responseModel;
64 } 70 }
65 - public static ResponseModel exceptionMsg(String message){ 71 +
  72 + public static ResponseModel exceptionMsg(String message) {
66 ResponseModel responseModel = new ResponseModel(); 73 ResponseModel responseModel = new ResponseModel();
67 responseModel.setRepCode(RepCodeEnum.EXCEPTION.getCode()); 74 responseModel.setRepCode(RepCodeEnum.EXCEPTION.getCode());
68 responseModel.setRepMsg(RepCodeEnum.EXCEPTION.getDesc() + ": " + message); 75 responseModel.setRepMsg(RepCodeEnum.EXCEPTION.getDesc() + ": " + message);
69 return responseModel; 76 return responseModel;
70 } 77 }
71 78
72 - @Override  
73 - public String toString() {  
74 - return "ResponseModel{" + "repCode='" + repCode + '\'' + ", repMsg='"  
75 - + repMsg + '\'' + ", repData=" + repData + '}';  
76 - }  
77 79
78 - public boolean isSuccess(){  
79 - return StringUtils.equals(repCode, RepCodeEnum.SUCCESS.getCode()); 80 + public boolean isSuccess() {
  81 + return StrUtil.equals(repCode, RepCodeEnum.SUCCESS.getCode());
80 } 82 }
81 83
82 public String getRepCode() { 84 public String getRepCode() {
83 return repCode; 85 return repCode;
84 } 86 }
85 87
86 - public void setRepCode(String repCode) {  
87 - this.repCode = repCode;  
88 - }  
89 public void setRepCodeEnum(RepCodeEnum repCodeEnum) { 88 public void setRepCodeEnum(RepCodeEnum repCodeEnum) {
90 - this.repCode=repCodeEnum.getCode();  
91 - this.repMsg=repCodeEnum.getDesc();  
92 - }  
93 -  
94 - public String getRepMsg() {  
95 - return repMsg; 89 + this.repCode = repCodeEnum.getCode();
  90 + this.repMsg = repCodeEnum.getDesc();
96 } 91 }
97 92
98 - public void setRepMsg(String repMsg) {  
99 - this.repMsg = repMsg;  
100 - }  
101 -  
102 - public Object getRepData() {  
103 - return repData;  
104 - }  
105 -  
106 - public void setRepData(Object repData) {  
107 - this.repData = repData;  
108 - }  
109 -  
110 -  
111 } 93 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/vo/CaptchaVO.java
@@ -6,10 +6,13 @@ @@ -6,10 +6,13 @@
6 */ 6 */
7 package com.anji.captcha.model.vo; 7 package com.anji.captcha.model.vo;
8 8
  9 +import lombok.Data;
  10 +
9 import java.awt.*; 11 import java.awt.*;
10 import java.io.Serializable; 12 import java.io.Serializable;
11 import java.util.List; 13 import java.util.List;
12 14
  15 +@Data
13 public class CaptchaVO implements Serializable { 16 public class CaptchaVO implements Serializable {
14 17
15 /** 18 /**
@@ -79,173 +82,23 @@ public class CaptchaVO implements Serializable { @@ -79,173 +82,23 @@ public class CaptchaVO implements Serializable {
79 */ 82 */
80 private String captchaVerification; 83 private String captchaVerification;
81 84
82 - /***  
83 - * 客户端UI组件id,组件初始化时设置一次,UUID  
84 - */  
85 - private String clientUid;  
86 - /***  
87 - * 客户端的请求时间,预留字段  
88 - */  
89 - private Long ts; 85 + /***
  86 + * 客户端UI组件id,组件初始化时设置一次,UUID
  87 + */
  88 + private String clientUid;
  89 + /***
  90 + * 客户端的请求时间,预留字段
  91 + */
  92 + private Long ts;
90 93
91 /*** 94 /***
92 * 客户端ip+userAgent 95 * 客户端ip+userAgent
93 */ 96 */
94 private String browserInfo; 97 private String browserInfo;
95 - public void resetClientFlag(){ 98 +
  99 + public void resetClientFlag() {
96 this.browserInfo = null; 100 this.browserInfo = null;
97 this.clientUid = null; 101 this.clientUid = null;
98 } 102 }
99 103
100 - public String getCaptchaId() {  
101 - return captchaId;  
102 - }  
103 -  
104 - public void setCaptchaId(String captchaId) {  
105 - this.captchaId = captchaId;  
106 - }  
107 -  
108 - public String getProjectCode() {  
109 - return projectCode;  
110 - }  
111 -  
112 - public void setProjectCode(String projectCode) {  
113 - this.projectCode = projectCode;  
114 - }  
115 -  
116 - public String getCaptchaType() {  
117 - return captchaType;  
118 - }  
119 -  
120 - public void setCaptchaType(String captchaType) {  
121 - this.captchaType = captchaType;  
122 - }  
123 -  
124 - public String getCaptchaOriginalPath() {  
125 - return captchaOriginalPath;  
126 - }  
127 -  
128 - public void setCaptchaOriginalPath(String captchaOriginalPath) {  
129 - this.captchaOriginalPath = captchaOriginalPath;  
130 - }  
131 -  
132 - public String getCaptchaFontType() {  
133 - return captchaFontType;  
134 - }  
135 -  
136 - public void setCaptchaFontType(String captchaFontType) {  
137 - this.captchaFontType = captchaFontType;  
138 - }  
139 -  
140 - public Integer getCaptchaFontSize() {  
141 - return captchaFontSize;  
142 - }  
143 -  
144 - public void setCaptchaFontSize(Integer captchaFontSize) {  
145 - this.captchaFontSize = captchaFontSize;  
146 - }  
147 -  
148 - public String getOriginalImageBase64() {  
149 - return originalImageBase64;  
150 - }  
151 -  
152 - public void setOriginalImageBase64(String originalImageBase64) {  
153 - this.originalImageBase64 = originalImageBase64;  
154 - }  
155 -  
156 - public PointVO getPoint() {  
157 - return point;  
158 - }  
159 -  
160 - public void setPoint(PointVO point) {  
161 - this.point = point;  
162 - }  
163 -  
164 - public String getJigsawImageBase64() {  
165 - return jigsawImageBase64;  
166 - }  
167 -  
168 - public void setJigsawImageBase64(String jigsawImageBase64) {  
169 - this.jigsawImageBase64 = jigsawImageBase64;  
170 - }  
171 -  
172 - public List<String> getWordList() {  
173 - return wordList;  
174 - }  
175 -  
176 - public void setWordList(List<String> wordList) {  
177 - this.wordList = wordList;  
178 - }  
179 -  
180 - public List<Point> getPointList() {  
181 - return pointList;  
182 - }  
183 -  
184 - public void setPointList(List<Point> pointList) {  
185 - this.pointList = pointList;  
186 - }  
187 -  
188 - public String getPointJson() {  
189 - return pointJson;  
190 - }  
191 -  
192 - public void setPointJson(String pointJson) {  
193 - this.pointJson = pointJson;  
194 - }  
195 -  
196 - public String getToken() {  
197 - return token;  
198 - }  
199 -  
200 - public void setToken(String token) {  
201 - this.token = token;  
202 - }  
203 -  
204 - public Boolean getResult() {  
205 - return result;  
206 - }  
207 -  
208 - public void setResult(Boolean result) {  
209 - this.result = result;  
210 - }  
211 -  
212 - public String getCaptchaVerification() {  
213 - return captchaVerification;  
214 - }  
215 -  
216 - public void setCaptchaVerification(String captchaVerification) {  
217 - this.captchaVerification = captchaVerification;  
218 - }  
219 -  
220 - public String getSecretKey() {  
221 - return secretKey;  
222 - }  
223 -  
224 - public void setSecretKey(String secretKey) {  
225 - this.secretKey = secretKey;  
226 - }  
227 -  
228 - public String getClientUid() {  
229 - return clientUid;  
230 - }  
231 -  
232 - public void setClientUid(String clientUid) {  
233 - this.clientUid = clientUid;  
234 - }  
235 -  
236 - public Long getTs() {  
237 - return ts;  
238 - }  
239 -  
240 - public void setTs(Long ts) {  
241 - this.ts = ts;  
242 - }  
243 -  
244 - public String getBrowserInfo() {  
245 - return browserInfo;  
246 - }  
247 -  
248 - public void setBrowserInfo(String browserInfo) {  
249 - this.browserInfo = browserInfo;  
250 - }  
251 } 104 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/model/vo/PointVO.java
1 package com.anji.captcha.model.vo; 1 package com.anji.captcha.model.vo;
2 2
  3 +import lombok.Data;
  4 +
3 import java.util.Arrays; 5 import java.util.Arrays;
4 import java.util.HashMap; 6 import java.util.HashMap;
5 import java.util.Map; 7 import java.util.Map;
@@ -9,6 +11,7 @@ import java.util.regex.Pattern; @@ -9,6 +11,7 @@ import java.util.regex.Pattern;
9 /** 11 /**
10 * Created by raodeming on 2020/5/16. 12 * Created by raodeming on 2020/5/16.
11 */ 13 */
  14 +@Data
12 public class PointVO { 15 public class PointVO {
13 private String secretKey; 16 private String secretKey;
14 17
@@ -16,30 +19,6 @@ public class PointVO { @@ -16,30 +19,6 @@ public class PointVO {
16 19
17 public int y; 20 public int y;
18 21
19 - public String getSecretKey() {  
20 - return secretKey;  
21 - }  
22 -  
23 - public void setSecretKey(String secretKey) {  
24 - this.secretKey = secretKey;  
25 - }  
26 -  
27 - public int getX() {  
28 - return x;  
29 - }  
30 -  
31 - public void setX(int x) {  
32 - this.x = x;  
33 - }  
34 -  
35 - public int getY() {  
36 - return y;  
37 - }  
38 -  
39 - public void setY(int y) {  
40 - this.y = y;  
41 - }  
42 -  
43 public PointVO(int x, int y, String secretKey) { 22 public PointVO(int x, int y, String secretKey) {
44 this.secretKey = secretKey; 23 this.secretKey = secretKey;
45 this.x = x; 24 this.x = x;
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/properties/AjCaptchaProperties.java
1 package com.anji.captcha.properties; 1 package com.anji.captcha.properties;
2 2
3 import com.anji.captcha.model.common.CaptchaTypeEnum; 3 import com.anji.captcha.model.common.CaptchaTypeEnum;
  4 +import lombok.Data;
4 import org.springframework.boot.context.properties.ConfigurationProperties; 5 import org.springframework.boot.context.properties.ConfigurationProperties;
5 6
6 import java.awt.*; 7 import java.awt.*;
@@ -8,6 +9,7 @@ import java.awt.*; @@ -8,6 +9,7 @@ import java.awt.*;
8 import static com.anji.captcha.properties.AjCaptchaProperties.PREFIX; 9 import static com.anji.captcha.properties.AjCaptchaProperties.PREFIX;
9 import static com.anji.captcha.properties.AjCaptchaProperties.StorageType.local; 10 import static com.anji.captcha.properties.AjCaptchaProperties.StorageType.local;
10 11
  12 +@Data
11 @ConfigurationProperties(PREFIX) 13 @ConfigurationProperties(PREFIX)
12 public class AjCaptchaProperties { 14 public class AjCaptchaProperties {
13 public static final String PREFIX = "aj.captcha"; 15 public static final String PREFIX = "aj.captcha";
@@ -113,90 +115,10 @@ public class AjCaptchaProperties { @@ -113,90 +115,10 @@ public class AjCaptchaProperties {
113 */ 115 */
114 private int clickWordCount = 4; 116 private int clickWordCount = 4;
115 117
116 - public int getFontStyle() {  
117 - return fontStyle;  
118 - }  
119 -  
120 - public void setFontStyle(int fontStyle) {  
121 - this.fontStyle = fontStyle;  
122 - }  
123 -  
124 - public int getFontSize() {  
125 - return fontSize;  
126 - }  
127 -  
128 - public void setFontSize(int fontSize) {  
129 - this.fontSize = fontSize;  
130 - }  
131 -  
132 - public int getClickWordCount() {  
133 - return clickWordCount;  
134 - }  
135 -  
136 - public void setClickWordCount(int clickWordCount) {  
137 - this.clickWordCount = clickWordCount;  
138 - }  
139 -  
140 - public boolean isHistoryDataClearEnable() {  
141 - return historyDataClearEnable;  
142 - }  
143 -  
144 - public void setHistoryDataClearEnable(boolean historyDataClearEnable) {  
145 - this.historyDataClearEnable = historyDataClearEnable;  
146 - }  
147 -  
148 - public boolean isReqFrequencyLimitEnable() {  
149 - return reqFrequencyLimitEnable;  
150 - }  
151 -  
152 public boolean getReqFrequencyLimitEnable() { 118 public boolean getReqFrequencyLimitEnable() {
153 return reqFrequencyLimitEnable; 119 return reqFrequencyLimitEnable;
154 } 120 }
155 121
156 - public void setReqFrequencyLimitEnable(boolean reqFrequencyLimitEnable) {  
157 - this.reqFrequencyLimitEnable = reqFrequencyLimitEnable;  
158 - }  
159 -  
160 - public int getReqGetLockLimit() {  
161 - return reqGetLockLimit;  
162 - }  
163 -  
164 - public void setReqGetLockLimit(int reqGetLockLimit) {  
165 - this.reqGetLockLimit = reqGetLockLimit;  
166 - }  
167 -  
168 - public int getReqGetLockSeconds() {  
169 - return reqGetLockSeconds;  
170 - }  
171 -  
172 - public void setReqGetLockSeconds(int reqGetLockSeconds) {  
173 - this.reqGetLockSeconds = reqGetLockSeconds;  
174 - }  
175 -  
176 - public int getReqGetMinuteLimit() {  
177 - return reqGetMinuteLimit;  
178 - }  
179 -  
180 - public void setReqGetMinuteLimit(int reqGetMinuteLimit) {  
181 - this.reqGetMinuteLimit = reqGetMinuteLimit;  
182 - }  
183 -  
184 - public int getReqCheckMinuteLimit() {  
185 - return reqGetMinuteLimit;  
186 - }  
187 -  
188 - public void setReqCheckMinuteLimit(int reqCheckMinuteLimit) {  
189 - this.reqCheckMinuteLimit = reqCheckMinuteLimit;  
190 - }  
191 -  
192 - public int getReqVerifyMinuteLimit() {  
193 - return reqVerifyMinuteLimit;  
194 - }  
195 -  
196 - public void setReqVerifyMinuteLimit(int reqVerifyMinuteLimit) {  
197 - this.reqVerifyMinuteLimit = reqVerifyMinuteLimit;  
198 - }  
199 -  
200 public enum StorageType { 122 public enum StorageType {
201 /** 123 /**
202 * 内存. 124 * 内存.
@@ -216,123 +138,4 @@ public class AjCaptchaProperties { @@ -216,123 +138,4 @@ public class AjCaptchaProperties {
216 return PREFIX; 138 return PREFIX;
217 } 139 }
218 140
219 - public CaptchaTypeEnum getType() {  
220 - return type;  
221 - }  
222 -  
223 - public void setType(CaptchaTypeEnum type) {  
224 - this.type = type;  
225 - }  
226 -  
227 - public String getJigsaw() {  
228 - return jigsaw;  
229 - }  
230 -  
231 - public void setJigsaw(String jigsaw) {  
232 - this.jigsaw = jigsaw;  
233 - }  
234 -  
235 - public String getPicClick() {  
236 - return picClick;  
237 - }  
238 -  
239 - public void setPicClick(String picClick) {  
240 - this.picClick = picClick;  
241 - }  
242 -  
243 - public String getWaterMark() {  
244 - return waterMark;  
245 - }  
246 -  
247 - public void setWaterMark(String waterMark) {  
248 - this.waterMark = waterMark;  
249 - }  
250 -  
251 - public String getWaterFont() {  
252 - return waterFont;  
253 - }  
254 -  
255 - public void setWaterFont(String waterFont) {  
256 - this.waterFont = waterFont;  
257 - }  
258 -  
259 - public String getFontType() {  
260 - return fontType;  
261 - }  
262 -  
263 - public void setFontType(String fontType) {  
264 - this.fontType = fontType;  
265 - }  
266 -  
267 - public String getSlipOffset() {  
268 - return slipOffset;  
269 - }  
270 -  
271 - public void setSlipOffset(String slipOffset) {  
272 - this.slipOffset = slipOffset;  
273 - }  
274 -  
275 - public Boolean getAesStatus() {  
276 - return aesStatus;  
277 - }  
278 -  
279 - public void setAesStatus(Boolean aesStatus) {  
280 - this.aesStatus = aesStatus;  
281 - }  
282 -  
283 - public StorageType getCacheType() {  
284 - return cacheType;  
285 - }  
286 -  
287 - public void setCacheType(StorageType cacheType) {  
288 - this.cacheType = cacheType;  
289 - }  
290 -  
291 - public String getInterferenceOptions() {  
292 - return interferenceOptions;  
293 - }  
294 -  
295 - public void setInterferenceOptions(String interferenceOptions) {  
296 - this.interferenceOptions = interferenceOptions;  
297 - }  
298 -  
299 - public String getCacheNumber() {  
300 - return cacheNumber;  
301 - }  
302 -  
303 - public void setCacheNumber(String cacheNumber) {  
304 - this.cacheNumber = cacheNumber;  
305 - }  
306 -  
307 - public String getTimingClear() {  
308 - return timingClear;  
309 - }  
310 -  
311 - public void setTimingClear(String timingClear) {  
312 - this.timingClear = timingClear;  
313 - }  
314 -  
315 - @Override  
316 - public String toString() {  
317 - return "\nAjCaptchaProperties{" +  
318 - "type=" + type +  
319 - ", jigsaw='" + jigsaw + '\'' +  
320 - ", picClick='" + picClick + '\'' +  
321 - ", waterMark='" + waterMark + '\'' +  
322 - ", waterFont='" + waterFont + '\'' +  
323 - ", fontType='" + fontType + '\'' +  
324 - ", slipOffset='" + slipOffset + '\'' +  
325 - ", aesStatus=" + aesStatus +  
326 - ", interferenceOptions='" + interferenceOptions + '\'' +  
327 - ", cacheNumber='" + cacheNumber + '\'' +  
328 - ", timingClear='" + timingClear + '\'' +  
329 - ", cacheType=" + cacheType +  
330 - ", reqFrequencyLimitEnable=" + reqFrequencyLimitEnable +  
331 - ", reqGetLockLimit=" + reqGetLockLimit +  
332 - ", reqGetLockSeconds=" + reqGetLockSeconds +  
333 - ", reqGetMinuteLimit=" + reqGetMinuteLimit +  
334 - ", reqCheckMinuteLimit=" + reqCheckMinuteLimit +  
335 - ", reqVerifyMinuteLimit=" + reqVerifyMinuteLimit +  
336 - '}';  
337 - }  
338 } 141 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/CaptchaCacheService.java
@@ -8,34 +8,36 @@ package com.anji.captcha.service; @@ -8,34 +8,36 @@ package com.anji.captcha.service;
8 8
9 /** 9 /**
10 * 验证码缓存接口 10 * 验证码缓存接口
  11 + *
11 * @author lide1202@hotmail.com 12 * @author lide1202@hotmail.com
12 * @date 2018-08-21 13 * @date 2018-08-21
13 */ 14 */
14 public interface CaptchaCacheService { 15 public interface CaptchaCacheService {
15 16
16 - void set(String key, String value, long expiresInSeconds); 17 + void set(String key, String value, long expiresInSeconds);
17 18
18 - boolean exists(String key); 19 + boolean exists(String key);
19 20
20 - void delete(String key); 21 + void delete(String key);
21 22
22 - String get(String key); 23 + String get(String key);
23 24
24 - /**  
25 - * 缓存类型-local/redis/memcache/..  
26 - * 通过java SPI机制,接入方可自定义实现类  
27 - * @return  
28 - */  
29 - String type(); 25 + /**
  26 + * 缓存类型-local/redis/memcache/..
  27 + * 通过java SPI机制,接入方可自定义实现类
  28 + *
  29 + * @return
  30 + */
  31 + String type();
30 32
31 - /***  
32 - *  
33 - * @param key  
34 - * @param val  
35 - * @return  
36 - */  
37 - default Long increment(String key, long val){  
38 - return 0L;  
39 - }; 33 + /***
  34 + *
  35 + * @param key
  36 + * @param val
  37 + * @return
  38 + */
  39 + default Long increment(String key, long val) {
  40 + return 0L;
  41 + }
40 42
41 } 43 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/CaptchaService.java
@@ -13,6 +13,7 @@ import java.util.Properties; @@ -13,6 +13,7 @@ import java.util.Properties;
13 13
14 /** 14 /**
15 * 验证码服务接口 15 * 验证码服务接口
  16 + *
16 * @author lide1202@hotmail.com 17 * @author lide1202@hotmail.com
17 * @date 2020-05-12 18 * @date 2020-05-12
18 */ 19 */
@@ -24,6 +25,7 @@ public interface CaptchaService { @@ -24,6 +25,7 @@ public interface CaptchaService {
24 25
25 /** 26 /**
26 * 获取验证码 27 * 获取验证码
  28 + *
27 * @param captchaVO 29 * @param captchaVO
28 * @return 30 * @return
29 */ 31 */
@@ -31,6 +33,7 @@ public interface CaptchaService { @@ -31,6 +33,7 @@ public interface CaptchaService {
31 33
32 /** 34 /**
33 * 核对验证码(前端) 35 * 核对验证码(前端)
  36 + *
34 * @param captchaVO 37 * @param captchaVO
35 * @return 38 * @return
36 */ 39 */
@@ -38,6 +41,7 @@ public interface CaptchaService { @@ -38,6 +41,7 @@ public interface CaptchaService {
38 41
39 /** 42 /**
40 * 二次校验验证码(后端) 43 * 二次校验验证码(后端)
  44 + *
41 * @param captchaVO 45 * @param captchaVO
42 * @return 46 * @return
43 */ 47 */
@@ -50,9 +54,10 @@ public interface CaptchaService { @@ -50,9 +54,10 @@ public interface CaptchaService {
50 */ 54 */
51 String captchaType(); 55 String captchaType();
52 56
53 - /**  
54 - * 历史资源清除(过期的图片文件,生成的临时图片...)  
55 - * @param config 配置项 控制资源清理的粒度  
56 - */  
57 - void destroy(Properties config); 57 + /**
  58 + * 历史资源清除(过期的图片文件,生成的临时图片...)
  59 + *
  60 + * @param config 配置项 控制资源清理的粒度
  61 + */
  62 + void destroy(Properties config);
58 } 63 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/AbstractCaptchaService.java
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 */ 6 */
7 package com.anji.captcha.service.impl; 7 package com.anji.captcha.service.impl;
8 8
  9 +import cn.hutool.core.util.StrUtil;
9 import com.anji.captcha.model.common.Const; 10 import com.anji.captcha.model.common.Const;
10 import com.anji.captcha.model.common.RepCodeEnum; 11 import com.anji.captcha.model.common.RepCodeEnum;
11 import com.anji.captcha.model.common.ResponseModel; 12 import com.anji.captcha.model.common.ResponseModel;
@@ -13,29 +14,28 @@ import com.anji.captcha.model.vo.CaptchaVO; @@ -13,29 +14,28 @@ import com.anji.captcha.model.vo.CaptchaVO;
13 import com.anji.captcha.service.CaptchaCacheService; 14 import com.anji.captcha.service.CaptchaCacheService;
14 import com.anji.captcha.service.CaptchaService; 15 import com.anji.captcha.service.CaptchaService;
15 import com.anji.captcha.util.*; 16 import com.anji.captcha.util.*;
16 -import org.slf4j.Logger;  
17 -import org.slf4j.LoggerFactory; 17 +import lombok.extern.slf4j.Slf4j;
18 18
19 import java.awt.*; 19 import java.awt.*;
20 import java.io.File; 20 import java.io.File;
21 -import java.io.FileOutputStream;  
22 import java.io.OutputStream; 21 import java.io.OutputStream;
23 import java.nio.charset.StandardCharsets; 22 import java.nio.charset.StandardCharsets;
  23 +import java.nio.file.Files;
24 import java.util.Base64; 24 import java.util.Base64;
  25 +import java.util.Objects;
25 import java.util.Properties; 26 import java.util.Properties;
26 27
27 /** 28 /**
28 * Created by raodeming on 2019/12/25. 29 * Created by raodeming on 2019/12/25.
29 */ 30 */
  31 +@Slf4j
30 public abstract class AbstractCaptchaService implements CaptchaService { 32 public abstract class AbstractCaptchaService implements CaptchaService {
31 33
32 - protected Logger logger = LoggerFactory.getLogger(getClass());  
33 -  
34 protected static final String IMAGE_TYPE_PNG = "png"; 34 protected static final String IMAGE_TYPE_PNG = "png";
35 35
36 - protected static int HAN_ZI_SIZE = 25; 36 + protected static int HAN_ZI_SIZE = 25;
37 37
38 - protected static int HAN_ZI_SIZE_HALF = HAN_ZI_SIZE / 2; 38 + protected static int HAN_ZI_SIZE_HALF = HAN_ZI_SIZE / 2;
39 //check校验坐标 39 //check校验坐标
40 protected static String REDIS_CAPTCHA_KEY = "RUNNING:CAPTCHA:%s"; 40 protected static String REDIS_CAPTCHA_KEY = "RUNNING:CAPTCHA:%s";
41 41
@@ -73,7 +73,7 @@ public abstract class AbstractCaptchaService implements CaptchaService { @@ -73,7 +73,7 @@ public abstract class AbstractCaptchaService implements CaptchaService {
73 ImageUtils.cacheImage(config.getProperty(Const.ORIGINAL_PATH_JIGSAW), 73 ImageUtils.cacheImage(config.getProperty(Const.ORIGINAL_PATH_JIGSAW),
74 config.getProperty(Const.ORIGINAL_PATH_PIC_CLICK)); 74 config.getProperty(Const.ORIGINAL_PATH_PIC_CLICK));
75 } 75 }
76 - logger.info("--->>>初始化验证码底图<<<---" + captchaType()); 76 + log.info("--->>>初始化验证码底图<<<---" + captchaType());
77 waterMark = config.getProperty(Const.CAPTCHA_WATER_MARK, "我的水印"); 77 waterMark = config.getProperty(Const.CAPTCHA_WATER_MARK, "我的水印");
78 slipOffset = config.getProperty(Const.CAPTCHA_SLIP_OFFSET, "5"); 78 slipOffset = config.getProperty(Const.CAPTCHA_SLIP_OFFSET, "5");
79 waterMarkFontStr = config.getProperty(Const.CAPTCHA_WATER_FONT, "WenQuanZhengHei.ttf"); 79 waterMarkFontStr = config.getProperty(Const.CAPTCHA_WATER_FONT, "WenQuanZhengHei.ttf");
@@ -88,13 +88,13 @@ public abstract class AbstractCaptchaService implements CaptchaService { @@ -88,13 +88,13 @@ public abstract class AbstractCaptchaService implements CaptchaService {
88 // 通过加载resources下的font字体解决,无需在linux中安装字体 88 // 通过加载resources下的font字体解决,无需在linux中安装字体
89 loadWaterMarkFont(); 89 loadWaterMarkFont();
90 90
91 - if (cacheType.equals("local")) {  
92 - logger.info("初始化local缓存..."); 91 + if ("local".equals(cacheType)) {
  92 + log.info("初始化local缓存...");
93 CacheUtil.init(Integer.parseInt(config.getProperty(Const.CAPTCHA_CACAHE_MAX_NUMBER, "1000")), 93 CacheUtil.init(Integer.parseInt(config.getProperty(Const.CAPTCHA_CACAHE_MAX_NUMBER, "1000")),
94 Long.parseLong(config.getProperty(Const.CAPTCHA_TIMING_CLEAR_SECOND, "180"))); 94 Long.parseLong(config.getProperty(Const.CAPTCHA_TIMING_CLEAR_SECOND, "180")));
95 } 95 }
96 - if (config.getProperty(Const.HISTORY_DATA_CLEAR_ENABLE, "0").equals("1")) {  
97 - logger.info("历史资源清除开关...开启..." + captchaType()); 96 + if ("1".equals(config.getProperty(Const.HISTORY_DATA_CLEAR_ENABLE, "0"))) {
  97 + log.info("历史资源清除开关...开启..." + captchaType());
98 Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 98 Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
99 @Override 99 @Override
100 public void run() { 100 public void run() {
@@ -102,9 +102,9 @@ public abstract class AbstractCaptchaService implements CaptchaService { @@ -102,9 +102,9 @@ public abstract class AbstractCaptchaService implements CaptchaService {
102 } 102 }
103 })); 103 }));
104 } 104 }
105 - if (config.getProperty(Const.REQ_FREQUENCY_LIMIT_ENABLE, "0").equals("1")) { 105 + if ("1".equals(config.getProperty(Const.REQ_FREQUENCY_LIMIT_ENABLE, "0"))) {
106 if (limitHandler == null) { 106 if (limitHandler == null) {
107 - logger.info("接口分钟内限流开关...开启..."); 107 + log.info("接口分钟内限流开关...开启...");
108 limitHandler = new FrequencyLimitHandler.DefaultLimitHandler(config, getCacheService(cacheType)); 108 limitHandler = new FrequencyLimitHandler.DefaultLimitHandler(config, getCacheService(cacheType));
109 } 109 }
110 } 110 }
@@ -150,7 +150,7 @@ public abstract class AbstractCaptchaService implements CaptchaService { @@ -150,7 +150,7 @@ public abstract class AbstractCaptchaService implements CaptchaService {
150 if (captchaVO == null) { 150 if (captchaVO == null) {
151 return RepCodeEnum.NULL_ERROR.parseError("captchaVO"); 151 return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
152 } 152 }
153 - if (StringUtils.isEmpty(captchaVO.getCaptchaVerification())) { 153 + if (StrUtil.isEmpty(captchaVO.getCaptchaVerification())) {
154 return RepCodeEnum.NULL_ERROR.parseError("captchaVerification"); 154 return RepCodeEnum.NULL_ERROR.parseError("captchaVerification");
155 } 155 }
156 if (limitHandler != null) { 156 if (limitHandler != null) {
@@ -163,17 +163,17 @@ public abstract class AbstractCaptchaService implements CaptchaService { @@ -163,17 +163,17 @@ public abstract class AbstractCaptchaService implements CaptchaService {
163 return resp == null || resp.isSuccess(); 163 return resp == null || resp.isSuccess();
164 } 164 }
165 165
166 - protected String getValidateClientId(CaptchaVO req){  
167 - // 以服务端获取的客户端标识 做识别标志  
168 - if(StringUtils.isNotEmpty(req.getBrowserInfo())){  
169 - return MD5Util.md5(req.getBrowserInfo());  
170 - }  
171 - // 以客户端Ui组件id做识别标志  
172 - if(StringUtils.isNotEmpty(req.getClientUid())){  
173 - return req.getClientUid();  
174 - }  
175 - return null;  
176 - } 166 + protected String getValidateClientId(CaptchaVO req) {
  167 + // 以服务端获取的客户端标识 做识别标志
  168 + if (StrUtil.isNotEmpty(req.getBrowserInfo())) {
  169 + return MD5Util.md5(req.getBrowserInfo());
  170 + }
  171 + // 以客户端Ui组件id做识别标志
  172 + if (StrUtil.isNotEmpty(req.getClientUid())) {
  173 + return req.getClientUid();
  174 + }
  175 + return null;
  176 + }
177 177
178 protected void afterValidateFail(CaptchaVO data) { 178 protected void afterValidateFail(CaptchaVO data) {
179 if (limitHandler != null) { 179 if (limitHandler != null) {
@@ -197,14 +197,14 @@ public abstract class AbstractCaptchaService implements CaptchaService { @@ -197,14 +197,14 @@ public abstract class AbstractCaptchaService implements CaptchaService {
197 if (waterMarkFontStr.toLowerCase().endsWith(".ttf") || waterMarkFontStr.toLowerCase().endsWith(".ttc") 197 if (waterMarkFontStr.toLowerCase().endsWith(".ttf") || waterMarkFontStr.toLowerCase().endsWith(".ttc")
198 || waterMarkFontStr.toLowerCase().endsWith(".otf")) { 198 || waterMarkFontStr.toLowerCase().endsWith(".otf")) {
199 this.waterMarkFont = Font.createFont(Font.TRUETYPE_FONT, 199 this.waterMarkFont = Font.createFont(Font.TRUETYPE_FONT,
200 - getClass().getResourceAsStream("/fonts/" + waterMarkFontStr)) 200 + Objects.requireNonNull(getClass().getResourceAsStream("/fonts/" + waterMarkFontStr)))
201 .deriveFont(Font.BOLD, HAN_ZI_SIZE / 2); 201 .deriveFont(Font.BOLD, HAN_ZI_SIZE / 2);
202 } else { 202 } else {
203 this.waterMarkFont = new Font(waterMarkFontStr, Font.BOLD, HAN_ZI_SIZE / 2); 203 this.waterMarkFont = new Font(waterMarkFontStr, Font.BOLD, HAN_ZI_SIZE / 2);
204 } 204 }
205 205
206 } catch (Exception e) { 206 } catch (Exception e) {
207 - logger.error("load font error:{}", e); 207 + log.error("load font error:{}", e);
208 } 208 }
209 } 209 }
210 210
@@ -228,7 +228,7 @@ public abstract class AbstractCaptchaService implements CaptchaService { @@ -228,7 +228,7 @@ public abstract class AbstractCaptchaService implements CaptchaService {
228 if (!tempFile.getParentFile().exists()) { 228 if (!tempFile.getParentFile().exists()) {
229 tempFile.getParentFile().mkdirs(); 229 tempFile.getParentFile().mkdirs();
230 } 230 }
231 - OutputStream out = new FileOutputStream(tempFile); 231 + OutputStream out = Files.newOutputStream(tempFile.toPath());
232 out.write(b); 232 out.write(b);
233 out.flush(); 233 out.flush();
234 out.close(); 234 out.close();
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/BlockPuzzleCaptchaServiceImpl.java
@@ -6,12 +6,14 @@ @@ -6,12 +6,14 @@
6 */ 6 */
7 package com.anji.captcha.service.impl; 7 package com.anji.captcha.service.impl;
8 8
  9 +import cn.hutool.core.util.StrUtil;
9 import com.anji.captcha.model.common.CaptchaTypeEnum; 10 import com.anji.captcha.model.common.CaptchaTypeEnum;
10 import com.anji.captcha.model.common.RepCodeEnum; 11 import com.anji.captcha.model.common.RepCodeEnum;
11 import com.anji.captcha.model.common.ResponseModel; 12 import com.anji.captcha.model.common.ResponseModel;
12 import com.anji.captcha.model.vo.CaptchaVO; 13 import com.anji.captcha.model.vo.CaptchaVO;
13 import com.anji.captcha.model.vo.PointVO; 14 import com.anji.captcha.model.vo.PointVO;
14 import com.anji.captcha.util.*; 15 import com.anji.captcha.util.*;
  16 +import lombok.extern.slf4j.Slf4j;
15 17
16 import javax.imageio.ImageIO; 18 import javax.imageio.ImageIO;
17 import java.awt.*; 19 import java.awt.*;
@@ -27,6 +29,7 @@ import java.util.Random; @@ -27,6 +29,7 @@ import java.util.Random;
27 * <p> 29 * <p>
28 * Created by raodeming on 2019/12/25. 30 * Created by raodeming on 2019/12/25.
29 */ 31 */
  32 +@Slf4j
30 public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { 33 public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
31 34
32 @Override 35 @Override
@@ -34,10 +37,10 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -34,10 +37,10 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
34 super.init(config); 37 super.init(config);
35 } 38 }
36 39
37 - @Override  
38 - public void destroy(Properties config) {  
39 - logger.info("start-clear-history-data-",captchaType());  
40 - } 40 + @Override
  41 + public void destroy(Properties config) {
  42 + log.info("start-clear-history-data-", captchaType());
  43 + }
41 44
42 @Override 45 @Override
43 public String captchaType() { 46 public String captchaType() {
@@ -46,14 +49,14 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -46,14 +49,14 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
46 49
47 @Override 50 @Override
48 public ResponseModel get(CaptchaVO captchaVO) { 51 public ResponseModel get(CaptchaVO captchaVO) {
49 - ResponseModel r = super.get(captchaVO);  
50 - if(!validatedReq(r)){  
51 - return r;  
52 - } 52 + ResponseModel r = super.get(captchaVO);
  53 + if (!validatedReq(r)) {
  54 + return r;
  55 + }
53 //原生图片 56 //原生图片
54 BufferedImage originalImage = ImageUtils.getOriginal(); 57 BufferedImage originalImage = ImageUtils.getOriginal();
55 if (null == originalImage) { 58 if (null == originalImage) {
56 - logger.error("滑动底图未初始化成功,请检查路径"); 59 + log.error("滑动底图未初始化成功,请检查路径");
57 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL); 60 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL);
58 } 61 }
59 //设置水印 62 //设置水印
@@ -68,13 +71,13 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -68,13 +71,13 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
68 String jigsawImageBase64 = ImageUtils.getslidingBlock(); 71 String jigsawImageBase64 = ImageUtils.getslidingBlock();
69 BufferedImage jigsawImage = ImageUtils.getBase64StrToImage(jigsawImageBase64); 72 BufferedImage jigsawImage = ImageUtils.getBase64StrToImage(jigsawImageBase64);
70 if (null == jigsawImage) { 73 if (null == jigsawImage) {
71 - logger.error("滑动底图未初始化成功,请检查路径"); 74 + log.error("滑动底图未初始化成功,请检查路径");
72 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL); 75 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL);
73 } 76 }
74 CaptchaVO captcha = pictureTemplatesCut(originalImage, jigsawImage, jigsawImageBase64); 77 CaptchaVO captcha = pictureTemplatesCut(originalImage, jigsawImage, jigsawImageBase64);
75 if (captcha == null 78 if (captcha == null
76 - || StringUtils.isBlank(captcha.getJigsawImageBase64())  
77 - || StringUtils.isBlank(captcha.getOriginalImageBase64())) { 79 + || StrUtil.isBlank(captcha.getJigsawImageBase64())
  80 + || StrUtil.isBlank(captcha.getOriginalImageBase64())) {
78 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_ERROR); 81 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_ERROR);
79 } 82 }
80 return ResponseModel.successData(captcha); 83 return ResponseModel.successData(captcha);
@@ -82,10 +85,10 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -82,10 +85,10 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
82 85
83 @Override 86 @Override
84 public ResponseModel check(CaptchaVO captchaVO) { 87 public ResponseModel check(CaptchaVO captchaVO) {
85 - ResponseModel r = super.check(captchaVO);  
86 - if(!validatedReq(r)){  
87 - return r;  
88 - } 88 + ResponseModel r = super.check(captchaVO);
  89 + if (!validatedReq(r)) {
  90 + return r;
  91 + }
89 //取坐标信息 92 //取坐标信息
90 String codeKey = String.format(REDIS_CAPTCHA_KEY, captchaVO.getToken()); 93 String codeKey = String.format(REDIS_CAPTCHA_KEY, captchaVO.getToken());
91 if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) { 94 if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) {
@@ -103,7 +106,7 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -103,7 +106,7 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
103 pointJson = decrypt(captchaVO.getPointJson(), point.getSecretKey()); 106 pointJson = decrypt(captchaVO.getPointJson(), point.getSecretKey());
104 point1 = JsonUtil.parseObject(pointJson, PointVO.class); 107 point1 = JsonUtil.parseObject(pointJson, PointVO.class);
105 } catch (Exception e) { 108 } catch (Exception e) {
106 - logger.error("验证码坐标解析失败", e); 109 + log.error("验证码坐标解析失败", e);
107 afterValidateFail(captchaVO); 110 afterValidateFail(captchaVO);
108 return ResponseModel.errorMsg(e.getMessage()); 111 return ResponseModel.errorMsg(e.getMessage());
109 } 112 }
@@ -119,7 +122,7 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -119,7 +122,7 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
119 try { 122 try {
120 value = AESUtil.aesEncrypt(captchaVO.getToken().concat("---").concat(pointJson), secretKey); 123 value = AESUtil.aesEncrypt(captchaVO.getToken().concat("---").concat(pointJson), secretKey);
121 } catch (Exception e) { 124 } catch (Exception e) {
122 - logger.error("AES加密失败", e); 125 + log.error("AES加密失败", e);
123 afterValidateFail(captchaVO); 126 afterValidateFail(captchaVO);
124 return ResponseModel.errorMsg(e.getMessage()); 127 return ResponseModel.errorMsg(e.getMessage());
125 } 128 }
@@ -132,10 +135,10 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -132,10 +135,10 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
132 135
133 @Override 136 @Override
134 public ResponseModel verification(CaptchaVO captchaVO) { 137 public ResponseModel verification(CaptchaVO captchaVO) {
135 - ResponseModel r = super.verification(captchaVO);  
136 - if(!validatedReq(r)){  
137 - return r;  
138 - } 138 + ResponseModel r = super.verification(captchaVO);
  139 + if (!validatedReq(r)) {
  140 + return r;
  141 + }
139 try { 142 try {
140 String codeKey = String.format(REDIS_SECOND_CAPTCHA_KEY, captchaVO.getCaptchaVerification()); 143 String codeKey = String.format(REDIS_SECOND_CAPTCHA_KEY, captchaVO.getCaptchaVerification());
141 if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) { 144 if (!CaptchaServiceFactory.getCache(cacheType).exists(codeKey)) {
@@ -144,7 +147,7 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -144,7 +147,7 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
144 //二次校验取值后,即刻失效 147 //二次校验取值后,即刻失效
145 CaptchaServiceFactory.getCache(cacheType).delete(codeKey); 148 CaptchaServiceFactory.getCache(cacheType).delete(codeKey);
146 } catch (Exception e) { 149 } catch (Exception e) {
147 - logger.error("验证码坐标解析失败", e); 150 + log.error("验证码坐标解析失败", e);
148 return ResponseModel.errorMsg(e.getMessage()); 151 return ResponseModel.errorMsg(e.getMessage());
149 } 152 }
150 return ResponseModel.success(); 153 return ResponseModel.success();
@@ -234,7 +237,7 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService { @@ -234,7 +237,7 @@ public class BlockPuzzleCaptchaServiceImpl extends AbstractCaptchaService {
234 //将坐标信息存入redis中 237 //将坐标信息存入redis中
235 String codeKey = String.format(REDIS_CAPTCHA_KEY, dataVO.getToken()); 238 String codeKey = String.format(REDIS_CAPTCHA_KEY, dataVO.getToken());
236 CaptchaServiceFactory.getCache(cacheType).set(codeKey, JsonUtil.toJSONString(point), EXPIRESIN_SECONDS); 239 CaptchaServiceFactory.getCache(cacheType).set(codeKey, JsonUtil.toJSONString(point), EXPIRESIN_SECONDS);
237 - logger.debug("token:{},point:{}", dataVO.getToken(), JsonUtil.toJSONString(point)); 240 + log.debug("token:{},point:{}", dataVO.getToken(), JsonUtil.toJSONString(point));
238 return dataVO; 241 return dataVO;
239 } catch (Exception e) { 242 } catch (Exception e) {
240 e.printStackTrace(); 243 e.printStackTrace();
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/CaptchaCacheServiceMemImpl.java
@@ -3,12 +3,15 @@ package com.anji.captcha.service.impl; @@ -3,12 +3,15 @@ package com.anji.captcha.service.impl;
3 import com.anji.captcha.service.CaptchaCacheService; 3 import com.anji.captcha.service.CaptchaCacheService;
4 import com.anji.captcha.util.CacheUtil; 4 import com.anji.captcha.util.CacheUtil;
5 5
  6 +import java.util.Objects;
  7 +
6 /** 8 /**
7 * 对于分布式部署的应用,我们建议应用自己实现CaptchaCacheService,比如用Redis,参考service/spring-boot代码示例。 9 * 对于分布式部署的应用,我们建议应用自己实现CaptchaCacheService,比如用Redis,参考service/spring-boot代码示例。
8 * 如果应用是单点的,也没有使用redis,那默认使用内存。 10 * 如果应用是单点的,也没有使用redis,那默认使用内存。
9 * 内存缓存只适合单节点部署的应用,否则验证码生产与验证在节点之间信息不同步,导致失败。 11 * 内存缓存只适合单节点部署的应用,否则验证码生产与验证在节点之间信息不同步,导致失败。
10 - * @Title: 默认使用内存当缓存 12 + *
11 * @author lide1202@hotmail.com 13 * @author lide1202@hotmail.com
  14 + * @Title: 默认使用内存当缓存
12 * @date 2020-05-12 15 * @date 2020-05-12
13 */ 16 */
14 public class CaptchaCacheServiceMemImpl implements CaptchaCacheService { 17 public class CaptchaCacheServiceMemImpl implements CaptchaCacheService {
@@ -33,14 +36,14 @@ public class CaptchaCacheServiceMemImpl implements CaptchaCacheService { @@ -33,14 +36,14 @@ public class CaptchaCacheServiceMemImpl implements CaptchaCacheService {
33 return CacheUtil.get(key); 36 return CacheUtil.get(key);
34 } 37 }
35 38
36 - @Override  
37 - public Long increment(String key, long val) {  
38 - Long ret = Long.valueOf(CacheUtil.get(key))+val;  
39 - CacheUtil.set(key,ret+"",0);  
40 - return ret;  
41 - } 39 + @Override
  40 + public Long increment(String key, long val) {
  41 + Long ret = Long.parseLong(Objects.requireNonNull(CacheUtil.get(key))) + val;
  42 + CacheUtil.set(key, ret + "", 0);
  43 + return ret;
  44 + }
42 45
43 - @Override 46 + @Override
44 public String type() { 47 public String type() {
45 return "local"; 48 return "local";
46 } 49 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/CaptchaServiceFactory.java
@@ -3,8 +3,7 @@ package com.anji.captcha.service.impl; @@ -3,8 +3,7 @@ package com.anji.captcha.service.impl;
3 import com.anji.captcha.model.common.Const; 3 import com.anji.captcha.model.common.Const;
4 import com.anji.captcha.service.CaptchaCacheService; 4 import com.anji.captcha.service.CaptchaCacheService;
5 import com.anji.captcha.service.CaptchaService; 5 import com.anji.captcha.service.CaptchaService;
6 -import org.slf4j.Logger;  
7 -import org.slf4j.LoggerFactory; 6 +import lombok.extern.slf4j.Slf4j;
8 7
9 import java.util.HashMap; 8 import java.util.HashMap;
10 import java.util.Map; 9 import java.util.Map;
@@ -14,10 +13,9 @@ import java.util.ServiceLoader; @@ -14,10 +13,9 @@ import java.util.ServiceLoader;
14 /** 13 /**
15 * Created by raodeming on 2020/5/26. 14 * Created by raodeming on 2020/5/26.
16 */ 15 */
  16 +@Slf4j
17 public class CaptchaServiceFactory { 17 public class CaptchaServiceFactory {
18 18
19 - private static Logger logger = LoggerFactory.getLogger(CaptchaServiceFactory.class);  
20 -  
21 public static CaptchaService getInstance(Properties config) { 19 public static CaptchaService getInstance(Properties config) {
22 //先把所有CaptchaService初始化,通过init方法,实例字体等,add by lide1202@hotmail.com 20 //先把所有CaptchaService初始化,通过init方法,实例字体等,add by lide1202@hotmail.com
23 /*try{ 21 /*try{
@@ -41,20 +39,20 @@ public class CaptchaServiceFactory { @@ -41,20 +39,20 @@ public class CaptchaServiceFactory {
41 return cacheService.get(cacheType); 39 return cacheService.get(cacheType);
42 } 40 }
43 41
44 - public volatile static Map<String, CaptchaService> instances = new HashMap();  
45 - public volatile static Map<String, CaptchaCacheService> cacheService = new HashMap(); 42 + public volatile static Map<String, CaptchaService> instances = new HashMap<>();
  43 + public volatile static Map<String, CaptchaCacheService> cacheService = new HashMap<>();
46 44
47 static { 45 static {
48 ServiceLoader<CaptchaCacheService> cacheServices = ServiceLoader.load(CaptchaCacheService.class); 46 ServiceLoader<CaptchaCacheService> cacheServices = ServiceLoader.load(CaptchaCacheService.class);
49 for (CaptchaCacheService item : cacheServices) { 47 for (CaptchaCacheService item : cacheServices) {
50 cacheService.put(item.type(), item); 48 cacheService.put(item.type(), item);
51 } 49 }
52 - logger.info("supported-captchaCache-service:{}", cacheService.keySet().toString()); 50 + log.info("supported-captchaCache-service:{}", cacheService.keySet().toString());
53 ServiceLoader<CaptchaService> services = ServiceLoader.load(CaptchaService.class); 51 ServiceLoader<CaptchaService> services = ServiceLoader.load(CaptchaService.class);
54 for (CaptchaService item : services) { 52 for (CaptchaService item : services) {
55 instances.put(item.captchaType(), item); 53 instances.put(item.captchaType(), item);
56 } 54 }
57 ; 55 ;
58 - logger.info("supported-captchaTypes-service:{}", instances.keySet().toString()); 56 + log.info("supported-captchaTypes-service:{}", instances.keySet().toString());
59 } 57 }
60 } 58 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/ClickWordCaptchaServiceImpl.java
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 */ 6 */
7 package com.anji.captcha.service.impl; 7 package com.anji.captcha.service.impl;
8 8
  9 +import cn.hutool.core.util.StrUtil;
9 import com.anji.captcha.model.common.CaptchaTypeEnum; 10 import com.anji.captcha.model.common.CaptchaTypeEnum;
10 import com.anji.captcha.model.common.Const; 11 import com.anji.captcha.model.common.Const;
11 import com.anji.captcha.model.common.RepCodeEnum; 12 import com.anji.captcha.model.common.RepCodeEnum;
@@ -13,6 +14,7 @@ import com.anji.captcha.model.common.ResponseModel; @@ -13,6 +14,7 @@ import com.anji.captcha.model.common.ResponseModel;
13 import com.anji.captcha.model.vo.CaptchaVO; 14 import com.anji.captcha.model.vo.CaptchaVO;
14 import com.anji.captcha.model.vo.PointVO; 15 import com.anji.captcha.model.vo.PointVO;
15 import com.anji.captcha.util.*; 16 import com.anji.captcha.util.*;
  17 +import lombok.extern.slf4j.Slf4j;
16 18
17 import java.awt.*; 19 import java.awt.*;
18 import java.awt.geom.AffineTransform; 20 import java.awt.geom.AffineTransform;
@@ -25,6 +27,7 @@ import java.util.*; @@ -25,6 +27,7 @@ import java.util.*;
25 * <p> 27 * <p>
26 * Created by raodeming on 2019/12/25. 28 * Created by raodeming on 2019/12/25.
27 */ 29 */
  30 +@Slf4j
28 public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService { 31 public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService {
29 32
30 public static String HAN_ZI = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6"; 33 public static String HAN_ZI = "\u7684\u4e00\u4e86\u662f\u6211\u4e0d\u5728\u4eba\u4eec\u6709\u6765\u4ed6\u8fd9\u4e0a\u7740\u4e2a\u5730\u5230\u5927\u91cc\u8bf4\u5c31\u53bb\u5b50\u5f97\u4e5f\u548c\u90a3\u8981\u4e0b\u770b\u5929\u65f6\u8fc7\u51fa\u5c0f\u4e48\u8d77\u4f60\u90fd\u628a\u597d\u8fd8\u591a\u6ca1\u4e3a\u53c8\u53ef\u5bb6\u5b66\u53ea\u4ee5\u4e3b\u4f1a\u6837\u5e74\u60f3\u751f\u540c\u8001\u4e2d\u5341\u4ece\u81ea\u9762\u524d\u5934\u9053\u5b83\u540e\u7136\u8d70\u5f88\u50cf\u89c1\u4e24\u7528\u5979\u56fd\u52a8\u8fdb\u6210\u56de\u4ec0\u8fb9\u4f5c\u5bf9\u5f00\u800c\u5df1\u4e9b\u73b0\u5c71\u6c11\u5019\u7ecf\u53d1\u5de5\u5411\u4e8b\u547d\u7ed9\u957f\u6c34\u51e0\u4e49\u4e09\u58f0\u4e8e\u9ad8\u624b\u77e5\u7406\u773c\u5fd7\u70b9\u5fc3\u6218\u4e8c\u95ee\u4f46\u8eab\u65b9\u5b9e\u5403\u505a\u53eb\u5f53\u4f4f\u542c\u9769\u6253\u5462\u771f\u5168\u624d\u56db\u5df2\u6240\u654c\u4e4b\u6700\u5149\u4ea7\u60c5\u8def\u5206\u603b\u6761\u767d\u8bdd\u4e1c\u5e2d\u6b21\u4eb2\u5982\u88ab\u82b1\u53e3\u653e\u513f\u5e38\u6c14\u4e94\u7b2c\u4f7f\u5199\u519b\u5427\u6587\u8fd0\u518d\u679c\u600e\u5b9a\u8bb8\u5feb\u660e\u884c\u56e0\u522b\u98de\u5916\u6811\u7269\u6d3b\u90e8\u95e8\u65e0\u5f80\u8239\u671b\u65b0\u5e26\u961f\u5148\u529b\u5b8c\u5374\u7ad9\u4ee3\u5458\u673a\u66f4\u4e5d\u60a8\u6bcf\u98ce\u7ea7\u8ddf\u7b11\u554a\u5b69\u4e07\u5c11\u76f4\u610f\u591c\u6bd4\u9636\u8fde\u8f66\u91cd\u4fbf\u6597\u9a6c\u54ea\u5316\u592a\u6307\u53d8\u793e\u4f3c\u58eb\u8005\u5e72\u77f3\u6ee1\u65e5\u51b3\u767e\u539f\u62ff\u7fa4\u7a76\u5404\u516d\u672c\u601d\u89e3\u7acb\u6cb3\u6751\u516b\u96be\u65e9\u8bba\u5417\u6839\u5171\u8ba9\u76f8\u7814\u4eca\u5176\u4e66\u5750\u63a5\u5e94\u5173\u4fe1\u89c9\u6b65\u53cd\u5904\u8bb0\u5c06\u5343\u627e\u4e89\u9886\u6216\u5e08\u7ed3\u5757\u8dd1\u8c01\u8349\u8d8a\u5b57\u52a0\u811a\u7d27\u7231\u7b49\u4e60\u9635\u6015\u6708\u9752\u534a\u706b\u6cd5\u9898\u5efa\u8d76\u4f4d\u5531\u6d77\u4e03\u5973\u4efb\u4ef6\u611f\u51c6\u5f20\u56e2\u5c4b\u79bb\u8272\u8138\u7247\u79d1\u5012\u775b\u5229\u4e16\u521a\u4e14\u7531\u9001\u5207\u661f\u5bfc\u665a\u8868\u591f\u6574\u8ba4\u54cd\u96ea\u6d41\u672a\u573a\u8be5\u5e76\u5e95\u6df1\u523b\u5e73\u4f1f\u5fd9\u63d0\u786e\u8fd1\u4eae\u8f7b\u8bb2\u519c\u53e4\u9ed1\u544a\u754c\u62c9\u540d\u5440\u571f\u6e05\u9633\u7167\u529e\u53f2\u6539\u5386\u8f6c\u753b\u9020\u5634\u6b64\u6cbb\u5317\u5fc5\u670d\u96e8\u7a7f\u5185\u8bc6\u9a8c\u4f20\u4e1a\u83dc\u722c\u7761\u5174\u5f62\u91cf\u54b1\u89c2\u82e6\u4f53\u4f17\u901a\u51b2\u5408\u7834\u53cb\u5ea6\u672f\u996d\u516c\u65c1\u623f\u6781\u5357\u67aa\u8bfb\u6c99\u5c81\u7ebf\u91ce\u575a\u7a7a\u6536\u7b97\u81f3\u653f\u57ce\u52b3\u843d\u94b1\u7279\u56f4\u5f1f\u80dc\u6559\u70ed\u5c55\u5305\u6b4c\u7c7b\u6e10\u5f3a\u6570\u4e61\u547c\u6027\u97f3\u7b54\u54e5\u9645\u65e7\u795e\u5ea7\u7ae0\u5e2e\u5566\u53d7\u7cfb\u4ee4\u8df3\u975e\u4f55\u725b\u53d6\u5165\u5cb8\u6562\u6389\u5ffd\u79cd\u88c5\u9876\u6025\u6797\u505c\u606f\u53e5\u533a\u8863\u822c\u62a5\u53f6\u538b\u6162\u53d4\u80cc\u7ec6";
@@ -43,27 +46,27 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService { @@ -43,27 +46,27 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService {
43 super.init(config); 46 super.init(config);
44 clickWordFontStr = config.getProperty(Const.CAPTCHA_FONT_TYPE, "SourceHanSansCN-Normal.otf"); 47 clickWordFontStr = config.getProperty(Const.CAPTCHA_FONT_TYPE, "SourceHanSansCN-Normal.otf");
45 try { 48 try {
46 - int size = Integer.valueOf(config.getProperty(Const.CAPTCHA_FONT_SIZE,HAN_ZI_SIZE+"")); 49 + int size = Integer.parseInt(config.getProperty(Const.CAPTCHA_FONT_SIZE,HAN_ZI_SIZE+""));
47 50
48 if (clickWordFontStr.toLowerCase().endsWith(".ttf") 51 if (clickWordFontStr.toLowerCase().endsWith(".ttf")
49 || clickWordFontStr.toLowerCase().endsWith(".ttc") 52 || clickWordFontStr.toLowerCase().endsWith(".ttc")
50 || clickWordFontStr.toLowerCase().endsWith(".otf")) { 53 || clickWordFontStr.toLowerCase().endsWith(".otf")) {
51 this.clickWordFont = Font.createFont(Font.TRUETYPE_FONT, 54 this.clickWordFont = Font.createFont(Font.TRUETYPE_FONT,
52 - getClass().getResourceAsStream("/fonts/" + clickWordFontStr)) 55 + Objects.requireNonNull(getClass().getResourceAsStream("/fonts/" + clickWordFontStr)))
53 .deriveFont(Font.BOLD, size); 56 .deriveFont(Font.BOLD, size);
54 } else { 57 } else {
55 - int style = Integer.valueOf(config.getProperty(Const.CAPTCHA_FONT_STYLE,Font.BOLD+"")); 58 + int style = Integer.parseInt(config.getProperty(Const.CAPTCHA_FONT_STYLE,Font.BOLD+""));
56 this.clickWordFont = new Font(clickWordFontStr, style, size); 59 this.clickWordFont = new Font(clickWordFontStr, style, size);
57 } 60 }
58 } catch (Exception ex) { 61 } catch (Exception ex) {
59 - logger.error("load font error:{}", ex); 62 + log.error("load font error:{}", ex);
60 } 63 }
61 - this.wordTotalCount = Integer.valueOf(config.getProperty(Const.CAPTCHA_WORD_COUNT,"4")); 64 + this.wordTotalCount = Integer.parseInt(config.getProperty(Const.CAPTCHA_WORD_COUNT,"4"));
62 } 65 }
63 66
64 @Override 67 @Override
65 public void destroy(Properties config) { 68 public void destroy(Properties config) {
66 - logger.info("start-clear-history-data-", captchaType()); 69 + log.info("start-clear-history-data-", captchaType());
67 } 70 }
68 71
69 @Override 72 @Override
@@ -74,12 +77,12 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService { @@ -74,12 +77,12 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService {
74 } 77 }
75 BufferedImage bufferedImage = ImageUtils.getPicClick(); 78 BufferedImage bufferedImage = ImageUtils.getPicClick();
76 if (null == bufferedImage) { 79 if (null == bufferedImage) {
77 - logger.error("滑动底图未初始化成功,请检查路径"); 80 + log.error("滑动底图未初始化成功,请检查路径");
78 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL); 81 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_BASEMAP_NULL);
79 } 82 }
80 CaptchaVO imageData = getImageData(bufferedImage); 83 CaptchaVO imageData = getImageData(bufferedImage);
81 if (imageData == null 84 if (imageData == null
82 - || StringUtils.isBlank(imageData.getOriginalImageBase64())) { 85 + || StrUtil.isBlank(imageData.getOriginalImageBase64())) {
83 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_ERROR); 86 return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_ERROR);
84 } 87 }
85 return ResponseModel.successData(imageData); 88 return ResponseModel.successData(imageData);
@@ -124,7 +127,7 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService { @@ -124,7 +127,7 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService {
124 pointJson = decrypt(captchaVO.getPointJson(), point.get(0).getSecretKey()); 127 pointJson = decrypt(captchaVO.getPointJson(), point.get(0).getSecretKey());
125 point1 = JsonUtil.parseArray(pointJson, PointVO.class); 128 point1 = JsonUtil.parseArray(pointJson, PointVO.class);
126 } catch (Exception e) { 129 } catch (Exception e) {
127 - logger.error("验证码坐标解析失败", e); 130 + log.error("验证码坐标解析失败", e);
128 afterValidateFail(captchaVO); 131 afterValidateFail(captchaVO);
129 return ResponseModel.errorMsg(e.getMessage()); 132 return ResponseModel.errorMsg(e.getMessage());
130 } 133 }
@@ -143,7 +146,7 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService { @@ -143,7 +146,7 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService {
143 try { 146 try {
144 value = AESUtil.aesEncrypt(captchaVO.getToken().concat("---").concat(pointJson), secretKey); 147 value = AESUtil.aesEncrypt(captchaVO.getToken().concat("---").concat(pointJson), secretKey);
145 } catch (Exception e) { 148 } catch (Exception e) {
146 - logger.error("AES加密失败", e); 149 + log.error("AES加密失败", e);
147 afterValidateFail(captchaVO); 150 afterValidateFail(captchaVO);
148 return ResponseModel.errorMsg(e.getMessage()); 151 return ResponseModel.errorMsg(e.getMessage());
149 } 152 }
@@ -159,7 +162,7 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService { @@ -159,7 +162,7 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService {
159 /*if (captchaVO == null) { 162 /*if (captchaVO == null) {
160 return RepCodeEnum.NULL_ERROR.parseError("captchaVO"); 163 return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
161 } 164 }
162 - if (StringUtils.isEmpty(captchaVO.getCaptchaVerification())) { 165 + if (StrUtil.isEmpty(captchaVO.getCaptchaVerification())) {
163 return RepCodeEnum.NULL_ERROR.parseError("captchaVerification"); 166 return RepCodeEnum.NULL_ERROR.parseError("captchaVerification");
164 }*/ 167 }*/
165 ResponseModel r = super.verification(captchaVO); 168 ResponseModel r = super.verification(captchaVO);
@@ -174,7 +177,7 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService { @@ -174,7 +177,7 @@ public class ClickWordCaptchaServiceImpl extends AbstractCaptchaService {
174 //二次校验取值后,即刻失效 177 //二次校验取值后,即刻失效
175 CaptchaServiceFactory.getCache(cacheType).delete(codeKey); 178 CaptchaServiceFactory.getCache(cacheType).delete(codeKey);
176 } catch (Exception e) { 179 } catch (Exception e) {
177 - logger.error("验证码坐标解析失败", e); 180 + log.error("验证码坐标解析失败", e);
178 return ResponseModel.errorMsg(e.getMessage()); 181 return ResponseModel.errorMsg(e.getMessage());
179 } 182 }
180 return ResponseModel.success(); 183 return ResponseModel.success();
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/DefaultCaptchaServiceImpl.java
@@ -6,17 +6,19 @@ @@ -6,17 +6,19 @@
6 */ 6 */
7 package com.anji.captcha.service.impl; 7 package com.anji.captcha.service.impl;
8 8
  9 +import cn.hutool.core.util.StrUtil;
9 import com.anji.captcha.model.common.RepCodeEnum; 10 import com.anji.captcha.model.common.RepCodeEnum;
10 import com.anji.captcha.model.common.ResponseModel; 11 import com.anji.captcha.model.common.ResponseModel;
11 import com.anji.captcha.model.vo.CaptchaVO; 12 import com.anji.captcha.model.vo.CaptchaVO;
12 import com.anji.captcha.service.CaptchaService; 13 import com.anji.captcha.service.CaptchaService;
13 -import com.anji.captcha.util.StringUtils; 14 +import lombok.extern.slf4j.Slf4j;
14 15
15 import java.util.Properties; 16 import java.util.Properties;
16 17
17 /** 18 /**
18 * Created by raodeming on 2019/12/25. 19 * Created by raodeming on 2019/12/25.
19 */ 20 */
  21 +@Slf4j
20 public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{ 22 public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{
21 23
22 @Override 24 @Override
@@ -53,7 +55,7 @@ public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{ @@ -53,7 +55,7 @@ public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{
53 if (captchaVO == null) { 55 if (captchaVO == null) {
54 return RepCodeEnum.NULL_ERROR.parseError("captchaVO"); 56 return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
55 } 57 }
56 - if (StringUtils.isEmpty(captchaVO.getCaptchaType())) { 58 + if (StrUtil.isEmpty(captchaVO.getCaptchaType())) {
57 return RepCodeEnum.NULL_ERROR.parseError("类型"); 59 return RepCodeEnum.NULL_ERROR.parseError("类型");
58 } 60 }
59 return getService(captchaVO.getCaptchaType()).get(captchaVO); 61 return getService(captchaVO.getCaptchaType()).get(captchaVO);
@@ -64,10 +66,10 @@ public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{ @@ -64,10 +66,10 @@ public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{
64 if (captchaVO == null) { 66 if (captchaVO == null) {
65 return RepCodeEnum.NULL_ERROR.parseError("captchaVO"); 67 return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
66 } 68 }
67 - if (StringUtils.isEmpty(captchaVO.getCaptchaType())) { 69 + if (StrUtil.isEmpty(captchaVO.getCaptchaType())) {
68 return RepCodeEnum.NULL_ERROR.parseError("类型"); 70 return RepCodeEnum.NULL_ERROR.parseError("类型");
69 } 71 }
70 - if (StringUtils.isEmpty(captchaVO.getToken())) { 72 + if (StrUtil.isEmpty(captchaVO.getToken())) {
71 return RepCodeEnum.NULL_ERROR.parseError("token"); 73 return RepCodeEnum.NULL_ERROR.parseError("token");
72 } 74 }
73 return getService(captchaVO.getCaptchaType()).check(captchaVO); 75 return getService(captchaVO.getCaptchaType()).check(captchaVO);
@@ -78,7 +80,7 @@ public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{ @@ -78,7 +80,7 @@ public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{
78 if (captchaVO == null) { 80 if (captchaVO == null) {
79 return RepCodeEnum.NULL_ERROR.parseError("captchaVO"); 81 return RepCodeEnum.NULL_ERROR.parseError("captchaVO");
80 } 82 }
81 - if (StringUtils.isEmpty(captchaVO.getCaptchaVerification())) { 83 + if (StrUtil.isEmpty(captchaVO.getCaptchaVerification())) {
82 return RepCodeEnum.NULL_ERROR.parseError("二次校验参数"); 84 return RepCodeEnum.NULL_ERROR.parseError("二次校验参数");
83 } 85 }
84 try { 86 try {
@@ -89,7 +91,7 @@ public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{ @@ -89,7 +91,7 @@ public class DefaultCaptchaServiceImpl extends AbstractCaptchaService{
89 //二次校验取值后,即刻失效 91 //二次校验取值后,即刻失效
90 CaptchaServiceFactory.getCache(cacheType).delete(codeKey); 92 CaptchaServiceFactory.getCache(cacheType).delete(codeKey);
91 } catch (Exception e) { 93 } catch (Exception e) {
92 - logger.error("验证码坐标解析失败", e); 94 + log.error("验证码坐标解析失败", e);
93 return ResponseModel.errorMsg(e.getMessage()); 95 return ResponseModel.errorMsg(e.getMessage());
94 } 96 }
95 return ResponseModel.success(); 97 return ResponseModel.success();
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/service/impl/FrequencyLimitHandler.java
1 package com.anji.captcha.service.impl; 1 package com.anji.captcha.service.impl;
2 2
  3 +import cn.hutool.core.util.StrUtil;
3 import com.anji.captcha.model.common.Const; 4 import com.anji.captcha.model.common.Const;
4 import com.anji.captcha.model.common.RepCodeEnum; 5 import com.anji.captcha.model.common.RepCodeEnum;
5 import com.anji.captcha.model.common.ResponseModel; 6 import com.anji.captcha.model.common.ResponseModel;
6 import com.anji.captcha.model.vo.CaptchaVO; 7 import com.anji.captcha.model.vo.CaptchaVO;
7 import com.anji.captcha.service.CaptchaCacheService; 8 import com.anji.captcha.service.CaptchaCacheService;
8 -import com.anji.captcha.util.StringUtils;  
9 9
10 import java.util.Objects; 10 import java.util.Objects;
11 import java.util.Properties; 11 import java.util.Properties;
@@ -66,15 +66,15 @@ public interface FrequencyLimitHandler { @@ -66,15 +66,15 @@ public interface FrequencyLimitHandler {
66 } 66 }
67 67
68 private String getClientCId(CaptchaVO input, String type) { 68 private String getClientCId(CaptchaVO input, String type) {
69 - return String.format(LIMIT_KEY ,type,input.getClientUid()); 69 + return String.format(LIMIT_KEY, type, input.getClientUid());
70 } 70 }
71 71
72 @Override 72 @Override
73 public ResponseModel validateGet(CaptchaVO d) { 73 public ResponseModel validateGet(CaptchaVO d) {
74 - // 无客户端身份标识,不限制  
75 - if(StringUtils.isEmpty(d.getClientUid())){  
76 - return null;  
77 - } 74 + // 无客户端身份标识,不限制
  75 + if (StrUtil.isEmpty(d.getClientUid())) {
  76 + return null;
  77 + }
78 String getKey = getClientCId(d, "GET"); 78 String getKey = getClientCId(d, "GET");
79 String lockKey = getClientCId(d, "LOCK"); 79 String lockKey = getClientCId(d, "LOCK");
80 // 失败次数过多,锁定 80 // 失败次数过多,锁定
@@ -88,7 +88,7 @@ public interface FrequencyLimitHandler { @@ -88,7 +88,7 @@ public interface FrequencyLimitHandler {
88 } 88 }
89 cacheService.increment(getKey, 1); 89 cacheService.increment(getKey, 1);
90 // 1分钟内请求次数过多 90 // 1分钟内请求次数过多
91 - if (Long.valueOf(getCnts) > Long.parseLong(config.getProperty(Const.REQ_GET_MINUTE_LIMIT, "120"))) { 91 + if (Long.parseLong(getCnts) > Long.parseLong(config.getProperty(Const.REQ_GET_MINUTE_LIMIT, "120"))) {
92 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_GET_ERROR); 92 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_GET_ERROR);
93 } 93 }
94 94
@@ -100,9 +100,9 @@ public interface FrequencyLimitHandler { @@ -100,9 +100,9 @@ public interface FrequencyLimitHandler {
100 return null; 100 return null;
101 } 101 }
102 // 1分钟内失败5次 102 // 1分钟内失败5次
103 - if (Long.valueOf(failCnts) > Long.parseLong(config.getProperty(Const.REQ_GET_LOCK_LIMIT, "5"))) { 103 + if (Long.parseLong(failCnts) > Long.parseLong(config.getProperty(Const.REQ_GET_LOCK_LIMIT, "5"))) {
104 // get接口锁定5分钟 104 // get接口锁定5分钟
105 - cacheService.set(lockKey, "1", Long.valueOf(config.getProperty(Const.REQ_GET_LOCK_SECONDS, "300"))); 105 + cacheService.set(lockKey, "1", Long.parseLong(config.getProperty(Const.REQ_GET_LOCK_SECONDS, "300")));
106 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LOCK_GET_ERROR); 106 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LOCK_GET_ERROR);
107 } 107 }
108 return null; 108 return null;
@@ -110,10 +110,10 @@ public interface FrequencyLimitHandler { @@ -110,10 +110,10 @@ public interface FrequencyLimitHandler {
110 110
111 @Override 111 @Override
112 public ResponseModel validateCheck(CaptchaVO d) { 112 public ResponseModel validateCheck(CaptchaVO d) {
113 - // 无客户端身份标识,不限制  
114 - if(StringUtils.isEmpty(d.getClientUid())){  
115 - return null;  
116 - } 113 + // 无客户端身份标识,不限制
  114 + if (StrUtil.isEmpty(d.getClientUid())) {
  115 + return null;
  116 + }
117 /*String getKey = getClientCId(d, "GET"); 117 /*String getKey = getClientCId(d, "GET");
118 if(Objects.isNull(cacheService.get(getKey))){ 118 if(Objects.isNull(cacheService.get(getKey))){
119 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_INVALID); 119 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_INVALID);
@@ -125,7 +125,7 @@ public interface FrequencyLimitHandler { @@ -125,7 +125,7 @@ public interface FrequencyLimitHandler {
125 v = "1"; 125 v = "1";
126 } 126 }
127 cacheService.increment(key, 1); 127 cacheService.increment(key, 1);
128 - if (Long.valueOf(v) > Long.valueOf(config.getProperty(Const.REQ_CHECK_MINUTE_LIMIT, "600"))) { 128 + if (Long.parseLong(v) > Long.parseLong(config.getProperty(Const.REQ_CHECK_MINUTE_LIMIT, "600"))) {
129 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_CHECK_ERROR); 129 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_CHECK_ERROR);
130 } 130 }
131 return null; 131 return null;
@@ -144,7 +144,7 @@ public interface FrequencyLimitHandler { @@ -144,7 +144,7 @@ public interface FrequencyLimitHandler {
144 v = "1"; 144 v = "1";
145 } 145 }
146 cacheService.increment(key, 1); 146 cacheService.increment(key, 1);
147 - if (Long.valueOf(v) > Long.valueOf(config.getProperty(Const.REQ_VALIDATE_MINUTE_LIMIT, "600"))) { 147 + if (Long.parseLong(v) > Long.parseLong(config.getProperty(Const.REQ_VALIDATE_MINUTE_LIMIT, "600"))) {
148 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_VERIFY_ERROR); 148 return ResponseModel.errorMsg(RepCodeEnum.API_REQ_LIMIT_VERIFY_ERROR);
149 } 149 }
150 return null; 150 return null;
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/AESUtil.java
@@ -7,10 +7,13 @@ @@ -7,10 +7,13 @@
7 package com.anji.captcha.util; 7 package com.anji.captcha.util;
8 8
9 9
  10 +import cn.hutool.core.util.StrUtil;
  11 +
10 import javax.crypto.Cipher; 12 import javax.crypto.Cipher;
11 import javax.crypto.KeyGenerator; 13 import javax.crypto.KeyGenerator;
12 import javax.crypto.spec.SecretKeySpec; 14 import javax.crypto.spec.SecretKeySpec;
13 import java.math.BigInteger; 15 import java.math.BigInteger;
  16 +import java.nio.charset.StandardCharsets;
14 import java.util.Base64; 17 import java.util.Base64;
15 18
16 19
@@ -20,6 +23,7 @@ public class AESUtil { @@ -20,6 +23,7 @@ public class AESUtil {
20 23
21 /** 24 /**
22 * 获取随机key 25 * 获取随机key
  26 + *
23 * @return 27 * @return
24 */ 28 */
25 public static String getKey() { 29 public static String getKey() {
@@ -29,39 +33,43 @@ public class AESUtil { @@ -29,39 +33,43 @@ public class AESUtil {
29 33
30 /** 34 /**
31 * 将byte[]转为各种进制的字符串 35 * 将byte[]转为各种进制的字符串
  36 + *
32 * @param bytes byte[] 37 * @param bytes byte[]
33 * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制 38 * @param radix 可以转换进制的范围,从Character.MIN_RADIX到Character.MAX_RADIX,超出范围后变为10进制
34 * @return 转换后的字符串 39 * @return 转换后的字符串
35 */ 40 */
36 - public static String binary(byte[] bytes, int radix){ 41 + public static String binary(byte[] bytes, int radix) {
37 return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数 42 return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数
38 } 43 }
39 44
40 /** 45 /**
41 * base 64 encode 46 * base 64 encode
  47 + *
42 * @param bytes 待编码的byte[] 48 * @param bytes 待编码的byte[]
43 * @return 编码后的base 64 code 49 * @return 编码后的base 64 code
44 */ 50 */
45 - public static String base64Encode(byte[] bytes){ 51 + public static String base64Encode(byte[] bytes) {
46 //return Base64.encodeBase64String(bytes); 52 //return Base64.encodeBase64String(bytes);
47 return Base64.getEncoder().encodeToString(bytes); 53 return Base64.getEncoder().encodeToString(bytes);
48 } 54 }
49 55
50 /** 56 /**
51 * base 64 decode 57 * base 64 decode
  58 + *
52 * @param base64Code 待解码的base 64 code 59 * @param base64Code 待解码的base 64 code
53 * @return 解码后的byte[] 60 * @return 解码后的byte[]
54 * @throws Exception 61 * @throws Exception
55 */ 62 */
56 - public static byte[] base64Decode(String base64Code) throws Exception{ 63 + public static byte[] base64Decode(String base64Code) throws Exception {
57 Base64.Decoder decoder = Base64.getDecoder(); 64 Base64.Decoder decoder = Base64.getDecoder();
58 - return StringUtils.isEmpty(base64Code) ? null : decoder.decode(base64Code); 65 + return StrUtil.isEmpty(base64Code) ? null : decoder.decode(base64Code);
59 } 66 }
60 67
61 68
62 /** 69 /**
63 * AES加密 70 * AES加密
64 - * @param content 待加密的内容 71 + *
  72 + * @param content 待加密的内容
65 * @param encryptKey 加密密钥 73 * @param encryptKey 加密密钥
66 * @return 加密后的byte[] 74 * @return 加密后的byte[]
67 * @throws Exception 75 * @throws Exception
@@ -72,19 +80,20 @@ public class AESUtil { @@ -72,19 +80,20 @@ public class AESUtil {
72 Cipher cipher = Cipher.getInstance(ALGORITHMSTR); 80 Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
73 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES")); 81 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));
74 82
75 - return cipher.doFinal(content.getBytes("utf-8")); 83 + return cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
76 } 84 }
77 85
78 86
79 /** 87 /**
80 * AES加密为base 64 code 88 * AES加密为base 64 code
81 - * @param content 待加密的内容 89 + *
  90 + * @param content 待加密的内容
82 * @param encryptKey 加密密钥 91 * @param encryptKey 加密密钥
83 * @return 加密后的base 64 code 92 * @return 加密后的base 64 code
84 * @throws Exception 93 * @throws Exception
85 */ 94 */
86 public static String aesEncrypt(String content, String encryptKey) throws Exception { 95 public static String aesEncrypt(String content, String encryptKey) throws Exception {
87 - if (StringUtils.isBlank(encryptKey)) { 96 + if (StrUtil.isBlank(encryptKey)) {
88 return content; 97 return content;
89 } 98 }
90 return base64Encode(aesEncryptToBytes(content, encryptKey)); 99 return base64Encode(aesEncryptToBytes(content, encryptKey));
@@ -92,8 +101,9 @@ public class AESUtil { @@ -92,8 +101,9 @@ public class AESUtil {
92 101
93 /** 102 /**
94 * AES解密 103 * AES解密
  104 + *
95 * @param encryptBytes 待解密的byte[] 105 * @param encryptBytes 待解密的byte[]
96 - * @param decryptKey 解密密钥 106 + * @param decryptKey 解密密钥
97 * @return 解密后的String 107 * @return 解密后的String
98 * @throws Exception 108 * @throws Exception
99 */ 109 */
@@ -110,16 +120,17 @@ public class AESUtil { @@ -110,16 +120,17 @@ public class AESUtil {
110 120
111 /** 121 /**
112 * 将base 64 code AES解密 122 * 将base 64 code AES解密
  123 + *
113 * @param encryptStr 待解密的base 64 code 124 * @param encryptStr 待解密的base 64 code
114 * @param decryptKey 解密密钥 125 * @param decryptKey 解密密钥
115 * @return 解密后的string 126 * @return 解密后的string
116 * @throws Exception 127 * @throws Exception
117 */ 128 */
118 public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception { 129 public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {
119 - if (StringUtils.isBlank(decryptKey)) { 130 + if (StrUtil.isBlank(decryptKey)) {
120 return encryptStr; 131 return encryptStr;
121 } 132 }
122 - return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey); 133 + return StrUtil.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);
123 } 134 }
124 135
125 /** 136 /**
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/Base64Utils.java deleted
1 -//  
2 -// Source code recreated from a .class file by IntelliJ IDEA  
3 -// (powered by Fernflower decompiler)  
4 -//  
5 -  
6 -package com.anji.captcha.util;  
7 -  
8 -import java.nio.charset.Charset;  
9 -import java.nio.charset.StandardCharsets;  
10 -import java.util.Base64;  
11 -  
12 -public abstract class Base64Utils {  
13 - private static final Charset DEFAULT_CHARSET;  
14 -  
15 - public Base64Utils() {  
16 - }  
17 -  
18 - public static byte[] encode(byte[] src) {  
19 - return src.length == 0 ? src : Base64.getEncoder().encode(src);  
20 - }  
21 -  
22 - public static byte[] decode(byte[] src) {  
23 - return src.length == 0 ? src : Base64.getDecoder().decode(src);  
24 - }  
25 -  
26 - public static byte[] encodeUrlSafe(byte[] src) {  
27 - return src.length == 0 ? src : Base64.getUrlEncoder().encode(src);  
28 - }  
29 -  
30 - public static byte[] decodeUrlSafe(byte[] src) {  
31 - return src.length == 0 ? src : Base64.getUrlDecoder().decode(src);  
32 - }  
33 -  
34 - public static String encodeToString(byte[] src) {  
35 - return src.length == 0 ? "" : new String(encode(src), DEFAULT_CHARSET);  
36 - }  
37 -  
38 - public static byte[] decodeFromString(String src) {  
39 - return src.isEmpty() ? new byte[0] : decode(src.getBytes(DEFAULT_CHARSET));  
40 - }  
41 -  
42 - public static String encodeToUrlSafeString(byte[] src) {  
43 - return new String(encodeUrlSafe(src), DEFAULT_CHARSET);  
44 - }  
45 -  
46 - public static byte[] decodeFromUrlSafeString(String src) {  
47 - return decodeUrlSafe(src.getBytes(DEFAULT_CHARSET));  
48 - }  
49 -  
50 - static {  
51 - DEFAULT_CHARSET = StandardCharsets.UTF_8;  
52 - }  
53 -}  
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/CacheUtil.java
@@ -24,8 +24,9 @@ public final class CacheUtil { @@ -24,8 +24,9 @@ public final class CacheUtil {
24 24
25 /** 25 /**
26 * 初始化 26 * 初始化
  27 + *
27 * @param cacheMaxNumber 缓存最大个数 28 * @param cacheMaxNumber 缓存最大个数
28 - * @param second 定时任务 秒执行清除过期缓存 29 + * @param second 定时任务 秒执行清除过期缓存
29 */ 30 */
30 public static void init(int cacheMaxNumber, long second) { 31 public static void init(int cacheMaxNumber, long second) {
31 CACHE_MAX_NUMBER = cacheMaxNumber; 32 CACHE_MAX_NUMBER = cacheMaxNumber;
@@ -37,27 +38,25 @@ public final class CacheUtil { @@ -37,27 +38,25 @@ public final class CacheUtil {
37 refresh(); 38 refresh();
38 } 39 }
39 }, 0, second * 1000);*/ 40 }, 0, second * 1000);*/
40 - scheduledExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {  
41 - @Override  
42 - public Thread newThread(Runnable r) {  
43 - return new Thread(r,"thd-captcha-cache-clean");  
44 - }  
45 - },new ThreadPoolExecutor.CallerRunsPolicy()); 41 + ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {
  42 + @Override
  43 + public Thread newThread(Runnable r) {
  44 + return new Thread(r, "thd-captcha-cache-clean");
  45 + }
  46 + }, new ThreadPoolExecutor.CallerRunsPolicy());
46 scheduledExecutor.scheduleAtFixedRate(new Runnable() { 47 scheduledExecutor.scheduleAtFixedRate(new Runnable() {
47 - @Override  
48 - public void run() {  
49 - refresh();  
50 - }  
51 - },10,second,TimeUnit.SECONDS); 48 + @Override
  49 + public void run() {
  50 + refresh();
  51 + }
  52 + }, 10, second, TimeUnit.SECONDS);
52 } 53 }
53 } 54 }
54 55
55 - private static ScheduledExecutorService scheduledExecutor;  
56 -  
57 /** 56 /**
58 * 缓存刷新,清除过期数据 57 * 缓存刷新,清除过期数据
59 */ 58 */
60 - public static void refresh(){ 59 + public static void refresh() {
61 logger.debug("local缓存刷新,清除过期数据"); 60 logger.debug("local缓存刷新,清除过期数据");
62 for (String key : CACHE_MAP.keySet()) { 61 for (String key : CACHE_MAP.keySet()) {
63 exists(key); 62 exists(key);
@@ -65,24 +64,24 @@ public final class CacheUtil { @@ -65,24 +64,24 @@ public final class CacheUtil {
65 } 64 }
66 65
67 66
68 - public static void set(String key, String value, long expiresInSeconds){ 67 + public static void set(String key, String value, long expiresInSeconds) {
69 //设置阈值,达到即clear缓存 68 //设置阈值,达到即clear缓存
70 if (CACHE_MAP.size() > CACHE_MAX_NUMBER * 2) { 69 if (CACHE_MAP.size() > CACHE_MAX_NUMBER * 2) {
71 logger.info("CACHE_MAP达到阈值,clear map"); 70 logger.info("CACHE_MAP达到阈值,clear map");
72 clear(); 71 clear();
73 } 72 }
74 CACHE_MAP.put(key, value); 73 CACHE_MAP.put(key, value);
75 - if(expiresInSeconds >0) {  
76 - CACHE_MAP.put(key + "_HoldTime", System.currentTimeMillis() + expiresInSeconds * 1000);//缓存失效时间  
77 - } 74 + if (expiresInSeconds > 0) {
  75 + CACHE_MAP.put(key + "_HoldTime", System.currentTimeMillis() + expiresInSeconds * 1000);//缓存失效时间
  76 + }
78 } 77 }
79 78
80 - public static void delete(String key){ 79 + public static void delete(String key) {
81 CACHE_MAP.remove(key); 80 CACHE_MAP.remove(key);
82 CACHE_MAP.remove(key + "_HoldTime"); 81 CACHE_MAP.remove(key + "_HoldTime");
83 } 82 }
84 83
85 - public static boolean exists(String key){ 84 + public static boolean exists(String key) {
86 Long cacheHoldTime = (Long) CACHE_MAP.get(key + "_HoldTime"); 85 Long cacheHoldTime = (Long) CACHE_MAP.get(key + "_HoldTime");
87 if (cacheHoldTime == null || cacheHoldTime == 0L) { 86 if (cacheHoldTime == null || cacheHoldTime == 0L) {
88 return false; 87 return false;
@@ -95,9 +94,9 @@ public final class CacheUtil { @@ -95,9 +94,9 @@ public final class CacheUtil {
95 } 94 }
96 95
97 96
98 - public static String get(String key){ 97 + public static String get(String key) {
99 if (exists(key)) { 98 if (exists(key)) {
100 - return (String)CACHE_MAP.get(key); 99 + return (String) CACHE_MAP.get(key);
101 } 100 }
102 return null; 101 return null;
103 } 102 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/FileCopyUtils.java
@@ -18,7 +18,7 @@ public abstract class FileCopyUtils { @@ -18,7 +18,7 @@ public abstract class FileCopyUtils {
18 } 18 }
19 19
20 public static void copy(byte[] in, File out) throws IOException { 20 public static void copy(byte[] in, File out) throws IOException {
21 - copy((InputStream)(new ByteArrayInputStream(in)), (OutputStream)Files.newOutputStream(out.toPath())); 21 + copy((InputStream) (new ByteArrayInputStream(in)), (OutputStream) Files.newOutputStream(out.toPath()));
22 } 22 }
23 23
24 public static byte[] copyToByteArray(File in) throws IOException { 24 public static byte[] copyToByteArray(File in) throws IOException {
@@ -63,7 +63,7 @@ public abstract class FileCopyUtils { @@ -63,7 +63,7 @@ public abstract class FileCopyUtils {
63 return new byte[0]; 63 return new byte[0];
64 } else { 64 } else {
65 ByteArrayOutputStream out = new ByteArrayOutputStream(4096); 65 ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
66 - copy((InputStream)in, (OutputStream)out); 66 + copy((InputStream) in, (OutputStream) out);
67 return out.toByteArray(); 67 return out.toByteArray();
68 } 68 }
69 } 69 }
@@ -74,13 +74,12 @@ public abstract class FileCopyUtils { @@ -74,13 +74,12 @@ public abstract class FileCopyUtils {
74 char[] buffer = new char[4096]; 74 char[] buffer = new char[4096];
75 75
76 int bytesRead; 76 int bytesRead;
77 - for(boolean var4 = true; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) { 77 + for (boolean var4 = true; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) {
78 out.write(buffer, 0, bytesRead); 78 out.write(buffer, 0, bytesRead);
79 } 79 }
80 80
81 out.flush(); 81 out.flush();
82 - int var5 = byteCount;  
83 - return var5; 82 + return byteCount;
84 } finally { 83 } finally {
85 try { 84 try {
86 in.close(); 85 in.close();
@@ -113,7 +112,7 @@ public abstract class FileCopyUtils { @@ -113,7 +112,7 @@ public abstract class FileCopyUtils {
113 return ""; 112 return "";
114 } else { 113 } else {
115 StringWriter out = new StringWriter(); 114 StringWriter out = new StringWriter();
116 - copy((Reader)in, (Writer)out); 115 + copy((Reader) in, (Writer) out);
117 return out.toString(); 116 return out.toString();
118 } 117 }
119 } 118 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/ImageUtils.java
@@ -6,9 +6,10 @@ @@ -6,9 +6,10 @@
6 */ 6 */
7 package com.anji.captcha.util; 7 package com.anji.captcha.util;
8 8
  9 +import cn.hutool.core.util.StrUtil;
9 import com.anji.captcha.model.common.CaptchaBaseMapEnum; 10 import com.anji.captcha.model.common.CaptchaBaseMapEnum;
10 -import org.slf4j.Logger;  
11 -import org.slf4j.LoggerFactory; 11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.util.Base64Utils;
12 13
13 import javax.imageio.ImageIO; 14 import javax.imageio.ImageIO;
14 import java.awt.image.BufferedImage; 15 import java.awt.image.BufferedImage;
@@ -19,9 +20,8 @@ import java.util.HashMap; @@ -19,9 +20,8 @@ import java.util.HashMap;
19 import java.util.Map; 20 import java.util.Map;
20 import java.util.concurrent.ConcurrentHashMap; 21 import java.util.concurrent.ConcurrentHashMap;
21 22
22 - 23 +@Slf4j
23 public class ImageUtils { 24 public class ImageUtils {
24 - private static Logger logger = LoggerFactory.getLogger(ImageUtils.class);  
25 private static Map<String, String> originalCacheMap = new ConcurrentHashMap(); //滑块底图 25 private static Map<String, String> originalCacheMap = new ConcurrentHashMap(); //滑块底图
26 private static Map<String, String> slidingBlockCacheMap = new ConcurrentHashMap(); //滑块 26 private static Map<String, String> slidingBlockCacheMap = new ConcurrentHashMap(); //滑块
27 private static Map<String, String> picClickCacheMap = new ConcurrentHashMap(); //点选文字 27 private static Map<String, String> picClickCacheMap = new ConcurrentHashMap(); //点选文字
@@ -29,7 +29,7 @@ public class ImageUtils { @@ -29,7 +29,7 @@ public class ImageUtils {
29 29
30 public static void cacheImage(String captchaOriginalPathJigsaw, String captchaOriginalPathClick) { 30 public static void cacheImage(String captchaOriginalPathJigsaw, String captchaOriginalPathClick) {
31 //滑动拼图 31 //滑动拼图
32 - if (StringUtils.isBlank(captchaOriginalPathJigsaw)) { 32 + if (StrUtil.isBlank(captchaOriginalPathJigsaw)) {
33 originalCacheMap.putAll(getResourcesImagesFile("defaultImages/jigsaw/original")); 33 originalCacheMap.putAll(getResourcesImagesFile("defaultImages/jigsaw/original"));
34 slidingBlockCacheMap.putAll(getResourcesImagesFile("defaultImages/jigsaw/slidingBlock")); 34 slidingBlockCacheMap.putAll(getResourcesImagesFile("defaultImages/jigsaw/slidingBlock"));
35 } else { 35 } else {
@@ -37,7 +37,7 @@ public class ImageUtils { @@ -37,7 +37,7 @@ public class ImageUtils {
37 slidingBlockCacheMap.putAll(getImagesFile(captchaOriginalPathJigsaw + File.separator + "slidingBlock")); 37 slidingBlockCacheMap.putAll(getImagesFile(captchaOriginalPathJigsaw + File.separator + "slidingBlock"));
38 } 38 }
39 //点选文字 39 //点选文字
40 - if (StringUtils.isBlank(captchaOriginalPathClick)) { 40 + if (StrUtil.isBlank(captchaOriginalPathClick)) {
41 picClickCacheMap.putAll(getResourcesImagesFile("defaultImages/pic-click")); 41 picClickCacheMap.putAll(getResourcesImagesFile("defaultImages/pic-click"));
42 } else { 42 } else {
43 picClickCacheMap.putAll(getImagesFile(captchaOriginalPathClick)); 43 picClickCacheMap.putAll(getImagesFile(captchaOriginalPathClick));
@@ -45,7 +45,7 @@ public class ImageUtils { @@ -45,7 +45,7 @@ public class ImageUtils {
45 fileNameMap.put(CaptchaBaseMapEnum.ORIGINAL.getCodeValue(), originalCacheMap.keySet().toArray(new String[0])); 45 fileNameMap.put(CaptchaBaseMapEnum.ORIGINAL.getCodeValue(), originalCacheMap.keySet().toArray(new String[0]));
46 fileNameMap.put(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue(), slidingBlockCacheMap.keySet().toArray(new String[0])); 46 fileNameMap.put(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue(), slidingBlockCacheMap.keySet().toArray(new String[0]));
47 fileNameMap.put(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue(), picClickCacheMap.keySet().toArray(new String[0])); 47 fileNameMap.put(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue(), picClickCacheMap.keySet().toArray(new String[0]));
48 - logger.info("初始化底图:{}", JsonUtil.toJSONString(fileNameMap)); 48 + log.info("初始化底图:{}", JsonUtil.toJSONString(fileNameMap));
49 } 49 }
50 50
51 public static void cacheBootImage(Map<String, String> originalMap, Map<String, String> slidingBlockMap, Map<String, String> picClickMap) { 51 public static void cacheBootImage(Map<String, String> originalMap, Map<String, String> slidingBlockMap, Map<String, String> picClickMap) {
@@ -55,7 +55,7 @@ public class ImageUtils { @@ -55,7 +55,7 @@ public class ImageUtils {
55 fileNameMap.put(CaptchaBaseMapEnum.ORIGINAL.getCodeValue(), originalCacheMap.keySet().toArray(new String[0])); 55 fileNameMap.put(CaptchaBaseMapEnum.ORIGINAL.getCodeValue(), originalCacheMap.keySet().toArray(new String[0]));
56 fileNameMap.put(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue(), slidingBlockCacheMap.keySet().toArray(new String[0])); 56 fileNameMap.put(CaptchaBaseMapEnum.SLIDING_BLOCK.getCodeValue(), slidingBlockCacheMap.keySet().toArray(new String[0]));
57 fileNameMap.put(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue(), picClickCacheMap.keySet().toArray(new String[0])); 57 fileNameMap.put(CaptchaBaseMapEnum.PIC_CLICK.getCodeValue(), picClickCacheMap.keySet().toArray(new String[0]));
58 - logger.info("自定义resource底图:{}", JsonUtil.toJSONString(fileNameMap)); 58 + log.info("自定义resource底图:{}", JsonUtil.toJSONString(fileNameMap));
59 } 59 }
60 60
61 61
@@ -75,8 +75,7 @@ public class ImageUtils { @@ -75,8 +75,7 @@ public class ImageUtils {
75 return null; 75 return null;
76 } 76 }
77 Integer randomInt = RandomUtils.getRandomInt(0, strings.length); 77 Integer randomInt = RandomUtils.getRandomInt(0, strings.length);
78 - String s = slidingBlockCacheMap.get(strings[randomInt]);  
79 - return s; 78 + return slidingBlockCacheMap.get(strings[randomInt]);
80 } 79 }
81 80
82 public static BufferedImage getPicClick() { 81 public static BufferedImage getPicClick() {
@@ -160,8 +159,6 @@ public class ImageUtils { @@ -160,8 +159,6 @@ public class ImageUtils {
160 byte[] bytes = FileCopyUtils.copyToByteArray(fileInputStream); 159 byte[] bytes = FileCopyUtils.copyToByteArray(fileInputStream);
161 String string = Base64Utils.encodeToString(bytes); 160 String string = Base64Utils.encodeToString(bytes);
162 imgMap.put(item.getName(), string); 161 imgMap.put(item.getName(), string);
163 - } catch (FileNotFoundException e) {  
164 - e.printStackTrace();  
165 } catch (IOException e) { 162 } catch (IOException e) {
166 e.printStackTrace(); 163 e.printStackTrace();
167 } 164 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/JsonUtil.java
1 package com.anji.captcha.util; 1 package com.anji.captcha.util;
2 2
3 import com.anji.captcha.model.vo.PointVO; 3 import com.anji.captcha.model.vo.PointVO;
4 -import org.slf4j.Logger;  
5 -import org.slf4j.LoggerFactory; 4 +import lombok.extern.slf4j.Slf4j;
6 5
7 import java.util.ArrayList; 6 import java.util.ArrayList;
8 import java.util.List; 7 import java.util.List;
@@ -12,63 +11,63 @@ import java.util.Map; @@ -12,63 +11,63 @@ import java.util.Map;
12 * 替换掉fastjson,自定义实现相关方法 11 * 替换掉fastjson,自定义实现相关方法
13 * note: 该实现不具有通用性,仅用于本项目。 12 * note: 该实现不具有通用性,仅用于本项目。
14 * 13 *
15 - *@author WongBin  
16 - *@date 2021/1/8 14 + * @author WongBin
  15 + * @date 2021/1/8
17 */ 16 */
  17 +@Slf4j
18 public class JsonUtil { 18 public class JsonUtil {
19 - private static Logger logger = LoggerFactory.getLogger(JsonUtil.class);  
20 - public static List<PointVO> parseArray(String text, Class<PointVO> clazz) {  
21 - if (text == null) {  
22 - return null;  
23 - } else {  
24 - String[] arr = text.replaceFirst("\\[","")  
25 - .replaceFirst("\\]","").split("\\}");  
26 - List<PointVO> ret = new ArrayList<>(arr.length);  
27 - for (String s : arr) {  
28 - ret.add(parseObject(s,PointVO.class));  
29 - }  
30 - return ret;  
31 - }  
32 - } 19 + public static List<PointVO> parseArray(String text, Class<PointVO> clazz) {
  20 + if (text == null) {
  21 + return null;
  22 + } else {
  23 + String[] arr = text.replaceFirst("\\[", "")
  24 + .replaceFirst("\\]", "").split("\\}");
  25 + List<PointVO> ret = new ArrayList<>(arr.length);
  26 + for (String s : arr) {
  27 + ret.add(parseObject(s, PointVO.class));
  28 + }
  29 + return ret;
  30 + }
  31 + }
33 32
34 - public static PointVO parseObject(String text, Class<PointVO> clazz) {  
35 - if(text == null) {  
36 - return null;  
37 - } 33 + public static PointVO parseObject(String text, Class<PointVO> clazz) {
  34 + if (text == null) {
  35 + return null;
  36 + }
38 /*if(!clazz.isAssignableFrom(PointVO.class)) { 37 /*if(!clazz.isAssignableFrom(PointVO.class)) {
39 throw new UnsupportedOperationException("不支持的输入类型:" 38 throw new UnsupportedOperationException("不支持的输入类型:"
40 + clazz.getSimpleName()); 39 + clazz.getSimpleName());
41 }*/ 40 }*/
42 - try {  
43 - PointVO ret = clazz.newInstance();  
44 - return ret.parse(text);  
45 - }catch (Exception ex){  
46 - logger.error("json解析异常", ex); 41 + try {
  42 + PointVO ret = clazz.newInstance();
  43 + return ret.parse(text);
  44 + } catch (Exception ex) {
  45 + log.error("json解析异常", ex);
47 46
48 - }  
49 - return null;  
50 - } 47 + }
  48 + return null;
  49 + }
51 50
52 - public static String toJSONString(Object object) {  
53 - if(object == null) {  
54 - return "{}";  
55 - }  
56 - if(object instanceof PointVO){  
57 - PointVO t = (PointVO)object;  
58 - return t.toJsonString();  
59 - }  
60 - if(object instanceof List){  
61 - List<PointVO> list = (List<PointVO>)object;  
62 - StringBuilder buf = new StringBuilder("[");  
63 - list.stream().forEach(t->{  
64 - buf.append(t.toJsonString()).append(",");  
65 - });  
66 - return buf.deleteCharAt(buf.lastIndexOf(",")).append("]").toString();  
67 - }  
68 - if(object instanceof Map){  
69 - return ((Map)object).entrySet().toString();  
70 - }  
71 - throw new UnsupportedOperationException("不支持的输入类型:"  
72 - +object.getClass().getSimpleName());  
73 - } 51 + public static String toJSONString(Object object) {
  52 + if (object == null) {
  53 + return "{}";
  54 + }
  55 + if (object instanceof PointVO) {
  56 + PointVO t = (PointVO) object;
  57 + return t.toJsonString();
  58 + }
  59 + if (object instanceof List) {
  60 + List<PointVO> list = (List<PointVO>) object;
  61 + StringBuilder buf = new StringBuilder("[");
  62 + list.forEach(t -> {
  63 + buf.append(t.toJsonString()).append(",");
  64 + });
  65 + return buf.deleteCharAt(buf.lastIndexOf(",")).append("]").toString();
  66 + }
  67 + if (object instanceof Map) {
  68 + return ((Map) object).entrySet().toString();
  69 + }
  70 + throw new UnsupportedOperationException("不支持的输入类型:"
  71 + + object.getClass().getSimpleName());
  72 + }
74 } 73 }
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/MD5Util.java
1 package com.anji.captcha.util; 1 package com.anji.captcha.util;
2 2
  3 +import java.nio.charset.StandardCharsets;
3 import java.security.MessageDigest; 4 import java.security.MessageDigest;
4 5
5 /** 6 /**
@@ -8,17 +9,18 @@ import java.security.MessageDigest; @@ -8,17 +9,18 @@ import java.security.MessageDigest;
8 public abstract class MD5Util { 9 public abstract class MD5Util {
9 /** 10 /**
10 * 获取指定字符串的md5值 11 * 获取指定字符串的md5值
  12 + *
11 * @param dataStr 明文 13 * @param dataStr 明文
12 * @return String 14 * @return String
13 */ 15 */
14 public static String md5(String dataStr) { 16 public static String md5(String dataStr) {
15 try { 17 try {
16 MessageDigest m = MessageDigest.getInstance("MD5"); 18 MessageDigest m = MessageDigest.getInstance("MD5");
17 - m.update(dataStr.getBytes("UTF8")); 19 + m.update(dataStr.getBytes(StandardCharsets.UTF_8));
18 byte[] s = m.digest(); 20 byte[] s = m.digest();
19 StringBuilder result = new StringBuilder(); 21 StringBuilder result = new StringBuilder();
20 - for (int i = 0; i < s.length; i++) {  
21 - result.append(Integer.toHexString((0x000000FF & s[i]) | 0xFFFFFF00).substring(6)); 22 + for (byte b : s) {
  23 + result.append(Integer.toHexString((0x000000FF & b) | 0xFFFFFF00).substring(6));
22 } 24 }
23 return result.toString(); 25 return result.toString();
24 } catch (Exception e) { 26 } catch (Exception e) {
@@ -29,10 +31,11 @@ public abstract class MD5Util { @@ -29,10 +31,11 @@ public abstract class MD5Util {
29 31
30 /** 32 /**
31 * 获取指定字符串的md5值, md5(str+salt) 33 * 获取指定字符串的md5值, md5(str+salt)
  34 + *
32 * @param dataStr 明文 35 * @param dataStr 明文
33 * @return String 36 * @return String
34 */ 37 */
35 - public static String md5WithSalt(String dataStr,String salt) { 38 + public static String md5WithSalt(String dataStr, String salt) {
36 return md5(dataStr + salt); 39 return md5(dataStr + salt);
37 } 40 }
38 41
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/RandomUtils.java
@@ -31,11 +31,10 @@ public class RandomUtils { @@ -31,11 +31,10 @@ public class RandomUtils {
31 * @return 31 * @return
32 */ 32 */
33 public static String getRandomHan(String hanZi) { 33 public static String getRandomHan(String hanZi) {
34 - String ch = hanZi.charAt(new Random().nextInt(hanZi.length())) + "";  
35 - return ch; 34 + return hanZi.charAt(new Random().nextInt(hanZi.length())) + "";
36 } 35 }
37 36
38 - public static int getRandomInt(int bound){ 37 + public static int getRandomInt(int bound) {
39 return ThreadLocalRandom.current().nextInt(bound); 38 return ThreadLocalRandom.current().nextInt(bound);
40 } 39 }
41 40
@@ -68,25 +67,27 @@ public class RandomUtils { @@ -68,25 +67,27 @@ public class RandomUtils {
68 67
69 /** 68 /**
70 * 随机范围内数字 69 * 随机范围内数字
  70 + *
71 * @param startNum 71 * @param startNum
72 * @param endNum 72 * @param endNum
73 * @return 73 * @return
74 */ 74 */
75 public static Integer getRandomInt(int startNum, int endNum) { 75 public static Integer getRandomInt(int startNum, int endNum) {
76 - return ThreadLocalRandom.current().nextInt(endNum-startNum) + startNum; 76 + return ThreadLocalRandom.current().nextInt(endNum - startNum) + startNum;
77 } 77 }
78 78
79 /** 79 /**
80 * 获取随机字符串 80 * 获取随机字符串
  81 + *
81 * @param length 82 * @param length
82 * @return 83 * @return
83 */ 84 */
84 - public static String getRandomString(int length){  
85 - String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
86 - Random random=new Random();  
87 - StringBuffer sb=new StringBuffer();  
88 - for(int i=0;i<length;i++){  
89 - int number=random.nextInt(62); 85 + public static String getRandomString(int length) {
  86 + String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  87 + Random random = new Random();
  88 + StringBuffer sb = new StringBuffer();
  89 + for (int i = 0; i < length; i++) {
  90 + int number = random.nextInt(62);
90 sb.append(str.charAt(number)); 91 sb.append(str.charAt(number));
91 } 92 }
92 return sb.toString(); 93 return sb.toString();
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/StreamUtils.java
@@ -19,7 +19,7 @@ public abstract class StreamUtils { @@ -19,7 +19,7 @@ public abstract class StreamUtils {
19 return new byte[0]; 19 return new byte[0];
20 } else { 20 } else {
21 ByteArrayOutputStream out = new ByteArrayOutputStream(4096); 21 ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
22 - copy((InputStream)in, out); 22 + copy((InputStream) in, out);
23 return out.toByteArray(); 23 return out.toByteArray();
24 } 24 }
25 } 25 }
@@ -31,10 +31,9 @@ public abstract class StreamUtils { @@ -31,10 +31,9 @@ public abstract class StreamUtils {
31 StringBuilder out = new StringBuilder(); 31 StringBuilder out = new StringBuilder();
32 InputStreamReader reader = new InputStreamReader(in, charset); 32 InputStreamReader reader = new InputStreamReader(in, charset);
33 char[] buffer = new char[4096]; 33 char[] buffer = new char[4096];
34 - boolean var5 = true;  
35 34
36 int bytesRead; 35 int bytesRead;
37 - while((bytesRead = reader.read(buffer)) != -1) { 36 + while ((bytesRead = reader.read(buffer)) != -1) {
38 out.append(buffer, 0, bytesRead); 37 out.append(buffer, 0, bytesRead);
39 } 38 }
40 39
@@ -57,7 +56,7 @@ public abstract class StreamUtils { @@ -57,7 +56,7 @@ public abstract class StreamUtils {
57 byte[] buffer = new byte[4096]; 56 byte[] buffer = new byte[4096];
58 57
59 int bytesRead; 58 int bytesRead;
60 - for(boolean var4 = true; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) { 59 + for (boolean var4 = true; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) {
61 out.write(buffer, 0, bytesRead); 60 out.write(buffer, 0, bytesRead);
62 } 61 }
63 62
@@ -73,17 +72,17 @@ public abstract class StreamUtils { @@ -73,17 +72,17 @@ public abstract class StreamUtils {
73 long bytesToCopy = end - start + 1L; 72 long bytesToCopy = end - start + 1L;
74 byte[] buffer = new byte[4096]; 73 byte[] buffer = new byte[4096];
75 74
76 - while(bytesToCopy > 0L) { 75 + while (bytesToCopy > 0L) {
77 int bytesRead = in.read(buffer); 76 int bytesRead = in.read(buffer);
78 if (bytesRead == -1) { 77 if (bytesRead == -1) {
79 break; 78 break;
80 } 79 }
81 80
82 - if ((long)bytesRead <= bytesToCopy) { 81 + if ((long) bytesRead <= bytesToCopy) {
83 out.write(buffer, 0, bytesRead); 82 out.write(buffer, 0, bytesRead);
84 - bytesToCopy -= (long)bytesRead; 83 + bytesToCopy -= (long) bytesRead;
85 } else { 84 } else {
86 - out.write(buffer, 0, (int)bytesToCopy); 85 + out.write(buffer, 0, (int) bytesToCopy);
87 bytesToCopy = 0L; 86 bytesToCopy = 0L;
88 } 87 }
89 } 88 }
@@ -96,7 +95,7 @@ public abstract class StreamUtils { @@ -96,7 +95,7 @@ public abstract class StreamUtils {
96 byte[] buffer = new byte[4096]; 95 byte[] buffer = new byte[4096];
97 int byteCount; 96 int byteCount;
98 int bytesRead; 97 int bytesRead;
99 - for(byteCount = 0; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) { 98 + for (byteCount = 0; (bytesRead = in.read(buffer)) != -1; byteCount += bytesRead) {
100 } 99 }
101 100
102 return byteCount; 101 return byteCount;
yudao-framework/yudao-spring-boot-starter-captcha/src/main/java/com/anji/captcha/util/StringUtils.java deleted
1 -/*  
2 - *Copyright © 2018 anji-plus  
3 - *安吉加加信息技术有限公司  
4 - *http://www.anji-plus.com  
5 - *All rights reserved.  
6 - */  
7 -package com.anji.captcha.util;  
8 -  
9 -public class StringUtils {  
10 -  
11 - /**  
12 - * The empty String <code>""</code>.  
13 - * @since 2.0  
14 - */  
15 - public static final String EMPTY = "";  
16 -  
17 - /**  
18 - * Represents a failed index search.  
19 - * @since 2.1  
20 - */  
21 - public static final int INDEX_NOT_FOUND = -1;  
22 -  
23 - /**  
24 - * <p>The maximum size to which the padding constant(s) can expand.</p>  
25 - */  
26 - private static final int PAD_LIMIT = 8192;  
27 -  
28 - /**  
29 - * <p><code>StringUtils</code> instances should NOT be constructed in  
30 - * standard programming. Instead, the class should be used as  
31 - * <code>StringUtils.trim(" foo ");</code>.</p>  
32 - *  
33 - * <p>This constructor is public to permit tools that require a JavaBean  
34 - * instance to operate.</p>  
35 - */  
36 - public StringUtils() {  
37 - super();  
38 - }  
39 -  
40 - // Empty checks  
41 - //-----------------------------------------------------------------------  
42 - /**  
43 - * <p>Checks if a String is empty ("") or null.</p>  
44 - *  
45 - * <pre>  
46 - * StringUtils.isEmpty(null) = true  
47 - * StringUtils.isEmpty("") = true  
48 - * StringUtils.isEmpty(" ") = false  
49 - * StringUtils.isEmpty("bob") = false  
50 - * StringUtils.isEmpty(" bob ") = false  
51 - * </pre>  
52 - *  
53 - * <p>NOTE: This method changed in Lang version 2.0.  
54 - * It no longer trims the String.  
55 - * That functionality is available in isBlank().</p>  
56 - *  
57 - * @param str the String to check, may be null  
58 - * @return <code>true</code> if the String is empty or null  
59 - */  
60 - public static boolean isEmpty(String str) {  
61 - return str == null || str.length() == 0;  
62 - }  
63 -  
64 - /**  
65 - * <p>Checks if a String is not empty ("") and not null.</p>  
66 - *  
67 - * <pre>  
68 - * StringUtils.isNotEmpty(null) = false  
69 - * StringUtils.isNotEmpty("") = false  
70 - * StringUtils.isNotEmpty(" ") = true  
71 - * StringUtils.isNotEmpty("bob") = true  
72 - * StringUtils.isNotEmpty(" bob ") = true  
73 - * </pre>  
74 - *  
75 - * @param str the String to check, may be null  
76 - * @return <code>true</code> if the String is not empty and not null  
77 - */  
78 - public static boolean isNotEmpty(String str) {  
79 - return !StringUtils.isEmpty(str);  
80 - }  
81 -  
82 - /**  
83 - * <p>Checks if a String is whitespace, empty ("") or null.</p>  
84 - *  
85 - * <pre>  
86 - * StringUtils.isBlank(null) = true  
87 - * StringUtils.isBlank("null") = true  
88 - * StringUtils.isBlank("") = true  
89 - * StringUtils.isBlank(" ") = true  
90 - * StringUtils.isBlank("bob") = false  
91 - * StringUtils.isBlank(" bob ") = false  
92 - * </pre>  
93 - *  
94 - * @param str the String to check, may be null  
95 - * @return <code>true</code> if the String is null, empty or whitespace  
96 - * @since 2.0  
97 - */  
98 - public static boolean isBlank(String str) {  
99 - int strLen;  
100 - if (str == null || (strLen = str.length()) == 0) {  
101 - return true;  
102 - }  
103 - if(equals("null", str.trim().toLowerCase())){  
104 - return true;  
105 - }  
106 - for (int i = 0; i < strLen; i++) {  
107 - if ((Character.isWhitespace(str.charAt(i)) == false)) {  
108 - return false;  
109 - }  
110 - }  
111 - return true;  
112 - }  
113 -  
114 - /**  
115 - * <p>Checks if a String is not empty (""), not null and not whitespace only.</p>  
116 - *  
117 - * <pre>  
118 - * StringUtils.isNotBlank(null) = false  
119 - * StringUtils.isNotBlank("null") = false  
120 - * StringUtils.isNotBlank("") = false  
121 - * StringUtils.isNotBlank(" ") = false  
122 - * StringUtils.isNotBlank("bob") = true  
123 - * StringUtils.isNotBlank(" bob ") = true  
124 - * </pre>  
125 - *  
126 - * @param str the String to check, may be null  
127 - * @return <code>true</code> if the String is  
128 - * not empty and not null and not whitespace  
129 - * @since 2.0  
130 - */  
131 - public static boolean isNotBlank(String str) {  
132 - return !StringUtils.isBlank(str);  
133 - }  
134 -  
135 - // Trim  
136 - //-----------------------------------------------------------------------  
137 - /**  
138 - * <p>Removes control characters (char &lt;= 32) from both  
139 - * ends of this String, handling <code>null</code> by returning  
140 - * an empty String ("").</p>  
141 - *  
142 - * <pre>  
143 - * StringUtils.clean(null) = ""  
144 - * StringUtils.clean("") = ""  
145 - * StringUtils.clean("abc") = "abc"  
146 - * StringUtils.clean(" abc ") = "abc"  
147 - * StringUtils.clean(" ") = ""  
148 - * </pre>  
149 - *  
150 - * @see String#trim()  
151 - * @param str the String to clean, may be null  
152 - * @return the trimmed text, never <code>null</code>  
153 - * @deprecated Use the clearer named {@link #trimToEmpty(String)}.  
154 - * Method will be removed in Commons Lang 3.0.  
155 - */  
156 - public static String clean(String str) {  
157 - return str == null ? EMPTY : str.trim();  
158 - }  
159 -  
160 - /**  
161 - * <p>Removes control characters (char &lt;= 32) from both  
162 - * ends of this String, handling <code>null</code> by returning  
163 - * <code>null</code>.</p>  
164 - *  
165 - * <p>The String is trimmed using {@link String#trim()}.  
166 - * Trim removes start and end characters &lt;= 32.  
167 - * To strip whitespace use {@link #strip(String)}.</p>  
168 - *  
169 - * <p>To trim your choice of characters, use the  
170 - * {@link #strip(String, String)} methods.</p>  
171 - *  
172 - * <pre>  
173 - * StringUtils.trim(null) = null  
174 - * StringUtils.trim("") = ""  
175 - * StringUtils.trim(" ") = ""  
176 - * StringUtils.trim("abc") = "abc"  
177 - * StringUtils.trim(" abc ") = "abc"  
178 - * </pre>  
179 - *  
180 - * @param str the String to be trimmed, may be null  
181 - * @return the trimmed string, <code>null</code> if null String input  
182 - */  
183 - public static String trim(String str) {  
184 - return str == null ? null : str.trim();  
185 - }  
186 -  
187 - /**  
188 - * <p>Removes control characters (char &lt;= 32) from both  
189 - * ends of this String returning <code>null</code> if the String is  
190 - * empty ("") after the trim or if it is <code>null</code>.  
191 - *  
192 - * <p>The String is trimmed using {@link String#trim()}.  
193 - * Trim removes start and end characters &lt;= 32.  
194 - * To strip whitespace use {@link #stripToNull(String)}.</p>  
195 - *  
196 - * <pre>  
197 - * StringUtils.trimToNull(null) = null  
198 - * StringUtils.trimToNull("") = null  
199 - * StringUtils.trimToNull(" ") = null  
200 - * StringUtils.trimToNull("abc") = "abc"  
201 - * StringUtils.trimToNull(" abc ") = "abc"  
202 - * </pre>  
203 - *  
204 - * @param str the String to be trimmed, may be null  
205 - * @return the trimmed String,  
206 - * <code>null</code> if only chars &lt;= 32, empty or null String input  
207 - * @since 2.0  
208 - */  
209 - public static String trimToNull(String str) {  
210 - String ts = trim(str);  
211 - return isEmpty(ts) ? null : ts;  
212 - }  
213 -  
214 - /**  
215 - * <p>Removes control characters (char &lt;= 32) from both  
216 - * ends of this String returning an empty String ("") if the String  
217 - * is empty ("") after the trim or if it is <code>null</code>.  
218 - *  
219 - * <p>The String is trimmed using {@link String#trim()}.  
220 - * Trim removes start and end characters &lt;= 32.  
221 - * To strip whitespace use {@link #stripToEmpty(String)}.</p>  
222 - *  
223 - * <pre>  
224 - * StringUtils.trimToEmpty(null) = ""  
225 - * StringUtils.trimToEmpty("") = ""  
226 - * StringUtils.trimToEmpty(" ") = ""  
227 - * StringUtils.trimToEmpty("abc") = "abc"  
228 - * StringUtils.trimToEmpty(" abc ") = "abc"  
229 - * </pre>  
230 - *  
231 - * @param str the String to be trimmed, may be null  
232 - * @return the trimmed String, or an empty String if <code>null</code> input  
233 - * @since 2.0  
234 - */  
235 - public static String trimToEmpty(String str) {  
236 - return str == null ? EMPTY : str.trim();  
237 - }  
238 -  
239 - // Stripping  
240 - //-----------------------------------------------------------------------  
241 - /**  
242 - * <p>Strips whitespace from the start and end of a String.</p>  
243 - *  
244 - * <p>This is similar to {@link #trim(String)} but removes whitespace.  
245 - * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>  
246 - *  
247 - * <p>A <code>null</code> input String returns <code>null</code>.</p>  
248 - *  
249 - * <pre>  
250 - * StringUtils.strip(null) = null  
251 - * StringUtils.strip("") = ""  
252 - * StringUtils.strip(" ") = ""  
253 - * StringUtils.strip("abc") = "abc"  
254 - * StringUtils.strip(" abc") = "abc"  
255 - * StringUtils.strip("abc ") = "abc"  
256 - * StringUtils.strip(" abc ") = "abc"  
257 - * StringUtils.strip(" ab c ") = "ab c"  
258 - * </pre>  
259 - *  
260 - * @param str the String to remove whitespace from, may be null  
261 - * @return the stripped String, <code>null</code> if null String input  
262 - */  
263 - public static String strip(String str) {  
264 - return strip(str, null);  
265 - }  
266 -  
267 - /**  
268 - * <p>Strips whitespace from the start and end of a String returning  
269 - * <code>null</code> if the String is empty ("") after the strip.</p>  
270 - *  
271 - * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.  
272 - * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>  
273 - *  
274 - * <pre>  
275 - * StringUtils.stripToNull(null) = null  
276 - * StringUtils.stripToNull("") = null  
277 - * StringUtils.stripToNull(" ") = null  
278 - * StringUtils.stripToNull("abc") = "abc"  
279 - * StringUtils.stripToNull(" abc") = "abc"  
280 - * StringUtils.stripToNull("abc ") = "abc"  
281 - * StringUtils.stripToNull(" abc ") = "abc"  
282 - * StringUtils.stripToNull(" ab c ") = "ab c"  
283 - * </pre>  
284 - *  
285 - * @param str the String to be stripped, may be null  
286 - * @return the stripped String,  
287 - * <code>null</code> if whitespace, empty or null String input  
288 - * @since 2.0  
289 - */  
290 - public static String stripToNull(String str) {  
291 - if (str == null) {  
292 - return null;  
293 - }  
294 - str = strip(str, null);  
295 - return str.length() == 0 ? null : str;  
296 - }  
297 -  
298 - /**  
299 - * <p>Strips whitespace from the start and end of a String returning  
300 - * an empty String if <code>null</code> input.</p>  
301 - *  
302 - * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.  
303 - * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>  
304 - *  
305 - * <pre>  
306 - * StringUtils.stripToEmpty(null) = ""  
307 - * StringUtils.stripToEmpty("") = ""  
308 - * StringUtils.stripToEmpty(" ") = ""  
309 - * StringUtils.stripToEmpty("abc") = "abc"  
310 - * StringUtils.stripToEmpty(" abc") = "abc"  
311 - * StringUtils.stripToEmpty("abc ") = "abc"  
312 - * StringUtils.stripToEmpty(" abc ") = "abc"  
313 - * StringUtils.stripToEmpty(" ab c ") = "ab c"  
314 - * </pre>  
315 - *  
316 - * @param str the String to be stripped, may be null  
317 - * @return the trimmed String, or an empty String if <code>null</code> input  
318 - * @since 2.0  
319 - */  
320 - public static String stripToEmpty(String str) {  
321 - return str == null ? EMPTY : strip(str, null);  
322 - }  
323 -  
324 - /**  
325 - * <p>Strips any of a set of characters from the start and end of a String.  
326 - * This is similar to {@link String#trim()} but allows the characters  
327 - * to be stripped to be controlled.</p>  
328 - *  
329 - * <p>A <code>null</code> input String returns <code>null</code>.  
330 - * An empty string ("") input returns the empty string.</p>  
331 - *  
332 - * <p>If the stripChars String is <code>null</code>, whitespace is  
333 - * stripped as defined by {@link Character#isWhitespace(char)}.  
334 - * Alternatively use {@link #strip(String)}.</p>  
335 - *  
336 - * <pre>  
337 - * StringUtils.strip(null, *) = null  
338 - * StringUtils.strip("", *) = ""  
339 - * StringUtils.strip("abc", null) = "abc"  
340 - * StringUtils.strip(" abc", null) = "abc"  
341 - * StringUtils.strip("abc ", null) = "abc"  
342 - * StringUtils.strip(" abc ", null) = "abc"  
343 - * StringUtils.strip(" abcyx", "xyz") = " abc"  
344 - * </pre>  
345 - *  
346 - * @param str the String to remove characters from, may be null  
347 - * @param stripChars the characters to remove, null treated as whitespace  
348 - * @return the stripped String, <code>null</code> if null String input  
349 - */  
350 - public static String strip(String str, String stripChars) {  
351 - if (isEmpty(str)) {  
352 - return str;  
353 - }  
354 - str = stripStart(str, stripChars);  
355 - return stripEnd(str, stripChars);  
356 - }  
357 -  
358 - /**  
359 - * <p>Strips any of a set of characters from the start of a String.</p>  
360 - *  
361 - * <p>A <code>null</code> input String returns <code>null</code>.  
362 - * An empty string ("") input returns the empty string.</p>  
363 - *  
364 - * <p>If the stripChars String is <code>null</code>, whitespace is  
365 - * stripped as defined by {@link Character#isWhitespace(char)}.</p>  
366 - *  
367 - * <pre>  
368 - * StringUtils.stripStart(null, *) = null  
369 - * StringUtils.stripStart("", *) = ""  
370 - * StringUtils.stripStart("abc", "") = "abc"  
371 - * StringUtils.stripStart("abc", null) = "abc"  
372 - * StringUtils.stripStart(" abc", null) = "abc"  
373 - * StringUtils.stripStart("abc ", null) = "abc "  
374 - * StringUtils.stripStart(" abc ", null) = "abc "  
375 - * StringUtils.stripStart("yxabc ", "xyz") = "abc "  
376 - * </pre>  
377 - *  
378 - * @param str the String to remove characters from, may be null  
379 - * @param stripChars the characters to remove, null treated as whitespace  
380 - * @return the stripped String, <code>null</code> if null String input  
381 - */  
382 - public static String stripStart(String str, String stripChars) {  
383 - int strLen;  
384 - if (str == null || (strLen = str.length()) == 0) {  
385 - return str;  
386 - }  
387 - int start = 0;  
388 - if (stripChars == null) {  
389 - while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {  
390 - start++;  
391 - }  
392 - } else if (stripChars.length() == 0) {  
393 - return str;  
394 - } else {  
395 - while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND)) {  
396 - start++;  
397 - }  
398 - }  
399 - return str.substring(start);  
400 - }  
401 -  
402 - /**  
403 - * <p>Strips any of a set of characters from the end of a String.</p>  
404 - *  
405 - * <p>A <code>null</code> input String returns <code>null</code>.  
406 - * An empty string ("") input returns the empty string.</p>  
407 - *  
408 - * <p>If the stripChars String is <code>null</code>, whitespace is  
409 - * stripped as defined by {@link Character#isWhitespace(char)}.</p>  
410 - *  
411 - * <pre>  
412 - * StringUtils.stripEnd(null, *) = null  
413 - * StringUtils.stripEnd("", *) = ""  
414 - * StringUtils.stripEnd("abc", "") = "abc"  
415 - * StringUtils.stripEnd("abc", null) = "abc"  
416 - * StringUtils.stripEnd(" abc", null) = " abc"  
417 - * StringUtils.stripEnd("abc ", null) = "abc"  
418 - * StringUtils.stripEnd(" abc ", null) = " abc"  
419 - * StringUtils.stripEnd(" abcyx", "xyz") = " abc"  
420 - * StringUtils.stripEnd("120.00", ".0") = "12"  
421 - * </pre>  
422 - *  
423 - * @param str the String to remove characters from, may be null  
424 - * @param stripChars the set of characters to remove, null treated as whitespace  
425 - * @return the stripped String, <code>null</code> if null String input  
426 - */  
427 - public static String stripEnd(String str, String stripChars) {  
428 - int end;  
429 - if (str == null || (end = str.length()) == 0) {  
430 - return str;  
431 - }  
432 -  
433 - if (stripChars == null) {  
434 - while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {  
435 - end--;  
436 - }  
437 - } else if (stripChars.length() == 0) {  
438 - return str;  
439 - } else {  
440 - while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND)) {  
441 - end--;  
442 - }  
443 - }  
444 - return str.substring(0, end);  
445 - }  
446 -  
447 - // StripAll  
448 - //-----------------------------------------------------------------------  
449 - /**  
450 - * <p>Strips whitespace from the start and end of every String in an array.  
451 - * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>  
452 - *  
453 - * <p>A new array is returned each time, except for length zero.  
454 - * A <code>null</code> array will return <code>null</code>.  
455 - * An empty array will return itself.  
456 - * A <code>null</code> array entry will be ignored.</p>  
457 - *  
458 - * <pre>  
459 - * StringUtils.stripAll(null) = null  
460 - * StringUtils.stripAll([]) = []  
461 - * StringUtils.stripAll(["abc", " abc"]) = ["abc", "abc"]  
462 - * StringUtils.stripAll(["abc ", null]) = ["abc", null]  
463 - * </pre>  
464 - *  
465 - * @param strs the array to remove whitespace from, may be null  
466 - * @return the stripped Strings, <code>null</code> if null array input  
467 - */  
468 - public static String[] stripAll(String[] strs) {  
469 - return stripAll(strs, null);  
470 - }  
471 -  
472 - /**  
473 - * <p>Strips any of a set of characters from the start and end of every  
474 - * String in an array.</p>  
475 - * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>  
476 - *  
477 - * <p>A new array is returned each time, except for length zero.  
478 - * A <code>null</code> array will return <code>null</code>.  
479 - * An empty array will return itself.  
480 - * A <code>null</code> array entry will be ignored.  
481 - * A <code>null</code> stripChars will strip whitespace as defined by  
482 - * {@link Character#isWhitespace(char)}.</p>  
483 - *  
484 - * <pre>  
485 - * StringUtils.stripAll(null, *) = null  
486 - * StringUtils.stripAll([], *) = []  
487 - * StringUtils.stripAll(["abc", " abc"], null) = ["abc", "abc"]  
488 - * StringUtils.stripAll(["abc ", null], null) = ["abc", null]  
489 - * StringUtils.stripAll(["abc ", null], "yz") = ["abc ", null]  
490 - * StringUtils.stripAll(["yabcz", null], "yz") = ["abc", null]  
491 - * </pre>  
492 - *  
493 - * @param strs the array to remove characters from, may be null  
494 - * @param stripChars the characters to remove, null treated as whitespace  
495 - * @return the stripped Strings, <code>null</code> if null array input  
496 - */  
497 - public static String[] stripAll(String[] strs, String stripChars) {  
498 - int strsLen;  
499 - if (strs == null || (strsLen = strs.length) == 0) {  
500 - return strs;  
501 - }  
502 - String[] newArr = new String[strsLen];  
503 - for (int i = 0; i < strsLen; i++) {  
504 - newArr[i] = strip(strs[i], stripChars);  
505 - }  
506 - return newArr;  
507 - }  
508 -  
509 - // Equals  
510 - //-----------------------------------------------------------------------  
511 - /**  
512 - * <p>Compares two Strings, returning <code>true</code> if they are equal.</p>  
513 - *  
514 - * <p><code>null</code>s are handled without exceptions. Two <code>null</code>  
515 - * references are considered to be equal. The comparison is case sensitive.</p>  
516 - *  
517 - * <pre>  
518 - * StringUtils.equals(null, null) = true  
519 - * StringUtils.equals(null, "abc") = false  
520 - * StringUtils.equals("abc", null) = false  
521 - * StringUtils.equals("abc", "abc") = true  
522 - * StringUtils.equals("abc", "ABC") = false  
523 - * </pre>  
524 - *  
525 - * @see String#equals(Object)  
526 - * @param str1 the first String, may be null  
527 - * @param str2 the second String, may be null  
528 - * @return <code>true</code> if the Strings are equal, case sensitive, or  
529 - * both <code>null</code>  
530 - */  
531 - public static boolean equals(String str1, String str2) {  
532 - return str1 == null ? str2 == null : str1.equals(str2);  
533 - }  
534 -  
535 - /**  
536 - * <p>Compares two Strings, returning <code>true</code> if they are equal ignoring  
537 - * the case.</p>  
538 - *  
539 - * <p><code>null</code>s are handled without exceptions. Two <code>null</code>  
540 - * references are considered equal. Comparison is case insensitive.</p>  
541 - *  
542 - * <pre>  
543 - * StringUtils.equalsIgnoreCase(null, null) = true  
544 - * StringUtils.equalsIgnoreCase(null, "abc") = false  
545 - * StringUtils.equalsIgnoreCase("abc", null) = false  
546 - * StringUtils.equalsIgnoreCase("abc", "abc") = true  
547 - * StringUtils.equalsIgnoreCase("abc", "ABC") = true  
548 - * </pre>  
549 - *  
550 - * @see String#equalsIgnoreCase(String)  
551 - * @param str1 the first String, may be null  
552 - * @param str2 the second String, may be null  
553 - * @return <code>true</code> if the Strings are equal, case insensitive, or  
554 - * both <code>null</code>  
555 - */  
556 - public static boolean equalsIgnoreCase(String str1, String str2) {  
557 - return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);  
558 - }  
559 -  
560 - // IndexOf  
561 - //-----------------------------------------------------------------------  
562 - /**  
563 - * <p>Finds the first index within a String, handling <code>null</code>.  
564 - * This method uses {@link String#indexOf(int)}.</p>  
565 - *  
566 - * <p>A <code>null</code> or empty ("") String will return <code>INDEX_NOT_FOUND (-1)</code>.</p>  
567 - *  
568 - * <pre>  
569 - * StringUtils.indexOf(null, *) = -1  
570 - * StringUtils.indexOf("", *) = -1  
571 - * StringUtils.indexOf("aabaabaa", 'a') = 0  
572 - * StringUtils.indexOf("aabaabaa", 'b') = 2  
573 - * </pre>  
574 - *  
575 - * @param str the String to check, may be null  
576 - * @param searchChar the character to find  
577 - * @return the first index of the search character,  
578 - * -1 if no match or <code>null</code> string input  
579 - * @since 2.0  
580 - */  
581 - public static int indexOf(String str, char searchChar) {  
582 - if (isEmpty(str)) {  
583 - return INDEX_NOT_FOUND;  
584 - }  
585 - return str.indexOf(searchChar);  
586 - }  
587 -  
588 - /**  
589 - * <p>Finds the first index within a String from a start position,  
590 - * handling <code>null</code>.  
591 - * This method uses {@link String#indexOf(int, int)}.</p>  
592 - *  
593 - * <p>A <code>null</code> or empty ("") String will return <code>(INDEX_NOT_FOUND) -1</code>.  
594 - * A negative start position is treated as zero.  
595 - * A start position greater than the string length returns <code>-1</code>.</p>  
596 - *  
597 - * <pre>  
598 - * StringUtils.indexOf(null, *, *) = -1  
599 - * StringUtils.indexOf("", *, *) = -1  
600 - * StringUtils.indexOf("aabaabaa", 'b', 0) = 2  
601 - * StringUtils.indexOf("aabaabaa", 'b', 3) = 5  
602 - * StringUtils.indexOf("aabaabaa", 'b', 9) = -1  
603 - * StringUtils.indexOf("aabaabaa", 'b', -1) = 2  
604 - * </pre>  
605 - *  
606 - * @param str the String to check, may be null  
607 - * @param searchChar the character to find  
608 - * @param startPos the start position, negative treated as zero  
609 - * @return the first index of the search character,  
610 - * -1 if no match or <code>null</code> string input  
611 - * @since 2.0  
612 - */  
613 - public static int indexOf(String str, char searchChar, int startPos) {  
614 - if (isEmpty(str)) {  
615 - return INDEX_NOT_FOUND;  
616 - }  
617 - return str.indexOf(searchChar, startPos);  
618 - }  
619 -  
620 - /**  
621 - * <p>Finds the first index within a String, handling <code>null</code>.  
622 - * This method uses {@link String#indexOf(String)}.</p>  
623 - *  
624 - * <p>A <code>null</code> String will return <code>-1</code>.</p>  
625 - *  
626 - * <pre>  
627 - * StringUtils.indexOf(null, *) = -1  
628 - * StringUtils.indexOf(*, null) = -1  
629 - * StringUtils.indexOf("", "") = 0  
630 - * StringUtils.indexOf("", *) = -1 (except when * = "")  
631 - * StringUtils.indexOf("aabaabaa", "a") = 0  
632 - * StringUtils.indexOf("aabaabaa", "b") = 2  
633 - * StringUtils.indexOf("aabaabaa", "ab") = 1  
634 - * StringUtils.indexOf("aabaabaa", "") = 0  
635 - * </pre>  
636 - *  
637 - * @param str the String to check, may be null  
638 - * @param searchStr the String to find, may be null  
639 - * @return the first index of the search String,  
640 - * -1 if no match or <code>null</code> string input  
641 - * @since 2.0  
642 - */  
643 - public static int indexOf(String str, String searchStr) {  
644 - if (str == null || searchStr == null) {  
645 - return INDEX_NOT_FOUND;  
646 - }  
647 - return str.indexOf(searchStr);  
648 - }  
649 -  
650 - /**  
651 - * <p>Finds the n-th index within a String, handling <code>null</code>.  
652 - * This method uses {@link String#indexOf(String)}.</p>  
653 - *  
654 - * <p>A <code>null</code> String will return <code>-1</code>.</p>  
655 - *  
656 - * <pre>  
657 - * StringUtils.ordinalIndexOf(null, *, *) = -1  
658 - * StringUtils.ordinalIndexOf(*, null, *) = -1  
659 - * StringUtils.ordinalIndexOf("", "", *) = 0  
660 - * StringUtils.ordinalIndexOf("aabaabaa", "a", 1) = 0  
661 - * StringUtils.ordinalIndexOf("aabaabaa", "a", 2) = 1  
662 - * StringUtils.ordinalIndexOf("aabaabaa", "b", 1) = 2  
663 - * StringUtils.ordinalIndexOf("aabaabaa", "b", 2) = 5  
664 - * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1  
665 - * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4  
666 - * StringUtils.ordinalIndexOf("aabaabaa", "", 1) = 0  
667 - * StringUtils.ordinalIndexOf("aabaabaa", "", 2) = 0  
668 - * </pre>  
669 - *  
670 - * <p>Note that 'head(String str, int n)' may be implemented as: </p>  
671 - *  
672 - * <pre>  
673 - * str.substring(0, lastOrdinalIndexOf(str, "\n", n))  
674 - * </pre>  
675 - *  
676 - * @param str the String to check, may be null  
677 - * @param searchStr the String to find, may be null  
678 - * @param ordinal the n-th <code>searchStr</code> to find  
679 - * @return the n-th index of the search String,  
680 - * <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input  
681 - * @since 2.1  
682 - */  
683 - public static int ordinalIndexOf(String str, String searchStr, int ordinal) {  
684 - return ordinalIndexOf(str, searchStr, ordinal, false);  
685 - }  
686 -  
687 - /**  
688 - * <p>Finds the n-th index within a String, handling <code>null</code>.  
689 - * This method uses {@link String#indexOf(String)}.</p>  
690 - *  
691 - * <p>A <code>null</code> String will return <code>-1</code>.</p>  
692 - *  
693 - * @param str the String to check, may be null  
694 - * @param searchStr the String to find, may be null  
695 - * @param ordinal the n-th <code>searchStr</code> to find  
696 - * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()  
697 - * @return the n-th index of the search String,  
698 - * <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input  
699 - */  
700 - // Shared code between ordinalIndexOf(String,String,int) and lastOrdinalIndexOf(String,String,int)  
701 - private static int ordinalIndexOf(String str, String searchStr, int ordinal, boolean lastIndex) {  
702 - if (str == null || searchStr == null || ordinal <= 0) {  
703 - return INDEX_NOT_FOUND;  
704 - }  
705 - if (searchStr.length() == 0) {  
706 - return lastIndex ? str.length() : 0;  
707 - }  
708 - int found = 0;  
709 - int index = lastIndex ? str.length() : INDEX_NOT_FOUND;  
710 - do {  
711 - if(lastIndex) {  
712 - index = str.lastIndexOf(searchStr, index - 1);  
713 - } else {  
714 - index = str.indexOf(searchStr, index + 1);  
715 - }  
716 - if (index < 0) {  
717 - return index;  
718 - }  
719 - found++;  
720 - } while (found < ordinal);  
721 - return index;  
722 - }  
723 -  
724 - /**  
725 - * <p>Finds the first index within a String, handling <code>null</code>.  
726 - * This method uses {@link String#indexOf(String, int)}.</p>  
727 - *  
728 - * <p>A <code>null</code> String will return <code>-1</code>.  
729 - * A negative start position is treated as zero.  
730 - * An empty ("") search String always matches.  
731 - * A start position greater than the string length only matches  
732 - * an empty search String.</p>  
733 - *  
734 - * <pre>  
735 - * StringUtils.indexOf(null, *, *) = -1  
736 - * StringUtils.indexOf(*, null, *) = -1  
737 - * StringUtils.indexOf("", "", 0) = 0  
738 - * StringUtils.indexOf("", *, 0) = -1 (except when * = "")  
739 - * StringUtils.indexOf("aabaabaa", "a", 0) = 0  
740 - * StringUtils.indexOf("aabaabaa", "b", 0) = 2  
741 - * StringUtils.indexOf("aabaabaa", "ab", 0) = 1  
742 - * StringUtils.indexOf("aabaabaa", "b", 3) = 5  
743 - * StringUtils.indexOf("aabaabaa", "b", 9) = -1  
744 - * StringUtils.indexOf("aabaabaa", "b", -1) = 2  
745 - * StringUtils.indexOf("aabaabaa", "", 2) = 2  
746 - * StringUtils.indexOf("abc", "", 9) = 3  
747 - * </pre>  
748 - *  
749 - * @param str the String to check, may be null  
750 - * @param searchStr the String to find, may be null  
751 - * @param startPos the start position, negative treated as zero  
752 - * @return the first index of the search String,  
753 - * -1 if no match or <code>null</code> string input  
754 - * @since 2.0  
755 - */  
756 - public static int indexOf(String str, String searchStr, int startPos) {  
757 - if (str == null || searchStr == null) {  
758 - return INDEX_NOT_FOUND;  
759 - }  
760 - // JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence  
761 - if (searchStr.length() == 0 && startPos >= str.length()) {  
762 - return str.length();  
763 - }  
764 - return str.indexOf(searchStr, startPos);  
765 - }  
766 -  
767 - /**  
768 - * <p>Case in-sensitive find of the first index within a String.</p>  
769 - *  
770 - * <p>A <code>null</code> String will return <code>-1</code>.  
771 - * A negative start position is treated as zero.  
772 - * An empty ("") search String always matches.  
773 - * A start position greater than the string length only matches  
774 - * an empty search String.</p>  
775 - *  
776 - * <pre>  
777 - * StringUtils.indexOfIgnoreCase(null, *) = -1  
778 - * StringUtils.indexOfIgnoreCase(*, null) = -1  
779 - * StringUtils.indexOfIgnoreCase("", "") = 0  
780 - * StringUtils.indexOfIgnoreCase("aabaabaa", "a") = 0  
781 - * StringUtils.indexOfIgnoreCase("aabaabaa", "b") = 2  
782 - * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1  
783 - * </pre>  
784 - *  
785 - * @param str the String to check, may be null  
786 - * @param searchStr the String to find, may be null  
787 - * @return the first index of the search String,  
788 - * -1 if no match or <code>null</code> string input  
789 - * @since 2.5  
790 - */  
791 - public static int indexOfIgnoreCase(String str, String searchStr) {  
792 - return indexOfIgnoreCase(str, searchStr, 0);  
793 - }  
794 -  
795 - /**  
796 - * <p>Case in-sensitive find of the first index within a String  
797 - * from the specified position.</p>  
798 - *  
799 - * <p>A <code>null</code> String will return <code>-1</code>.  
800 - * A negative start position is treated as zero.  
801 - * An empty ("") search String always matches.  
802 - * A start position greater than the string length only matches  
803 - * an empty search String.</p>  
804 - *  
805 - * <pre>  
806 - * StringUtils.indexOfIgnoreCase(null, *, *) = -1  
807 - * StringUtils.indexOfIgnoreCase(*, null, *) = -1  
808 - * StringUtils.indexOfIgnoreCase("", "", 0) = 0  
809 - * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0) = 0  
810 - * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0) = 2  
811 - * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1  
812 - * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3) = 5  
813 - * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9) = -1  
814 - * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2  
815 - * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2) = 2  
816 - * StringUtils.indexOfIgnoreCase("abc", "", 9) = 3  
817 - * </pre>  
818 - *  
819 - * @param str the String to check, may be null  
820 - * @param searchStr the String to find, may be null  
821 - * @param startPos the start position, negative treated as zero  
822 - * @return the first index of the search String,  
823 - * -1 if no match or <code>null</code> string input  
824 - * @since 2.5  
825 - */  
826 - public static int indexOfIgnoreCase(String str, String searchStr, int startPos) {  
827 - if (str == null || searchStr == null) {  
828 - return INDEX_NOT_FOUND;  
829 - }  
830 - if (startPos < 0) {  
831 - startPos = 0;  
832 - }  
833 - int endLimit = (str.length() - searchStr.length()) + 1;  
834 - if (startPos > endLimit) {  
835 - return INDEX_NOT_FOUND;  
836 - }  
837 - if (searchStr.length() == 0) {  
838 - return startPos;  
839 - }  
840 - for (int i = startPos; i < endLimit; i++) {  
841 - if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {  
842 - return i;  
843 - }  
844 - }  
845 - return INDEX_NOT_FOUND;  
846 - }  
847 -  
848 - // LastIndexOf  
849 - //-----------------------------------------------------------------------  
850 - /**  
851 - * <p>Finds the last index within a String, handling <code>null</code>.  
852 - * This method uses {@link String#lastIndexOf(int)}.</p>  
853 - *  
854 - * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.</p>  
855 - *  
856 - * <pre>  
857 - * StringUtils.lastIndexOf(null, *) = -1  
858 - * StringUtils.lastIndexOf("", *) = -1  
859 - * StringUtils.lastIndexOf("aabaabaa", 'a') = 7  
860 - * StringUtils.lastIndexOf("aabaabaa", 'b') = 5  
861 - * </pre>  
862 - *  
863 - * @param str the String to check, may be null  
864 - * @param searchChar the character to find  
865 - * @return the last index of the search character,  
866 - * -1 if no match or <code>null</code> string input  
867 - * @since 2.0  
868 - */  
869 - public static int lastIndexOf(String str, char searchChar) {  
870 - if (isEmpty(str)) {  
871 - return INDEX_NOT_FOUND;  
872 - }  
873 - return str.lastIndexOf(searchChar);  
874 - }  
875 -  
876 - /**  
877 - * <p>Finds the last index within a String from a start position,  
878 - * handling <code>null</code>.  
879 - * This method uses {@link String#lastIndexOf(int, int)}.</p>  
880 - *  
881 - * <p>A <code>null</code> or empty ("") String will return <code>-1</code>.  
882 - * A negative start position returns <code>-1</code>.  
883 - * A start position greater than the string length searches the whole string.</p>  
884 - *  
885 - * <pre>  
886 - * StringUtils.lastIndexOf(null, *, *) = -1  
887 - * StringUtils.lastIndexOf("", *, *) = -1  
888 - * StringUtils.lastIndexOf("aabaabaa", 'b', 8) = 5  
889 - * StringUtils.lastIndexOf("aabaabaa", 'b', 4) = 2  
890 - * StringUtils.lastIndexOf("aabaabaa", 'b', 0) = -1  
891 - * StringUtils.lastIndexOf("aabaabaa", 'b', 9) = 5  
892 - * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1  
893 - * StringUtils.lastIndexOf("aabaabaa", 'a', 0) = 0  
894 - * </pre>  
895 - *  
896 - * @param str the String to check, may be null  
897 - * @param searchChar the character to find  
898 - * @param startPos the start position  
899 - * @return the last index of the search character,  
900 - * -1 if no match or <code>null</code> string input  
901 - * @since 2.0  
902 - */  
903 - public static int lastIndexOf(String str, char searchChar, int startPos) {  
904 - if (isEmpty(str)) {  
905 - return INDEX_NOT_FOUND;  
906 - }  
907 - return str.lastIndexOf(searchChar, startPos);  
908 - }  
909 -  
910 - /**  
911 - * <p>Finds the last index within a String, handling <code>null</code>.  
912 - * This method uses {@link String#lastIndexOf(String)}.</p>  
913 - *  
914 - * <p>A <code>null</code> String will return <code>-1</code>.</p>  
915 - *  
916 - * <pre>  
917 - * StringUtils.lastIndexOf(null, *) = -1  
918 - * StringUtils.lastIndexOf(*, null) = -1  
919 - * StringUtils.lastIndexOf("", "") = 0  
920 - * StringUtils.lastIndexOf("aabaabaa", "a") = 7  
921 - * StringUtils.lastIndexOf("aabaabaa", "b") = 5  
922 - * StringUtils.lastIndexOf("aabaabaa", "ab") = 4  
923 - * StringUtils.lastIndexOf("aabaabaa", "") = 8  
924 - * </pre>  
925 - *  
926 - * @param str the String to check, may be null  
927 - * @param searchStr the String to find, may be null  
928 - * @return the last index of the search String,  
929 - * -1 if no match or <code>null</code> string input  
930 - * @since 2.0  
931 - */  
932 - public static int lastIndexOf(String str, String searchStr) {  
933 - if (str == null || searchStr == null) {  
934 - return INDEX_NOT_FOUND;  
935 - }  
936 - return str.lastIndexOf(searchStr);  
937 - }  
938 -  
939 - /**  
940 - * <p>Finds the n-th last index within a String, handling <code>null</code>.  
941 - * This method uses {@link String#lastIndexOf(String)}.</p>  
942 - *  
943 - * <p>A <code>null</code> String will return <code>-1</code>.</p>  
944 - *  
945 - * <pre>  
946 - * StringUtils.lastOrdinalIndexOf(null, *, *) = -1  
947 - * StringUtils.lastOrdinalIndexOf(*, null, *) = -1  
948 - * StringUtils.lastOrdinalIndexOf("", "", *) = 0  
949 - * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1) = 7  
950 - * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2) = 6  
951 - * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1) = 5  
952 - * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2) = 2  
953 - * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4  
954 - * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1  
955 - * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1) = 8  
956 - * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2) = 8  
957 - * </pre>  
958 - *  
959 - * <p>Note that 'tail(String str, int n)' may be implemented as: </p>  
960 - *  
961 - * <pre>  
962 - * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)  
963 - * </pre>  
964 - *  
965 - * @param str the String to check, may be null  
966 - * @param searchStr the String to find, may be null  
967 - * @param ordinal the n-th last <code>searchStr</code> to find  
968 - * @return the n-th last index of the search String,  
969 - * <code>-1</code> (<code>INDEX_NOT_FOUND</code>) if no match or <code>null</code> string input  
970 - * @since 2.5  
971 - */  
972 - public static int lastOrdinalIndexOf(String str, String searchStr, int ordinal) {  
973 - return ordinalIndexOf(str, searchStr, ordinal, true);  
974 - }  
975 -  
976 - /**  
977 - * <p>Finds the first index within a String, handling <code>null</code>.  
978 - * This method uses {@link String#lastIndexOf(String, int)}.</p>  
979 - *  
980 - * <p>A <code>null</code> String will return <code>-1</code>.  
981 - * A negative start position returns <code>-1</code>.  
982 - * An empty ("") search String always matches unless the start position is negative.  
983 - * A start position greater than the string length searches the whole string.</p>  
984 - *  
985 - * <pre>  
986 - * StringUtils.lastIndexOf(null, *, *) = -1  
987 - * StringUtils.lastIndexOf(*, null, *) = -1  
988 - * StringUtils.lastIndexOf("aabaabaa", "a", 8) = 7  
989 - * StringUtils.lastIndexOf("aabaabaa", "b", 8) = 5  
990 - * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4  
991 - * StringUtils.lastIndexOf("aabaabaa", "b", 9) = 5  
992 - * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1  
993 - * StringUtils.lastIndexOf("aabaabaa", "a", 0) = 0  
994 - * StringUtils.lastIndexOf("aabaabaa", "b", 0) = -1  
995 - * </pre>  
996 - *  
997 - * @param str the String to check, may be null  
998 - * @param searchStr the String to find, may be null  
999 - * @param startPos the start position, negative treated as zero  
1000 - * @return the first index of the search String,  
1001 - * -1 if no match or <code>null</code> string input  
1002 - * @since 2.0  
1003 - */  
1004 - public static int lastIndexOf(String str, String searchStr, int startPos) {  
1005 - if (str == null || searchStr == null) {  
1006 - return INDEX_NOT_FOUND;  
1007 - }  
1008 - return str.lastIndexOf(searchStr, startPos);  
1009 - }  
1010 -  
1011 - /**  
1012 - * <p>Case in-sensitive find of the last index within a String.</p>  
1013 - *  
1014 - * <p>A <code>null</code> String will return <code>-1</code>.  
1015 - * A negative start position returns <code>-1</code>.  
1016 - * An empty ("") search String always matches unless the start position is negative.  
1017 - * A start position greater than the string length searches the whole string.</p>  
1018 - *  
1019 - * <pre>  
1020 - * StringUtils.lastIndexOfIgnoreCase(null, *) = -1  
1021 - * StringUtils.lastIndexOfIgnoreCase(*, null) = -1  
1022 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A") = 7  
1023 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B") = 5  
1024 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4  
1025 - * </pre>  
1026 - *  
1027 - * @param str the String to check, may be null  
1028 - * @param searchStr the String to find, may be null  
1029 - * @return the first index of the search String,  
1030 - * -1 if no match or <code>null</code> string input  
1031 - * @since 2.5  
1032 - */  
1033 - public static int lastIndexOfIgnoreCase(String str, String searchStr) {  
1034 - if (str == null || searchStr == null) {  
1035 - return INDEX_NOT_FOUND;  
1036 - }  
1037 - return lastIndexOfIgnoreCase(str, searchStr, str.length());  
1038 - }  
1039 -  
1040 - /**  
1041 - * <p>Case in-sensitive find of the last index within a String  
1042 - * from the specified position.</p>  
1043 - *  
1044 - * <p>A <code>null</code> String will return <code>-1</code>.  
1045 - * A negative start position returns <code>-1</code>.  
1046 - * An empty ("") search String always matches unless the start position is negative.  
1047 - * A start position greater than the string length searches the whole string.</p>  
1048 - *  
1049 - * <pre>  
1050 - * StringUtils.lastIndexOfIgnoreCase(null, *, *) = -1  
1051 - * StringUtils.lastIndexOfIgnoreCase(*, null, *) = -1  
1052 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8) = 7  
1053 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8) = 5  
1054 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4  
1055 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9) = 5  
1056 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1  
1057 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0) = 0  
1058 - * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0) = -1  
1059 - * </pre>  
1060 - *  
1061 - * @param str the String to check, may be null  
1062 - * @param searchStr the String to find, may be null  
1063 - * @param startPos the start position  
1064 - * @return the first index of the search String,  
1065 - * -1 if no match or <code>null</code> string input  
1066 - * @since 2.5  
1067 - */  
1068 - public static int lastIndexOfIgnoreCase(String str, String searchStr, int startPos) {  
1069 - if (str == null || searchStr == null) {  
1070 - return INDEX_NOT_FOUND;  
1071 - }  
1072 - if (startPos > (str.length() - searchStr.length())) {  
1073 - startPos = str.length() - searchStr.length();  
1074 - }  
1075 - if (startPos < 0) {  
1076 - return INDEX_NOT_FOUND;  
1077 - }  
1078 - if (searchStr.length() == 0) {  
1079 - return startPos;  
1080 - }  
1081 -  
1082 - for (int i = startPos; i >= 0; i--) {  
1083 - if (str.regionMatches(true, i, searchStr, 0, searchStr.length())) {  
1084 - return i;  
1085 - }  
1086 - }  
1087 - return INDEX_NOT_FOUND;  
1088 - }  
1089 -  
1090 - // Contains  
1091 - //-----------------------------------------------------------------------  
1092 - /**  
1093 - * <p>Checks if String contains a search character, handling <code>null</code>.  
1094 - * This method uses {@link String#indexOf(int)}.</p>  
1095 - *  
1096 - * <p>A <code>null</code> or empty ("") String will return <code>false</code>.</p>  
1097 - *  
1098 - * <pre>  
1099 - * StringUtils.contains(null, *) = false  
1100 - * StringUtils.contains("", *) = false  
1101 - * StringUtils.contains("abc", 'a') = true  
1102 - * StringUtils.contains("abc", 'z') = false  
1103 - * </pre>  
1104 - *  
1105 - * @param str the String to check, may be null  
1106 - * @param searchChar the character to find  
1107 - * @return true if the String contains the search character,  
1108 - * false if not or <code>null</code> string input  
1109 - * @since 2.0  
1110 - */  
1111 - public static boolean contains(String str, char searchChar) {  
1112 - if (isEmpty(str)) {  
1113 - return false;  
1114 - }  
1115 - return str.indexOf(searchChar) >= 0;  
1116 - }  
1117 -  
1118 - /**  
1119 - * <p>Checks if String contains a search String, handling <code>null</code>.  
1120 - * This method uses {@link String#indexOf(String)}.</p>  
1121 - *  
1122 - * <p>A <code>null</code> String will return <code>false</code>.</p>  
1123 - *  
1124 - * <pre>  
1125 - * StringUtils.contains(null, *) = false  
1126 - * StringUtils.contains(*, null) = false  
1127 - * StringUtils.contains("", "") = true  
1128 - * StringUtils.contains("abc", "") = true  
1129 - * StringUtils.contains("abc", "a") = true  
1130 - * StringUtils.contains("abc", "z") = false  
1131 - * </pre>  
1132 - *  
1133 - * @param str the String to check, may be null  
1134 - * @param searchStr the String to find, may be null  
1135 - * @return true if the String contains the search String,  
1136 - * false if not or <code>null</code> string input  
1137 - * @since 2.0  
1138 - */  
1139 - public static boolean contains(String str, String searchStr) {  
1140 - if (str == null || searchStr == null) {  
1141 - return false;  
1142 - }  
1143 - return str.indexOf(searchStr) >= 0;  
1144 - }  
1145 -  
1146 - /**  
1147 - * <p>Checks if String contains a search String irrespective of case,  
1148 - * handling <code>null</code>. Case-insensitivity is defined as by  
1149 - * {@link String#equalsIgnoreCase(String)}.  
1150 - *  
1151 - * <p>A <code>null</code> String will return <code>false</code>.</p>  
1152 - *  
1153 - * <pre>  
1154 - * StringUtils.contains(null, *) = false  
1155 - * StringUtils.contains(*, null) = false  
1156 - * StringUtils.contains("", "") = true  
1157 - * StringUtils.contains("abc", "") = true  
1158 - * StringUtils.contains("abc", "a") = true  
1159 - * StringUtils.contains("abc", "z") = false  
1160 - * StringUtils.contains("abc", "A") = true  
1161 - * StringUtils.contains("abc", "Z") = false  
1162 - * </pre>  
1163 - *  
1164 - * @param str the String to check, may be null  
1165 - * @param searchStr the String to find, may be null  
1166 - * @return true if the String contains the search String irrespective of  
1167 - * case or false if not or <code>null</code> string input  
1168 - */  
1169 - public static boolean containsIgnoreCase(String str, String searchStr) {  
1170 - if (str == null || searchStr == null) {  
1171 - return false;  
1172 - }  
1173 - int len = searchStr.length();  
1174 - int max = str.length() - len;  
1175 - for (int i = 0; i <= max; i++) {  
1176 - if (str.regionMatches(true, i, searchStr, 0, len)) {  
1177 - return true;  
1178 - }  
1179 - }  
1180 - return false;  
1181 - }  
1182 -  
1183 -  
1184 - // IndexOfAny strings  
1185 - //-----------------------------------------------------------------------  
1186 - /**  
1187 - * <p>Find the first index of any of a set of potential substrings.</p>  
1188 - *  
1189 - * <p>A <code>null</code> String will return <code>-1</code>.  
1190 - * A <code>null</code> or zero length search array will return <code>-1</code>.  
1191 - * A <code>null</code> search array entry will be ignored, but a search  
1192 - * array containing "" will return <code>0</code> if <code>str</code> is not  
1193 - * null. This method uses {@link String#indexOf(String)}.</p>  
1194 - *  
1195 - * <pre>  
1196 - * StringUtils.indexOfAny(null, *) = -1  
1197 - * StringUtils.indexOfAny(*, null) = -1  
1198 - * StringUtils.indexOfAny(*, []) = -1  
1199 - * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"]) = 2  
1200 - * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"]) = 2  
1201 - * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"]) = -1  
1202 - * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1  
1203 - * StringUtils.indexOfAny("zzabyycdxx", [""]) = 0  
1204 - * StringUtils.indexOfAny("", [""]) = 0  
1205 - * StringUtils.indexOfAny("", ["a"]) = -1  
1206 - * </pre>  
1207 - *  
1208 - * @param str the String to check, may be null  
1209 - * @param searchStrs the Strings to search for, may be null  
1210 - * @return the first index of any of the searchStrs in str, -1 if no match  
1211 - */  
1212 - public static int indexOfAny(String str, String[] searchStrs) {  
1213 - if ((str == null) || (searchStrs == null)) {  
1214 - return INDEX_NOT_FOUND;  
1215 - }  
1216 - int sz = searchStrs.length;  
1217 -  
1218 - // String's can't have a MAX_VALUEth index.  
1219 - int ret = Integer.MAX_VALUE;  
1220 -  
1221 - int tmp = 0;  
1222 - for (int i = 0; i < sz; i++) {  
1223 - String search = searchStrs[i];  
1224 - if (search == null) {  
1225 - continue;  
1226 - }  
1227 - tmp = str.indexOf(search);  
1228 - if (tmp == INDEX_NOT_FOUND) {  
1229 - continue;  
1230 - }  
1231 -  
1232 - if (tmp < ret) {  
1233 - ret = tmp;  
1234 - }  
1235 - }  
1236 -  
1237 - return (ret == Integer.MAX_VALUE) ? INDEX_NOT_FOUND : ret;  
1238 - }  
1239 -  
1240 - /**  
1241 - * <p>Find the latest index of any of a set of potential substrings.</p>  
1242 - *  
1243 - * <p>A <code>null</code> String will return <code>-1</code>.  
1244 - * A <code>null</code> search array will return <code>-1</code>.  
1245 - * A <code>null</code> or zero length search array entry will be ignored,  
1246 - * but a search array containing "" will return the length of <code>str</code>  
1247 - * if <code>str</code> is not null. This method uses {@link String#indexOf(String)}</p>  
1248 - *  
1249 - * <pre>  
1250 - * StringUtils.lastIndexOfAny(null, *) = -1  
1251 - * StringUtils.lastIndexOfAny(*, null) = -1  
1252 - * StringUtils.lastIndexOfAny(*, []) = -1  
1253 - * StringUtils.lastIndexOfAny(*, [null]) = -1  
1254 - * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6  
1255 - * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6  
1256 - * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1  
1257 - * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1  
1258 - * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""]) = 10  
1259 - * </pre>  
1260 - *  
1261 - * @param str the String to check, may be null  
1262 - * @param searchStrs the Strings to search for, may be null  
1263 - * @return the last index of any of the Strings, -1 if no match  
1264 - */  
1265 - public static int lastIndexOfAny(String str, String[] searchStrs) {  
1266 - if ((str == null) || (searchStrs == null)) {  
1267 - return INDEX_NOT_FOUND;  
1268 - }  
1269 - int sz = searchStrs.length;  
1270 - int ret = INDEX_NOT_FOUND;  
1271 - int tmp = 0;  
1272 - for (int i = 0; i < sz; i++) {  
1273 - String search = searchStrs[i];  
1274 - if (search == null) {  
1275 - continue;  
1276 - }  
1277 - tmp = str.lastIndexOf(search);  
1278 - if (tmp > ret) {  
1279 - ret = tmp;  
1280 - }  
1281 - }  
1282 - return ret;  
1283 - }  
1284 -  
1285 - // Substring  
1286 - //-----------------------------------------------------------------------  
1287 - /**  
1288 - * <p>Gets a substring from the specified String avoiding exceptions.</p>  
1289 - *  
1290 - * <p>A negative start position can be used to start <code>n</code>  
1291 - * characters from the end of the String.</p>  
1292 - *  
1293 - * <p>A <code>null</code> String will return <code>null</code>.  
1294 - * An empty ("") String will return "".</p>  
1295 - *  
1296 - * <pre>  
1297 - * StringUtils.substring(null, *) = null  
1298 - * StringUtils.substring("", *) = ""  
1299 - * StringUtils.substring("abc", 0) = "abc"  
1300 - * StringUtils.substring("abc", 2) = "c"  
1301 - * StringUtils.substring("abc", 4) = ""  
1302 - * StringUtils.substring("abc", -2) = "bc"  
1303 - * StringUtils.substring("abc", -4) = "abc"  
1304 - * </pre>  
1305 - *  
1306 - * @param str the String to get the substring from, may be null  
1307 - * @param start the position to start from, negative means  
1308 - * count back from the end of the String by this many characters  
1309 - * @return substring from start position, <code>null</code> if null String input  
1310 - */  
1311 - public static String substring(String str, int start) {  
1312 - if (str == null) {  
1313 - return null;  
1314 - }  
1315 -  
1316 - // handle negatives, which means last n characters  
1317 - if (start < 0) {  
1318 - start = str.length() + start; // remember start is negative  
1319 - }  
1320 -  
1321 - if (start < 0) {  
1322 - start = 0;  
1323 - }  
1324 - if (start > str.length()) {  
1325 - return EMPTY;  
1326 - }  
1327 -  
1328 - return str.substring(start);  
1329 - }  
1330 -  
1331 - /**  
1332 - * <p>Gets a substring from the specified String avoiding exceptions.</p>  
1333 - *  
1334 - * <p>A negative start position can be used to start/end <code>n</code>  
1335 - * characters from the end of the String.</p>  
1336 - *  
1337 - * <p>The returned substring starts with the character in the <code>start</code>  
1338 - * position and ends before the <code>end</code> position. All position counting is  
1339 - * zero-based -- i.e., to start at the beginning of the string use  
1340 - * <code>start = 0</code>. Negative start and end positions can be used to  
1341 - * specify offsets relative to the end of the String.</p>  
1342 - *  
1343 - * <p>If <code>start</code> is not strictly to the left of <code>end</code>, ""  
1344 - * is returned.</p>  
1345 - *  
1346 - * <pre>  
1347 - * StringUtils.substring(null, *, *) = null  
1348 - * StringUtils.substring("", * , *) = "";  
1349 - * StringUtils.substring("abc", 0, 2) = "ab"  
1350 - * StringUtils.substring("abc", 2, 0) = ""  
1351 - * StringUtils.substring("abc", 2, 4) = "c"  
1352 - * StringUtils.substring("abc", 4, 6) = ""  
1353 - * StringUtils.substring("abc", 2, 2) = ""  
1354 - * StringUtils.substring("abc", -2, -1) = "b"  
1355 - * StringUtils.substring("abc", -4, 2) = "ab"  
1356 - * </pre>  
1357 - *  
1358 - * @param str the String to get the substring from, may be null  
1359 - * @param start the position to start from, negative means  
1360 - * count back from the end of the String by this many characters  
1361 - * @param end the position to end at (exclusive), negative means  
1362 - * count back from the end of the String by this many characters  
1363 - * @return substring from start position to end positon,  
1364 - * <code>null</code> if null String input  
1365 - */  
1366 - public static String substring(String str, int start, int end) {  
1367 - if (str == null) {  
1368 - return null;  
1369 - }  
1370 -  
1371 - // handle negatives  
1372 - if (end < 0) {  
1373 - end = str.length() + end; // remember end is negative  
1374 - }  
1375 - if (start < 0) {  
1376 - start = str.length() + start; // remember start is negative  
1377 - }  
1378 -  
1379 - // check length next  
1380 - if (end > str.length()) {  
1381 - end = str.length();  
1382 - }  
1383 -  
1384 - // if start is greater than end, return ""  
1385 - if (start > end) {  
1386 - return EMPTY;  
1387 - }  
1388 -  
1389 - if (start < 0) {  
1390 - start = 0;  
1391 - }  
1392 - if (end < 0) {  
1393 - end = 0;  
1394 - }  
1395 -  
1396 - return str.substring(start, end);  
1397 - }  
1398 -  
1399 - // Left/Right/Mid  
1400 - //-----------------------------------------------------------------------  
1401 - /**  
1402 - * <p>Gets the leftmost <code>len</code> characters of a String.</p>  
1403 - *  
1404 - * <p>If <code>len</code> characters are not available, or the  
1405 - * String is <code>null</code>, the String will be returned without  
1406 - * an exception. An empty String is returned if len is negative.</p>  
1407 - *  
1408 - * <pre>  
1409 - * StringUtils.left(null, *) = null  
1410 - * StringUtils.left(*, -ve) = ""  
1411 - * StringUtils.left("", *) = ""  
1412 - * StringUtils.left("abc", 0) = ""  
1413 - * StringUtils.left("abc", 2) = "ab"  
1414 - * StringUtils.left("abc", 4) = "abc"  
1415 - * </pre>  
1416 - *  
1417 - * @param str the String to get the leftmost characters from, may be null  
1418 - * @param len the length of the required String  
1419 - * @return the leftmost characters, <code>null</code> if null String input  
1420 - */  
1421 - public static String left(String str, int len) {  
1422 - if (str == null) {  
1423 - return null;  
1424 - }  
1425 - if (len < 0) {  
1426 - return EMPTY;  
1427 - }  
1428 - if (str.length() <= len) {  
1429 - return str;  
1430 - }  
1431 - return str.substring(0, len);  
1432 - }  
1433 -  
1434 - /**  
1435 - * <p>Gets the rightmost <code>len</code> characters of a String.</p>  
1436 - *  
1437 - * <p>If <code>len</code> characters are not available, or the String  
1438 - * is <code>null</code>, the String will be returned without an  
1439 - * an exception. An empty String is returned if len is negative.</p>  
1440 - *  
1441 - * <pre>  
1442 - * StringUtils.right(null, *) = null  
1443 - * StringUtils.right(*, -ve) = ""  
1444 - * StringUtils.right("", *) = ""  
1445 - * StringUtils.right("abc", 0) = ""  
1446 - * StringUtils.right("abc", 2) = "bc"  
1447 - * StringUtils.right("abc", 4) = "abc"  
1448 - * </pre>  
1449 - *  
1450 - * @param str the String to get the rightmost characters from, may be null  
1451 - * @param len the length of the required String  
1452 - * @return the rightmost characters, <code>null</code> if null String input  
1453 - */  
1454 - public static String right(String str, int len) {  
1455 - if (str == null) {  
1456 - return null;  
1457 - }  
1458 - if (len < 0) {  
1459 - return EMPTY;  
1460 - }  
1461 - if (str.length() <= len) {  
1462 - return str;  
1463 - }  
1464 - return str.substring(str.length() - len);  
1465 - }  
1466 -  
1467 - /**  
1468 - * <p>Gets <code>len</code> characters from the middle of a String.</p>  
1469 - *  
1470 - * <p>If <code>len</code> characters are not available, the remainder  
1471 - * of the String will be returned without an exception. If the  
1472 - * String is <code>null</code>, <code>null</code> will be returned.  
1473 - * An empty String is returned if len is negative or exceeds the  
1474 - * length of <code>str</code>.</p>  
1475 - *  
1476 - * <pre>  
1477 - * StringUtils.mid(null, *, *) = null  
1478 - * StringUtils.mid(*, *, -ve) = ""  
1479 - * StringUtils.mid("", 0, *) = ""  
1480 - * StringUtils.mid("abc", 0, 2) = "ab"  
1481 - * StringUtils.mid("abc", 0, 4) = "abc"  
1482 - * StringUtils.mid("abc", 2, 4) = "c"  
1483 - * StringUtils.mid("abc", 4, 2) = ""  
1484 - * StringUtils.mid("abc", -2, 2) = "ab"  
1485 - * </pre>  
1486 - *  
1487 - * @param str the String to get the characters from, may be null  
1488 - * @param pos the position to start from, negative treated as zero  
1489 - * @param len the length of the required String  
1490 - * @return the middle characters, <code>null</code> if null String input  
1491 - */  
1492 - public static String mid(String str, int pos, int len) {  
1493 - if (str == null) {  
1494 - return null;  
1495 - }  
1496 - if (len < 0 || pos > str.length()) {  
1497 - return EMPTY;  
1498 - }  
1499 - if (pos < 0) {  
1500 - pos = 0;  
1501 - }  
1502 - if (str.length() <= (pos + len)) {  
1503 - return str.substring(pos);  
1504 - }  
1505 - return str.substring(pos, pos + len);  
1506 - }  
1507 -  
1508 - // SubStringAfter/SubStringBefore  
1509 - //-----------------------------------------------------------------------  
1510 - /**  
1511 - * <p>Gets the substring before the first occurrence of a separator.  
1512 - * The separator is not returned.</p>  
1513 - *  
1514 - * <p>A <code>null</code> string input will return <code>null</code>.  
1515 - * An empty ("") string input will return the empty string.  
1516 - * A <code>null</code> separator will return the input string.</p>  
1517 - *  
1518 - * <p>If nothing is found, the string input is returned.</p>  
1519 - *  
1520 - * <pre>  
1521 - * StringUtils.substringBefore(null, *) = null  
1522 - * StringUtils.substringBefore("", *) = ""  
1523 - * StringUtils.substringBefore("abc", "a") = ""  
1524 - * StringUtils.substringBefore("abcba", "b") = "a"  
1525 - * StringUtils.substringBefore("abc", "c") = "ab"  
1526 - * StringUtils.substringBefore("abc", "d") = "abc"  
1527 - * StringUtils.substringBefore("abc", "") = ""  
1528 - * StringUtils.substringBefore("abc", null) = "abc"  
1529 - * </pre>  
1530 - *  
1531 - * @param str the String to get a substring from, may be null  
1532 - * @param separator the String to search for, may be null  
1533 - * @return the substring before the first occurrence of the separator,  
1534 - * <code>null</code> if null String input  
1535 - * @since 2.0  
1536 - */  
1537 - public static String substringBefore(String str, String separator) {  
1538 - if (isEmpty(str) || separator == null) {  
1539 - return str;  
1540 - }  
1541 - if (separator.length() == 0) {  
1542 - return EMPTY;  
1543 - }  
1544 - int pos = str.indexOf(separator);  
1545 - if (pos == INDEX_NOT_FOUND) {  
1546 - return str;  
1547 - }  
1548 - return str.substring(0, pos);  
1549 - }  
1550 -  
1551 - /**  
1552 - * <p>Gets the substring after the first occurrence of a separator.  
1553 - * The separator is not returned.</p>  
1554 - *  
1555 - * <p>A <code>null</code> string input will return <code>null</code>.  
1556 - * An empty ("") string input will return the empty string.  
1557 - * A <code>null</code> separator will return the empty string if the  
1558 - * input string is not <code>null</code>.</p>  
1559 - *  
1560 - * <p>If nothing is found, the empty string is returned.</p>  
1561 - *  
1562 - * <pre>  
1563 - * StringUtils.substringAfter(null, *) = null  
1564 - * StringUtils.substringAfter("", *) = ""  
1565 - * StringUtils.substringAfter(*, null) = ""  
1566 - * StringUtils.substringAfter("abc", "a") = "bc"  
1567 - * StringUtils.substringAfter("abcba", "b") = "cba"  
1568 - * StringUtils.substringAfter("abc", "c") = ""  
1569 - * StringUtils.substringAfter("abc", "d") = ""  
1570 - * StringUtils.substringAfter("abc", "") = "abc"  
1571 - * </pre>  
1572 - *  
1573 - * @param str the String to get a substring from, may be null  
1574 - * @param separator the String to search for, may be null  
1575 - * @return the substring after the first occurrence of the separator,  
1576 - * <code>null</code> if null String input  
1577 - * @since 2.0  
1578 - */  
1579 - public static String substringAfter(String str, String separator) {  
1580 - if (isEmpty(str)) {  
1581 - return str;  
1582 - }  
1583 - if (separator == null) {  
1584 - return EMPTY;  
1585 - }  
1586 - int pos = str.indexOf(separator);  
1587 - if (pos == INDEX_NOT_FOUND) {  
1588 - return EMPTY;  
1589 - }  
1590 - return str.substring(pos + separator.length());  
1591 - }  
1592 -  
1593 - /**  
1594 - * <p>Gets the substring before the last occurrence of a separator.  
1595 - * The separator is not returned.</p>  
1596 - *  
1597 - * <p>A <code>null</code> string input will return <code>null</code>.  
1598 - * An empty ("") string input will return the empty string.  
1599 - * An empty or <code>null</code> separator will return the input string.</p>  
1600 - *  
1601 - * <p>If nothing is found, the string input is returned.</p>  
1602 - *  
1603 - * <pre>  
1604 - * StringUtils.substringBeforeLast(null, *) = null  
1605 - * StringUtils.substringBeforeLast("", *) = ""  
1606 - * StringUtils.substringBeforeLast("abcba", "b") = "abc"  
1607 - * StringUtils.substringBeforeLast("abc", "c") = "ab"  
1608 - * StringUtils.substringBeforeLast("a", "a") = ""  
1609 - * StringUtils.substringBeforeLast("a", "z") = "a"  
1610 - * StringUtils.substringBeforeLast("a", null) = "a"  
1611 - * StringUtils.substringBeforeLast("a", "") = "a"  
1612 - * </pre>  
1613 - *  
1614 - * @param str the String to get a substring from, may be null  
1615 - * @param separator the String to search for, may be null  
1616 - * @return the substring before the last occurrence of the separator,  
1617 - * <code>null</code> if null String input  
1618 - * @since 2.0  
1619 - */  
1620 - public static String substringBeforeLast(String str, String separator) {  
1621 - if (isEmpty(str) || isEmpty(separator)) {  
1622 - return str;  
1623 - }  
1624 - int pos = str.lastIndexOf(separator);  
1625 - if (pos == INDEX_NOT_FOUND) {  
1626 - return str;  
1627 - }  
1628 - return str.substring(0, pos);  
1629 - }  
1630 -  
1631 - /**  
1632 - * <p>Gets the substring after the last occurrence of a separator.  
1633 - * The separator is not returned.</p>  
1634 - *  
1635 - * <p>A <code>null</code> string input will return <code>null</code>.  
1636 - * An empty ("") string input will return the empty string.  
1637 - * An empty or <code>null</code> separator will return the empty string if  
1638 - * the input string is not <code>null</code>.</p>  
1639 - *  
1640 - * <p>If nothing is found, the empty string is returned.</p>  
1641 - *  
1642 - * <pre>  
1643 - * StringUtils.substringAfterLast(null, *) = null  
1644 - * StringUtils.substringAfterLast("", *) = ""  
1645 - * StringUtils.substringAfterLast(*, "") = ""  
1646 - * StringUtils.substringAfterLast(*, null) = ""  
1647 - * StringUtils.substringAfterLast("abc", "a") = "bc"  
1648 - * StringUtils.substringAfterLast("abcba", "b") = "a"  
1649 - * StringUtils.substringAfterLast("abc", "c") = ""  
1650 - * StringUtils.substringAfterLast("a", "a") = ""  
1651 - * StringUtils.substringAfterLast("a", "z") = ""  
1652 - * </pre>  
1653 - *  
1654 - * @param str the String to get a substring from, may be null  
1655 - * @param separator the String to search for, may be null  
1656 - * @return the substring after the last occurrence of the separator,  
1657 - * <code>null</code> if null String input  
1658 - * @since 2.0  
1659 - */  
1660 - public static String substringAfterLast(String str, String separator) {  
1661 - if (isEmpty(str)) {  
1662 - return str;  
1663 - }  
1664 - if (isEmpty(separator)) {  
1665 - return EMPTY;  
1666 - }  
1667 - int pos = str.lastIndexOf(separator);  
1668 - if (pos == INDEX_NOT_FOUND || pos == (str.length() - separator.length())) {  
1669 - return EMPTY;  
1670 - }  
1671 - return str.substring(pos + separator.length());  
1672 - }  
1673 -  
1674 - // Substring between  
1675 - //-----------------------------------------------------------------------  
1676 - /**  
1677 - * <p>Gets the String that is nested in between two instances of the  
1678 - * same String.</p>  
1679 - *  
1680 - * <p>A <code>null</code> input String returns <code>null</code>.  
1681 - * A <code>null</code> tag returns <code>null</code>.</p>  
1682 - *  
1683 - * <pre>  
1684 - * StringUtils.substringBetween(null, *) = null  
1685 - * StringUtils.substringBetween("", "") = ""  
1686 - * StringUtils.substringBetween("", "tag") = null  
1687 - * StringUtils.substringBetween("tagabctag", null) = null  
1688 - * StringUtils.substringBetween("tagabctag", "") = ""  
1689 - * StringUtils.substringBetween("tagabctag", "tag") = "abc"  
1690 - * </pre>  
1691 - *  
1692 - * @param str the String containing the substring, may be null  
1693 - * @param tag the String before and after the substring, may be null  
1694 - * @return the substring, <code>null</code> if no match  
1695 - * @since 2.0  
1696 - */  
1697 - public static String substringBetween(String str, String tag) {  
1698 - return substringBetween(str, tag, tag);  
1699 - }  
1700 -  
1701 - /**  
1702 - * <p>Gets the String that is nested in between two Strings.  
1703 - * Only the first match is returned.</p>  
1704 - *  
1705 - * <p>A <code>null</code> input String returns <code>null</code>.  
1706 - * A <code>null</code> open/close returns <code>null</code> (no match).  
1707 - * An empty ("") open and close returns an empty string.</p>  
1708 - *  
1709 - * <pre>  
1710 - * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"  
1711 - * StringUtils.substringBetween(null, *, *) = null  
1712 - * StringUtils.substringBetween(*, null, *) = null  
1713 - * StringUtils.substringBetween(*, *, null) = null  
1714 - * StringUtils.substringBetween("", "", "") = ""  
1715 - * StringUtils.substringBetween("", "", "]") = null  
1716 - * StringUtils.substringBetween("", "[", "]") = null  
1717 - * StringUtils.substringBetween("yabcz", "", "") = ""  
1718 - * StringUtils.substringBetween("yabcz", "y", "z") = "abc"  
1719 - * StringUtils.substringBetween("yabczyabcz", "y", "z") = "abc"  
1720 - * </pre>  
1721 - *  
1722 - * @param str the String containing the substring, may be null  
1723 - * @param open the String before the substring, may be null  
1724 - * @param close the String after the substring, may be null  
1725 - * @return the substring, <code>null</code> if no match  
1726 - * @since 2.0  
1727 - */  
1728 - public static String substringBetween(String str, String open, String close) {  
1729 - if (str == null || open == null || close == null) {  
1730 - return null;  
1731 - }  
1732 - int start = str.indexOf(open);  
1733 - if (start != INDEX_NOT_FOUND) {  
1734 - int end = str.indexOf(close, start + open.length());  
1735 - if (end != INDEX_NOT_FOUND) {  
1736 - return str.substring(start + open.length(), end);  
1737 - }  
1738 - }  
1739 - return null;  
1740 - }  
1741 -  
1742 -}  
1743 \ No newline at end of file 0 \ No newline at end of file
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/captcha/CaptchaController.java
1 package cn.iocoder.yudao.module.system.controller.admin.captcha; 1 package cn.iocoder.yudao.module.system.controller.admin.captcha;
2 2
  3 +import cn.hutool.core.util.StrUtil;
3 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 4 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
4 import com.anji.captcha.model.common.ResponseModel; 5 import com.anji.captcha.model.common.ResponseModel;
5 import com.anji.captcha.model.vo.CaptchaVO; 6 import com.anji.captcha.model.vo.CaptchaVO;
  7 +import com.anji.captcha.service.CaptchaService;
6 import io.swagger.annotations.Api; 8 import io.swagger.annotations.Api;
7 import io.swagger.annotations.ApiOperation; 9 import io.swagger.annotations.ApiOperation;
8 import org.springframework.web.bind.annotation.PostMapping; 10 import org.springframework.web.bind.annotation.PostMapping;
@@ -10,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestBody; @@ -10,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestBody;
10 import org.springframework.web.bind.annotation.RequestMapping; 12 import org.springframework.web.bind.annotation.RequestMapping;
11 import org.springframework.web.bind.annotation.RestController; 13 import org.springframework.web.bind.annotation.RestController;
12 14
  15 +import javax.annotation.Resource;
13 import javax.annotation.security.PermitAll; 16 import javax.annotation.security.PermitAll;
14 import javax.servlet.http.HttpServletRequest; 17 import javax.servlet.http.HttpServletRequest;
15 18
@@ -24,24 +27,46 @@ import javax.servlet.http.HttpServletRequest; @@ -24,24 +27,46 @@ import javax.servlet.http.HttpServletRequest;
24 @Api(tags = "管理后台 - 验证码") 27 @Api(tags = "管理后台 - 验证码")
25 @RestController("adminCaptchaController") 28 @RestController("adminCaptchaController")
26 @RequestMapping("/system/captcha") 29 @RequestMapping("/system/captcha")
27 -public class CaptchaController extends com.anji.captcha.controller.CaptchaController { 30 +public class CaptchaController {
  31 +
  32 + @Resource
  33 + private CaptchaService captchaService;
28 34
29 @PostMapping({"/get"}) 35 @PostMapping({"/get"})
30 @ApiOperation("获得验证码") 36 @ApiOperation("获得验证码")
31 @PermitAll 37 @PermitAll
32 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 38 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
33 - @Override  
34 public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) { 39 public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
35 - return super.get(data, request); 40 + assert request.getRemoteHost() != null;
  41 + data.setBrowserInfo(getRemoteId(request));
  42 + return captchaService.get(data);
36 } 43 }
37 44
38 @PostMapping("/check") 45 @PostMapping("/check")
39 @ApiOperation("校验验证码") 46 @ApiOperation("校验验证码")
40 @PermitAll 47 @PermitAll
41 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 48 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
42 - @Override  
43 public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) { 49 public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
44 - return super.check(data, request); 50 + data.setBrowserInfo(getRemoteId(request));
  51 + return captchaService.check(data);
  52 + }
  53 +
  54 + public static String getRemoteId(HttpServletRequest request) {
  55 + String xfwd = request.getHeader("X-Forwarded-For");
  56 + String ip = getRemoteIpFromXfwd(xfwd);
  57 + String ua = request.getHeader("user-agent");
  58 + if (StrUtil.isNotBlank(ip)) {
  59 + return ip + ua;
  60 + }
  61 + return request.getRemoteAddr() + ua;
  62 + }
  63 +
  64 + private static String getRemoteIpFromXfwd(String xfwd) {
  65 + if (StrUtil.isNotBlank(xfwd)) {
  66 + String[] ipList = xfwd.split(",");
  67 + return StrUtil.trim(ipList[0]);
  68 + }
  69 + return null;
45 } 70 }
46 71
47 } 72 }