RuoYi
2020-07-23 a71e2e4777b412aef735b7c3d547a502b6990ad9
验证码类型支持(数组计算、字符验证)
已修改3个文件
已添加2个文件
239 ■■■■■ 文件已修改
pom.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/CaptchaConfig.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/common/CaptchaController.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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>
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();
        // æ˜¯å¦æœ‰è¾¹æ¡† é»˜è®¤ä¸ºtrue æˆ‘们可以自己设置yes,no
        properties.setProperty(KAPTCHA_BORDER, "yes");
        // éªŒè¯ç æ–‡æœ¬å­—符颜色 é»˜è®¤ä¸ºColor.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");
        // éªŒè¯ç æ–‡æœ¬å­—体样式 é»˜è®¤ä¸ºnew 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();
        // æ˜¯å¦æœ‰è¾¹æ¡† é»˜è®¤ä¸ºtrue æˆ‘们可以自己设置yes,no
        properties.setProperty(KAPTCHA_BORDER, "yes");
        // è¾¹æ¡†é¢œè‰² é»˜è®¤ä¸ºColor.BLACK
        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
        // éªŒè¯ç æ–‡æœ¬å­—符颜色 é»˜è®¤ä¸ºColor.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");
        // éªŒè¯ç æ–‡æœ¬å­—体样式 é»˜è®¤ä¸ºnew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
        // éªŒè¯ç å™ªç‚¹é¢œè‰² é»˜è®¤ä¸ºColor.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;
    }
}
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();
    }
}
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;
    }
}
src/main/resources/application.yml
@@ -12,6 +12,8 @@
  profile: D:/ruoyi/uploadPath
  # èŽ·å–ip地址开关
  addressEnabled: false
  # éªŒè¯ç ç±»åž‹ math æ•°ç»„计算 char å­—符验证
  captchaType: math
# å¼€å‘环境配置
server: