diff --git a/opsli-base-support/opsli-core/pom.xml b/opsli-base-support/opsli-core/pom.xml
index 2dbaf822..094a8b9e 100644
--- a/opsli-base-support/opsli-core/pom.xml
+++ b/opsli-base-support/opsli-core/pom.xml
@@ -54,10 +54,10 @@
3.3.1
-
+
- com.github.axet
- kaptcha
+ com.github.whvcse
+ easy-captcha
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/KaptchaConfig.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/KaptchaConfig.java
deleted file mode 100644
index e63f2437..00000000
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/KaptchaConfig.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.opsli.core.autoconfigure.conf;
-
-import com.google.code.kaptcha.impl.DefaultKaptcha;
-import com.google.code.kaptcha.util.Config;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.util.Properties;
-
-
-/**
- * 生成验证码配置
- *
- * @author 孙志强
-
- * @date 2017-04-20 19:22
- */
-@Configuration
-public class KaptchaConfig {
-
- @Bean
- public DefaultKaptcha producer() {
- Properties properties = new Properties();
- properties.put("kaptcha.border", "no");
- properties.put("kaptcha.textproducer.font.color", "black");
- properties.put("kaptcha.textproducer.char.space", "10");
- properties.put("kaptcha.textproducer.char.string", "1234567890");
- properties.put("kaptcha.textproducer.char.length", "4");
- Config config = new Config(properties);
- DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
- defaultKaptcha.setConfig(config);
- return defaultKaptcha;
- }
-}
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/ShiroConfig.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/ShiroConfig.java
index e545b597..0c6abf7e 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/ShiroConfig.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/autoconfigure/conf/ShiroConfig.java
@@ -91,7 +91,7 @@ public class ShiroConfig {
filterMap.put("/sys/login", "anon");
filterMap.put("/sys/publicKey", "anon");
filterMap.put("/sys/slipCount", "anon");
- filterMap.put("/captcha.jpg", "anon");
+ filterMap.put("/captcha*", "anon");
// 导出Excel\模版 不做自动拦截 手动拦截
filterMap.put(apiPathProperties.getGlobalPrefix() + "/**/exportExcel", "anon");
diff --git a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/CaptchaUtil.java b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/CaptchaUtil.java
index 8f065ef7..3c8ff26d 100644
--- a/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/CaptchaUtil.java
+++ b/opsli-base-support/opsli-core/src/main/java/org/opsli/core/utils/CaptchaUtil.java
@@ -15,11 +15,14 @@
*/
package org.opsli.core.utils;
-import com.google.code.kaptcha.Producer;
+import cn.hutool.core.util.RandomUtil;
+import com.google.common.collect.Lists;
+import com.wf.captcha.ArithmeticCaptcha;
+import com.wf.captcha.GifCaptcha;
+import com.wf.captcha.SpecCaptcha;
+import com.wf.captcha.base.Captcha;
import org.apache.commons.lang3.StringUtils;
-import org.opsli.common.constants.CacheConstants;
import org.opsli.common.exception.TokenException;
-import org.opsli.common.utils.Props;
import org.opsli.core.cache.local.CacheUtil;
import org.opsli.core.msg.TokenMsg;
import org.opsli.plugins.redis.RedisPlugin;
@@ -28,10 +31,12 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
-import java.awt.image.BufferedImage;
+import java.io.OutputStream;
+import java.util.List;
import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
+
/**
* 验证码
*
@@ -41,7 +46,16 @@ import static org.opsli.common.constants.OrderConstants.UTIL_ORDER;
@Component
@Order(UTIL_ORDER)
@Lazy(false)
-public class CaptchaUtil{
+public class CaptchaUtil {
+
+ /** 验证码宽度 */
+ private static final int CAPTCHA_WIDTH = 180;
+ /** 验证码高度 */
+ private static final int CAPTCHA_HEIGHT = 58;
+ /** 验证码位数 */
+ private static final int CAPTCHA_LEN = 4;
+ /** 验证码策略 */
+ private static final List CAPTCHA_STRATEGY_LIST;
/** 缓存前缀 */
private static final String PREFIX = "temp:captcha:";
@@ -49,55 +63,69 @@ public class CaptchaUtil{
private static final int TIME_OUT = 300;
/** Redis插件 */
private static RedisPlugin redisPlugin;
- /** 谷歌验证码 */
- private static Producer producer;
+
+ static {
+ CAPTCHA_STRATEGY_LIST = Lists.newArrayListWithCapacity(3);
+ CAPTCHA_STRATEGY_LIST.add(new CaptchaStrategyBySpec());
+ CAPTCHA_STRATEGY_LIST.add(new CaptchaStrategyByGif());
+ CAPTCHA_STRATEGY_LIST.add(new CaptchaStrategyByArithmetic());
+ }
/**
* 获得验证码
- * @param uuid UUID
- * @return BufferedImage
+ *
+ * @param uuid
+ * @return
*/
- public static BufferedImage getCaptcha(String uuid) {
- if(StringUtils.isBlank(uuid)){
+ public static void createCaptcha(String uuid, OutputStream out) {
+ if (StringUtils.isBlank(uuid)) {
throw new RuntimeException("uuid不能为空");
}
- //生成文字验证码
- String code = producer.createText();
+ // 随机生成验证码
+ int randomInt = RandomUtil.randomInt(0, CAPTCHA_STRATEGY_LIST.size());
- boolean ret = redisPlugin.put(CacheUtil.getPrefixName() + PREFIX + uuid, code, TIME_OUT);
+ // 获得验证码生成策略
+ CaptchaStrategy captchaStrategy = CAPTCHA_STRATEGY_LIST.get(randomInt);
+ // 生成验证码
+ Captcha captcha = captchaStrategy.createCaptcha();
+
+ // 保存至缓存
+ boolean ret = redisPlugin.put(CacheUtil.getPrefixName() + PREFIX + uuid, captcha.text(), TIME_OUT);
if(ret){
- return producer.createImage(code);
+ // 输出
+ captcha.out(out);
}
- return null;
}
/**
* 校验验证码
- * @param uuid UUID
- * @param code CODE
+ *
+ * @param uuid
+ * @param code
+ * @return
*/
public static void validate(String uuid, String code) {
// 判断UUID 是否为空
- if(StringUtils.isEmpty(uuid)){
+ if (StringUtils.isEmpty(uuid)) {
throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_UUID_NULL);
}
// 判断 验证码是否为空
- if(StringUtils.isEmpty(code)){
+ if (StringUtils.isEmpty(code)) {
throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_CODE_NULL);
}
// 验证码
String codeTemp = (String) redisPlugin.get(CacheUtil.getPrefixName() + PREFIX + uuid);
- if(StringUtils.isEmpty(codeTemp)){
+ if (StringUtils.isEmpty(codeTemp)) {
throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_NULL);
}
// 验证 验证码是否正确
boolean captchaFlag = codeTemp.equalsIgnoreCase(code);
- if(!captchaFlag){
+ if (!captchaFlag) {
throw new TokenException(TokenMsg.EXCEPTION_CAPTCHA_ERROR);
}
}
@@ -105,11 +133,12 @@ public class CaptchaUtil{
/**
* 删除验证码
- * @param uuid UUID
- * @return boolean
+ *
+ * @param uuid
+ * @return
*/
public static boolean delCaptcha(String uuid) {
- if(StringUtils.isEmpty(uuid)){
+ if (StringUtils.isEmpty(uuid)) {
return false;
}
@@ -118,16 +147,61 @@ public class CaptchaUtil{
}
-
// ==========================
@Autowired
- public void setRedisPlugin(RedisPlugin redisPlugin) {
+ public void setRedisPlugin(RedisPlugin redisPlugin) {
CaptchaUtil.redisPlugin = redisPlugin;
}
- @Autowired
- public void setProducer(Producer producer) {
- CaptchaUtil.producer = producer;
+
+ // ======================
+
+ public interface CaptchaStrategy{
+
+ /**
+ * 生成验证码对象
+ * @return Captcha
+ */
+ Captcha createCaptcha();
+
}
+
+ /**
+ * 数字英文混合验证码 静态
+ */
+ private static class CaptchaStrategyBySpec implements CaptchaStrategy{
+ @Override
+ public Captcha createCaptcha() {
+ // 生成验证码
+ SpecCaptcha captcha = new SpecCaptcha(CAPTCHA_WIDTH, CAPTCHA_HEIGHT, CAPTCHA_LEN);
+ captcha.setCharType(Captcha.TYPE_DEFAULT);
+ return captcha;
+ }
+ }
+
+ /**
+ * 数字英文混合验证码 动态
+ */
+ private static class CaptchaStrategyByGif implements CaptchaStrategy{
+ @Override
+ public Captcha createCaptcha() {
+ // 生成验证码
+ GifCaptcha captcha = new GifCaptcha(CAPTCHA_WIDTH, CAPTCHA_HEIGHT, CAPTCHA_LEN);
+ captcha.setCharType(Captcha.TYPE_DEFAULT);
+ return captcha;
+ }
+ }
+
+ /**
+ * 算数验证码 动态
+ */
+ private static class CaptchaStrategyByArithmetic implements CaptchaStrategy{
+ @Override
+ public Captcha createCaptcha() {
+ // 生成验证码
+ return new ArithmeticCaptcha(CAPTCHA_WIDTH, CAPTCHA_HEIGHT);
+ }
+ }
+
}
diff --git a/opsli-modulars/opsli-modulars-system/src/main/java/org/opsli/modulars/system/login/web/LoginRestController.java b/opsli-modulars/opsli-modulars-system/src/main/java/org/opsli/modulars/system/login/web/LoginRestController.java
index d2809ce7..9e69e1f9 100644
--- a/opsli-modulars/opsli-modulars-system/src/main/java/org/opsli/modulars/system/login/web/LoginRestController.java
+++ b/opsli-modulars/opsli-modulars-system/src/main/java/org/opsli/modulars/system/login/web/LoginRestController.java
@@ -183,21 +183,13 @@ public class LoginRestController {
*/
@Limiter(alertType = AlertType.ALERT)
@ApiOperation(value = "验证码", notes = "验证码")
- @GetMapping("captcha.jpg")
+ @GetMapping("captcha")
public void captcha(String uuid, HttpServletResponse response) throws IOException {
- response.setHeader("Cache-Control", "no-store, no-cache");
- response.setContentType("image/jpeg");
-
- try {
- //获取图片验证码
- BufferedImage image = CaptchaUtil.getCaptcha(uuid);
- if(image != null){
- ServletOutputStream out = response.getOutputStream();
- ImageIO.write(image, "jpg", out);
- IOUtils.closeQuietly(out);
- }
- }catch (RuntimeException e){
- OutputStreamUtil.exceptionResponse(e.getMessage(), response);
+ ServletOutputStream out = response.getOutputStream();
+ if(out != null){
+ response.setHeader("Cache-Control", "no-store, no-cache");
+ //生成图片验证码
+ CaptchaUtil.createCaptcha(uuid, out);
}
}
diff --git a/pom.xml b/pom.xml
index 60e31b5a..0ad7dcc7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,7 +71,7 @@
3.9.1
4.5.2
3.9.0
- 0.0.9
+ 1.6.2
1.6.0
1.68
@@ -102,14 +102,13 @@
import
-
+
- com.github.axet
- kaptcha
- ${kaptcha.version}
+ com.github.whvcse
+ easy-captcha
+ ${captcha.version}
-
com.auth0