pom文件中引入DefaultKaptcha的依赖
<dependency>
                <groupId>com.github.penggle</groupId>
                <artifactId>kaptcha</artifactId>
                <version>2.3.2</version>
            </dependency>

Kaptcha 是一个可高度配置的实用验证码生成工具,可自由配置的选项如

  • 验证码的字体
  • 验证码字体的大小
  • 验证码字体的字体颜色
  • 验证码内容的范围(数字,字母,中文汉字!)
  • 验证码图片的大小,边框,边框粗细,边框颜色
  • 验证码的干扰线
  • 验证码的样式(鱼眼样式、3D、普通模糊、…)

CaptchaConfig类中配置验证码相关的参数(字符验证码)

若依 springsecurity 手机验证码登录_mybatis


若依的配置文件在这里

若依 springsecurity 手机验证码登录_缓存_02


若依的验证码操作处理

若依 springsecurity 手机验证码登录_缓存_03


若依 springsecurity 手机验证码登录_java_04


提供了一个 getCode() 方法,用于生成验证码图片并将验证码信息保存到 Redis 缓存中。

若依 springsecurity 手机验证码登录_java_05


首先判断是否启用了验证码功能,如果没有启用则直接返回一个 AjaxResult 对象,其中包含 captchaEnabled 字段(bool 类型),值为 false。

若依 springsecurity 手机验证码登录_java_06


若依 springsecurity 手机验证码登录_mybatis_07


如果启用了验证码,则生成一个随机的 uuid 并将其作为验证码存储的 key,将验证码的值作为 value 存储到 Redis 缓存中,同时将验证码图片以 base64 格式返回给前端。

/**
 * 验证码操作处理
 * 
 * @author core
 */
@RestController
public class CaptchaController
{
    @Resource(name = "captchaProducer")
    private Producer captchaProducer; // 验证码生成器,用于生成字符验证码图片
    //自动装配 Spring 框架的相关注解(例如 @RestController、@Resource、@Autowired),这些注解在程序启动时会被解析,在需要时自动创建对象并注入依赖。
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath; // 验证码生成器,用于生成数学计算验证码图片

    @Autowired
    private RedisCache redisCache; // Redis 缓存服务,用于保存验证码信息
    
    @Autowired
    private ISysConfigService configService;   // 配置服务,用于获取是否启用验证码等信息
    /**
     * 生成验证码图片
     * @param response HTTP 响应对象
     * @throws IOException IO 异常
     */
    @GetMapping("/captchaImage")
    public AjaxResult getCode(HttpServletResponse response) throws IOException
    {
        AjaxResult ajax = AjaxResult.success(); // 创建 AjaxResult 对象,用于封装返回到前端的数据
        boolean captchaEnabled = configService.selectCaptchaEnabled();  // 获取是否启用验证码
        ajax.put("captchaEnabled", captchaEnabled);  // 将是否启用验证码的值保存到 AjaxResult 对象中,以返回到前端
        if (!captchaEnabled) // 如果未启用验证码,直接返回 AjaxResult 对象
        {
            return ajax;
        }

        // 生成验证码信息
        String uuid = IdUtils.simpleUUID();    // 随机生成 UUID 作为 Key
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; // 构造验证码 Key,用于在缓存中保存验证码信息

        String capStr = null, code = null; // 验证码字符串和验证码值
        BufferedImage image = null; // 验证码图片

        // 生成验证码图片和验证码值
        String captchaType = CoreConfig.getCaptchaType(); // 获取验证码类型,可选值有:"char" 和 "math"
        if ("math".equals(captchaType)) // 如果验证码类型为数学计算类型
        {
            String capText = captchaProducerMath.createText();  // 生成一个包含数学计算公式的验证码字符串
//            System.out.println(capText);
//            4-2=?@2
            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); // 将验证码信息存储到缓存中,验证码 Key 为 verifyKey,验证码值为 code
        // 转换验证码图片流,并以 base64 格式返回
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try
        {
            ImageIO.write(image, "jpg", os);
        }
        catch (IOException e)
        {
            return AjaxResult.error(e.getMessage());
        }

        ajax.put("uuid", uuid); // 将 UUID 作为 'uuid' 键保存到 AjaxResult 中,以返回到前端
        ajax.put("img", Base64.encode(os.toByteArray()));// 将验证码图片的 base64 编码保存到 'img' 键中,以返回到前端
        return ajax;
    }
}

前端页面利用Img标签的src属性,根据Base64编码格式数据获取验证码图片显示。

// 获取验证码方法
    getCode() {
      getCodeImg().then(res => {
          this.codeUrl = "data:image/gif;base64," + res.img;
          this.loginForm.uuid = res.uuid;
      });
    },
<!-- 利用img标签,src属性根据Base64编码格式数据来获取验证码图。 -->
    <div class="login-code">
        <img :src="codeUrl" @click="getCode" class="login-code-img"/>
    </div>

校验验证码

若依 springsecurity 手机验证码登录_mybatis_08

public void validateCaptcha(String username, String code, String uuid)
    {
        boolean captchaEnabled = configService.selectCaptchaEnabled();  // 获取是否启用验证码
        if (captchaEnabled) {   // 如果启用验证码
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");  // 构建缓存中验证码的 key
            String captcha = redisCache.getCacheObject(verifyKey);  // 从缓存中获取验证码信息
            redisCache.deleteObject(verifyKey);    // 从缓存中删除验证码信息
            if (captcha == null) {  // 如果验证码信息为空
                // 记录登录失败日志,并抛出 CaptchaExpireException 异常,表示验证码过期
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
                throw new CaptchaExpireException();
            }
            if (!code.equalsIgnoreCase(captcha)) { // 如果用户输入的验证码与缓存中的验证码不匹配
                // 记录登录失败日志,并抛出 CaptchaException 异常,表示验证码错误
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
                throw new CaptchaException();
            }
        }
    }

以上就是若依框架生成验证码的功能以及校验过程。