From a71e2e4777b412aef735b7c3d547a502b6990ad9 Mon Sep 17 00:00:00 2001 From: RuoYi <yzz_ivy@163.com> Date: 星期四, 23 七月 2020 10:52:59 +0800 Subject: [PATCH] 验证码类型支持(数组计算、字符验证) --- src/main/java/com/ruoyi/framework/config/CaptchaConfig.java | 83 ++++++++++++++++++++ pom.xml | 14 +++ src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java | 75 ++++++++++++++++++ src/main/resources/application.yml | 2 src/main/java/com/ruoyi/project/common/CaptchaController.java | 65 +++++++++++----- 5 files changed, 219 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index 638c5d9..5f533da 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,7 @@ <commons.fileupload.version>1.3.3</commons.fileupload.version> <bitwalker.version>1.19</bitwalker.version> <jwt.version>0.9.0</jwt.version> + <kaptcha.version>2.3.2</kaptcha.version> <swagger.version>2.9.2</swagger.version> <poi.version>3.17</poi.version> <oshi.version>3.9.1</oshi.version> @@ -243,6 +244,19 @@ </exclusion> </exclusions> </dependency> + + <!--楠岃瘉鐮� --> + <dependency> + <groupId>com.github.penggle</groupId> + <artifactId>kaptcha</artifactId> + <version>${kaptcha.version}</version> + <exclusions> + <exclusion> + <artifactId>javax.servlet-api</artifactId> + <groupId>javax.servlet</groupId> + </exclusion> + </exclusions> + </dependency> </dependencies> diff --git a/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java new file mode 100644 index 0000000..b6f80bf --- /dev/null +++ b/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java @@ -0,0 +1,83 @@ +package com.ruoyi.framework.config; + +import java.util.Properties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import static com.google.code.kaptcha.Constants.*; + +/** + * 楠岃瘉鐮侀厤缃� + * + * @author ruoyi + */ +@Configuration +public class CaptchaConfig +{ + @Bean(name = "captchaProducer") + public DefaultKaptcha getKaptchaBean() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 鏄惁鏈夎竟妗� 榛樿涓簍rue 鎴戜滑鍙互鑷繁璁剧疆yes锛宯o + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂鑹� 榛樿涓篊olor.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); + // 楠岃瘉鐮佸浘鐗囧搴� 榛樿涓�200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 楠岃瘉鐮佸浘鐗囬珮搴� 榛樿涓�50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 楠岃瘉鐮佹枃鏈瓧绗﹀ぇ灏� 榛樿涓�40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂暱搴� 榛樿涓�5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); + // 楠岃瘉鐮佹枃鏈瓧浣撴牱寮� 榛樿涓簄ew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 鍥剧墖鏍峰紡 姘寸汗com.google.code.kaptcha.impl.WaterRipple 楸肩溂com.google.code.kaptcha.impl.FishEyeGimpy 闃村奖com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + @Bean(name = "captchaProducerMath") + public DefaultKaptcha getKaptchaBeanMath() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 鏄惁鏈夎竟妗� 榛樿涓簍rue 鎴戜滑鍙互鑷繁璁剧疆yes锛宯o + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 杈规棰滆壊 榛樿涓篊olor.BLACK + properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂鑹� 榛樿涓篊olor.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); + // 楠岃瘉鐮佸浘鐗囧搴� 榛樿涓�200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 楠岃瘉鐮佸浘鐗囬珮搴� 榛樿涓�50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 楠岃瘉鐮佹枃鏈瓧绗﹀ぇ灏� 榛樿涓�40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); + // 楠岃瘉鐮佹枃鏈敓鎴愬櫒 + properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂棿璺� 榛樿涓�2 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); + // 楠岃瘉鐮佹枃鏈瓧绗﹂暱搴� 榛樿涓�5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); + // 楠岃瘉鐮佹枃鏈瓧浣撴牱寮� 榛樿涓簄ew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 楠岃瘉鐮佸櫔鐐归鑹� 榛樿涓篊olor.BLACK + properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); + // 骞叉壈瀹炵幇绫� + properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); + // 鍥剧墖鏍峰紡 姘寸汗com.google.code.kaptcha.impl.WaterRipple 楸肩溂com.google.code.kaptcha.impl.FishEyeGimpy 闃村奖com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } +} diff --git a/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java b/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java new file mode 100644 index 0000000..e003ce9 --- /dev/null +++ b/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java @@ -0,0 +1,75 @@ +package com.ruoyi.framework.config; + +import java.util.Random; +import com.google.code.kaptcha.text.impl.DefaultTextCreator; + +/** + * 楠岃瘉鐮佹枃鏈敓鎴愬櫒 + * + * @author ruoyi + */ +public class KaptchaTextCreator extends DefaultTextCreator +{ + private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); + + @Override + public String getText() + { + Integer result = 0; + Random random = new Random(); + int x = random.nextInt(10); + int y = random.nextInt(10); + StringBuilder suChinese = new StringBuilder(); + int randomoperands = (int) Math.round(Math.random() * 2); + if (randomoperands == 0) + { + result = x * y; + suChinese.append(CNUMBERS[x]); + suChinese.append("*"); + suChinese.append(CNUMBERS[y]); + } + else if (randomoperands == 1) + { + if (!(x == 0) && y % x == 0) + { + result = y / x; + suChinese.append(CNUMBERS[y]); + suChinese.append("/"); + suChinese.append(CNUMBERS[x]); + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + } + else if (randomoperands == 2) + { + if (x >= y) + { + result = x - y; + suChinese.append(CNUMBERS[x]); + suChinese.append("-"); + suChinese.append(CNUMBERS[y]); + } + else + { + result = y - x; + suChinese.append(CNUMBERS[y]); + suChinese.append("-"); + suChinese.append(CNUMBERS[x]); + } + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + suChinese.append("=?@" + result); + return suChinese.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/ruoyi/project/common/CaptchaController.java b/src/main/java/com/ruoyi/project/common/CaptchaController.java index 9a3af20..68823fc 100644 --- a/src/main/java/com/ruoyi/project/common/CaptchaController.java +++ b/src/main/java/com/ruoyi/project/common/CaptchaController.java @@ -1,15 +1,19 @@ package com.ruoyi.project.common; -import java.io.ByteArrayOutputStream; +import java.awt.image.BufferedImage; import java.io.IOException; import java.util.concurrent.TimeUnit; +import javax.annotation.Resource; +import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.FastByteArrayOutputStream; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; +import com.google.code.kaptcha.Producer; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.utils.IdUtils; -import com.ruoyi.common.utils.VerifyCodeUtils; import com.ruoyi.common.utils.sign.Base64; import com.ruoyi.framework.redis.RedisCache; import com.ruoyi.framework.web.domain.AjaxResult; @@ -22,8 +26,19 @@ @RestController public class CaptchaController { + + @Resource(name = "captchaProducer") + private Producer captchaProducer; + + @Resource(name = "captchaProducerMath") + private Producer captchaProducerMath; + @Autowired private RedisCache redisCache; + + // 楠岃瘉鐮佺被鍨� + @Value("${ruoyi.captchaType}") + private String captchaType; /** * 鐢熸垚楠岃瘉鐮� @@ -31,32 +46,42 @@ @GetMapping("/captchaImage") public AjaxResult getCode(HttpServletResponse response) throws IOException { - // 鐢熸垚闅忔満瀛椾覆 - String verifyCode = VerifyCodeUtils.generateVerifyCode(4); - // 鍞竴鏍囪瘑 + // 淇濆瓨楠岃瘉鐮佷俊鎭� String uuid = IdUtils.simpleUUID(); String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; - redisCache.setCacheObject(verifyKey, verifyCode, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); - // 鐢熸垚鍥剧墖 - int w = 111, h = 36; - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - VerifyCodeUtils.outputImage(w, h, stream, verifyCode); + String capStr = null, code = null; + BufferedImage image = null; + + // 鐢熸垚楠岃瘉鐮� + if ("math".equals(captchaType)) + { + String capText = captchaProducerMath.createText(); + capStr = capText.substring(0, capText.lastIndexOf("@")); + code = capText.substring(capText.lastIndexOf("@") + 1); + image = captchaProducerMath.createImage(capStr); + } + else if ("char".equals(captchaType)) + { + capStr = code = captchaProducer.createText(); + image = captchaProducer.createImage(capStr); + } + + redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); + // 杞崲娴佷俊鎭啓鍑� + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); try { - AjaxResult ajax = AjaxResult.success(); - ajax.put("uuid", uuid); - ajax.put("img", Base64.encode(stream.toByteArray())); - return ajax; + ImageIO.write(image, "jpg", os); } - catch (Exception e) + catch (IOException e) { - e.printStackTrace(); return AjaxResult.error(e.getMessage()); } - finally - { - stream.close(); - } + + AjaxResult ajax = AjaxResult.success(); + ajax.put("uuid", uuid); + ajax.put("img", Base64.encode(os.toByteArray())); + return ajax; } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7e94949..a181e80 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -12,6 +12,8 @@ profile: D:/ruoyi/uploadPath # 鑾峰彇ip鍦板潃寮�鍏� addressEnabled: false + # 楠岃瘉鐮佺被鍨� math 鏁扮粍璁$畻 char 瀛楃楠岃瘉 + captchaType: math # 寮�鍙戠幆澧冮厤缃� server: -- Gitblit v1.9.3