对若依框架的步骤解读之生成验证码

目录

 1.验证码的实现过程

        1.1代码需要引入的依赖:

        1.2代码所在的包:

        1.3代码的映射路径以及方法名称:

       1.4代码的深入逻辑:

                1.4.1:检查验证码开关

                1.4.2:保存验证码:


 1.验证码的实现过程

        1.1代码需要引入的依赖:

<dependency>
             <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>javax.servlet-api</artifactId>
                    <groupId>javax.servlet</groupId>
                </exclusion>
            </exclusions>
 </dependency>

        1.2代码所在的包:

package com.ruoyi.web.controller.common;

        1.3代码的映射路径以及方法名称:

@GetMapping("/captchaImage")
    public AjaxResult getCode(HttpServletResponse response) throws IOException{
}

       1.4代码的深入逻辑:

                1.4.1:检查验证码开关

boolean captchaEnabled = configService.selectCaptchaEnabled();
selectCaptchaEnabled():检查验证码开关 -true:开 -false:关

通过selectCaptchaEnabled()方法中的

selectConfigByKey(String configKey)

在调用redisCache.getCacheObject(getCacheKey(configKey)),可以获取到在reids缓存的对应的value值。其中有两种情况:

第一种:从redis成功获取到了value值:

     /**
     * 在redis中储存验证码的形式为:sys_config:sys.account.captchaEnabled :true
     * 或者sys_config:sys.account.captchaEnabled :false 这种形式
     */
String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));



 private String getCacheKey(String configKey)
    {
        //在redis中储存验证码的key为:sys_config:sys.account.captchaEnabled 
        return CacheConstants.SYS_CONFIG_KEY + configKey;
    }

第二种(redis获取失败,从mysql获取):

if (StringUtils.isNotEmpty(configValue))
        {
             //找到value直接返回  
            return configValue;
        }
            SysConfig config = new SysConfig();
            config.setConfigKey(configKey);
            SysConfig retConfig = configMapper.selectConfig(config);
            if (StringUtils.isNotNull(retConfig)){
            redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
            return retConfig.getConfigValue();
            }           

在mysql查找时,设置了自定义的SysConfigMapper.xml文件, 并在 sys_config 表中根据 configKey来查找对应的value。

若返回结果不为null:则将对应的key和value 存入redis缓存中,即:key: sys_config:sys.account.captchaEnabled -> value: true(false);

若返回结果为null: 则返回结果为“” (空字符串),在利用Convert.toBool(captchaEnabled)返回boolean类型的值。

补充: 

 String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled");
        //假如redis缓存查不到,则开启验证码,保证安全性
        if(StringUtils.isEmpty(captchaEnabled)){
            return true;
        }

 从上述代码我们可以看出,假如查找完验证码为空,则返回null,也就是说假如验证码未设置开和关(yes or no || 1 or 0)这种关系,则默认是开启的,目的是保证了安全性。

通俗的讲:除非我明确在redis或者mysql表示了我的验证码状态时关闭的,否则都是开启的状态。

                1.4.2:保存验证码:

//生成key 形式为:captcha_codes: 随机生成的uuid
String uuid = IdUtils.simpleUUID();
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
@ConfigurationProperties(prefix = "ruoyi")

根据配置文件中前缀为“ruoyi”来获取属性值

在application.yml中表现为:

ruoyi:

        captchaType: math

其中captchaType属性可以又两个值:1.math 数字验证码 2.char 字符验证码 

若为math,则:

String capText = captchaProducerMath.createText();
//createText()中会调用getText()方法


private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");

    public String getText()
    {
        Integer result = 0;
        Random random = new Random();
        //x和y的值都是10以内随机数
        int x = random.nextInt(10);
        int y = random.nextInt(10);
        StringBuilder suChinese = new StringBuilder();
        //randomoperands的值为3以内的随机数,randomoperands的作用是随机分配乘、除、加、减四个算法
        int randomoperands = random.nextInt(3);
        if (randomoperands == 0)
        {
            //在此就解释一个,一下可以类推
            //suChinese会拼接上x和y的值 也就是这种形式:例如x = 3,y = 4;则为: 3 * 4
            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 (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]);
            }
        }
        //suChinese继续拼接=?@,拼接后最后形式为: 3 * 4 =?@12
        suChinese.append("=?@" + result);
        //最后返回的就是拼接的最后结果:3 * 4 =?@12
        return suChinese.toString();
    }

后续利用

//将结果中的@符号去掉。变成 3 * 4 =?这种形式
capStr = capText.substring(0, capText.lastIndexOf("@"));
//截取结果 3 * 4 =?12 ,最后变成算式结果12
code = capText.substring(capText.lastIndexOf("@") + 1);
//生成图片验证码
image = captchaProducerMath.createImage(capStr);

最后将生成的验证码放入redis缓存中,并设置默认的过期时间

 verifyKey:captcha_codes: 随机生成的uuid code:最后算式的结果 Constants.CAPTCHA_EXPIRATION:过期时间 默认为两分钟
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION,TimeUnit.MINUTES);

转换流信息将image写出

FastByteArrayOutputStream os = new FastByteArrayOutputStream();
            try
            {
                ImageIO.write(image, "jpg", os);
            }
            catch (IOException e)
            {
                return AjaxResult.error(e.getMessage());
            }

将uuid和image放入ajax中返回给前端

ajax.put("uuid", uuid);
//通过base64将流转换成字节数组
ajax.put("img", Base64.encode(os.toByteArray()));

综上所述:

        ajax所携带的信息有五个:

                1.验证码开关状态:-true 或者 -false

                2.uuid 唯一标识

                3.image 验证码的.jpg图片

                4.msg 返回信息:操作成功

                5.code 状态码:200

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值