300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 若依前后端分离框架——生成数字验证码功能源码学习

若依前后端分离框架——生成数字验证码功能源码学习

时间:2020-06-13 10:52:34

相关推荐

若依前后端分离框架——生成数字验证码功能源码学习

使用版本:Ruo-Vue 3.8.0

项目地址:/y_project/RuoYi-Vue

0.1:验证码生成流程图

0.2:验证码生成时序图

0.3:验证码的配置项

代码位置:com.google.code.kaptcha.Constants

public class Constants{// session keypublic final static String KAPTCHA_SESSION_KEY = "KAPTCHA_SESSION_KEY";// session datepublic final static String KAPTCHA_SESSION_DATE = "KAPTCHA_SESSION_DATE";public final static String KAPTCHA_SESSION_CONFIG_KEY = "kaptcha.session.key";public final static String KAPTCHA_SESSION_CONFIG_DATE = "kaptcha.session.date";// 是否有边框 默认为true 我们可以自己设置yes,nopublic final static String KAPTCHA_BORDER = "kaptcha.border";// 边框颜色 默认为Color.BLACKpublic final static String KAPTCHA_BORDER_COLOR = "kaptcha.border.color";// 边框宽度public final static String KAPTCHA_BORDER_THICKNESS = "kaptcha.border.thickness";// 验证码噪点颜色 默认为Color.BLACKpublic final static String KAPTCHA_NOISE_COLOR = "kaptcha.noise.color";// 干扰实现类public final static String KAPTCHA_NOISE_IMPL = "kaptcha.noise.impl";// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpypublic final static String KAPTCHA_OBSCURIFICATOR_IMPL = "kaptcha.obscurificator.impl";// 图片实现类public final static String KAPTCHA_PRODUCER_IMPL = "kaptcha.producer.impl";// 验证码文本生成器public final static String KAPTCHA_TEXTPRODUCER_IMPL = "kaptcha.textproducer.impl";// 文本集合,验证码值从此集合中获取public final static String KAPTCHA_TEXTPRODUCER_CHAR_STRING = "kaptcha.textproducer.char.string";// 验证码文本字符长度 默认为5public final static String KAPTCHA_TEXTPRODUCER_CHAR_LENGTH = "kaptcha.textproducer.char.length";// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)public final static String KAPTCHA_TEXTPRODUCER_FONT_NAMES = "kaptcha.textproducer.font.names";// 验证码文本字符颜色 默认为Color.BLACKpublic final static String KAPTCHA_TEXTPRODUCER_FONT_COLOR = "kaptcha.textproducer.font.color";// 验证码文本字符大小 默认为40public final static String KAPTCHA_TEXTPRODUCER_FONT_SIZE = "kaptcha.textproducer.font.size";// 验证码文本字符间距 默认为2public final static String KAPTCHA_TEXTPRODUCER_CHAR_SPACE = "kaptcha.textproducer.char.space";// 文字渲染public final static String KAPTCHA_WORDRENDERER_IMPL = "kaptcha.word.impl";// 背景实现类public final static String KAPTCHA_BACKGROUND_IMPL = "kaptcha.background.impl";// 背景颜色渐变,开始颜色public static final String KAPTCHA_BACKGROUND_CLR_FROM = "kaptcha.background.clear.from";// 背景颜色渐变,结束颜色public static final String KAPTCHA_BACKGROUND_CLR_TO = "kaptcha.background.clear.to";// 验证码图片宽度 默认为200public static final String KAPTCHA_IMAGE_WIDTH = "kaptcha.image.width";// 验证码图片高度 默认为50public static final String KAPTCHA_IMAGE_HEIGHT = "kaptcha.image.height";}

1:获取验证码的入口

代码位置:com.ruoyi.mon.CaptchaController#getCode

@Resource(name = "captchaProducer")private Producer captchaProducer;@Resource(name = "captchaProducerMath")private Producer captchaProducerMath;@Autowiredprivate RedisCache redisCache;@Autowiredprivate ISysConfigService configService;/*** 生成验证码*/@GetMapping("/captchaImage")public AjaxResult getCode(HttpServletResponse response) throws IOException{// 是否需要生成验证码AjaxResult ajax = AjaxResult.success();// boolean captchaOnOff = configService.selectCaptchaOnOff();ajax.put("captchaOnOff", captchaOnOff);if (!captchaOnOff){return ajax;}String uuid = IdUtils.simpleUUID();String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;String capStr = null, code = null;BufferedImage image = null;// 生成验证码String captchaType = RuoYiConfig.getCaptchaType();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);}// 保存验证码到redisredisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);// 构造需要返回的数据FastByteArrayOutputStream os = new FastByteArrayOutputStream();try{ImageIO.write(image, "jpg", os);}catch (IOException e){return AjaxResult.error(e.getMessage());}ajax.put("uuid", uuid);ajax.put("img", Base64.encode(os.toByteArray()));return ajax;}

这里重点研究如何生成验证码

String captchaType = RuoYiConfig.getCaptchaType();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);}

以下是对自定义生成验证码类进行分析

1.1:自定义captchaProducerMath

代码位置:com.ruoyi.framework.config.CaptchaConfig#getKaptchaBeanMath

@Bean(name = "captchaProducerMath")public DefaultKaptcha getKaptchaBeanMath(){DefaultKaptcha defaultKaptcha = new DefaultKaptcha();Properties properties = new Properties();// 是否有边框 默认为true 我们可以自己设置yes,noproperties.setProperty(KAPTCHA_BORDER, "yes");// 边框颜色 默认为Color.BLACKproperties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");// 验证码文本字符颜色 默认为Color.BLACKproperties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");// 验证码图片宽度 默认为200properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");// 验证码图片高度 默认为50properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");// 验证码文本字符大小 默认为40properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");// KAPTCHA_SESSION_KEYproperties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");// 验证码文本生成器【1】properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator");// 验证码文本字符间距 默认为2properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");// 验证码文本字符长度 默认为5properties.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.BLACKproperties.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.ShadowGimpyproperties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");Config config = new Config(properties);//【2】defaultKaptcha.setConfig(config);return defaultKaptcha;}

【1】这里使用了自定义的验证码文本生成器,以下为自定义的验证码文本生成器的源码【2】在这里使用反射的方式将自定义的文本生成器反射到DefaultKaptcha里

1.2:自定义的文本生成器

代码位置:com.ruoyi.framework.config.KaptchaTextCreator

/*** 验证码文本生成器* * @author ruoyi*/// 【1】public class KaptchaTextCreator extends DefaultTextCreator{private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");@Overridepublic String getText(){Integer result = 0;Random random = new Random();int x = random.nextInt(10);int y = random.nextInt(10);StringBuilder suChinese = new StringBuilder();// 【2】int randomoperands = (int) Math.round(Math.random() * 2);if (randomoperands == 0){// 【3】result = x * y;suChinese.append(CNUMBERS[x]);suChinese.append("*");suChinese.append(CNUMBERS[y]);}else if (randomoperands == 1){// 【4】if (!(x == 0) && y % x == 0){// 【5】result = y / x;suChinese.append(CNUMBERS[y]);suChinese.append("/");suChinese.append(CNUMBERS[x]);}else{// 【6】result = x + y;suChinese.append(CNUMBERS[x]);suChinese.append("+");suChinese.append(CNUMBERS[y]);}}else if (randomoperands == 2){// 【7】if (x >= y){// 【8】result = x - y;suChinese.append(CNUMBERS[x]);suChinese.append("-");suChinese.append(CNUMBERS[y]);}else{// 【9】result = y - x;suChinese.append(CNUMBERS[y]);suChinese.append("-");suChinese.append(CNUMBERS[x]);}}else{// 【10】result = x + y;suChinese.append(CNUMBERS[x]);suChinese.append("+");suChinese.append(CNUMBERS[y]);}suChinese.append("=?@" + result);return suChinese.toString();}}

【1】:需要继承DefaultTextCreator类【2】:Math.round会取到最接近的整数,所以Math.round(Math.random() * 2)的结果只会是0、1、2【3】【4】【7】【10】:做了一个小测试,这四个分支的的占比大约是25:50:25:0【5】【6】:这两个分支的占比大约是16:34【8】【9】:这两个分支的占比大约是14:11

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。