天天看点

五分钟带你玩转SpringSecurity(十一)全网最全!带你掌握随机颜色与计算方式的验证码

上文我们使用Kaptcha定制验证码 ,但是样式有些low,甚至很难看清。测试的小伙伴纷纷抗议。。。

解决方案:1:定制验证码的样式,如字体,字号,间隔,颜色等

                  2:使用数字运算代替字母

之前的验证码

五分钟带你玩转SpringSecurity(十一)全网最全!带你掌握随机颜色与计算方式的验证码
更改后的验证码
五分钟带你玩转SpringSecurity(十一)全网最全!带你掌握随机颜色与计算方式的验证码
废话不多说 上代码:

KaptchaImageCodeConfig

Kaptcha配置 重点代码为properties.setProperty("kaptcha.textproducer.impl", "com.core.code.KaptchaTextCreator"); 含义是指定生成验证码的逻辑

@Configuration
public class KaptchaImageCodeConfig {
 
    @Bean
    public DefaultKaptcha getDefaultKaptcha() {
        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");
        // 验证码图片宽度 默认为200
        properties.setProperty("kaptcha.image.width", "200");
        // 验证码图片高度 默认为50
        properties.setProperty("kaptcha.image.height", "36");
        // 验证码文本字符颜色 默认为Color.BLACK
        properties.setProperty("kaptcha.textproducer.font.color", "red");
        // 验证码文本字符大小 默认为40
        properties.setProperty("kaptcha.textproducer.font.size", "36");
        // 验证码文本生成器(生成验证码规则类的位置) 重点!!!!
        properties.setProperty("kaptcha.textproducer.impl", "com.core.code.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", "彩云,宋体,楷体,微软雅黑");
        // 验证码噪点颜色 默认为Color.BLACK
        properties.setProperty("kaptcha.noise.color", "white");
        Config config = new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}      

KaptchaTextCreator

也就是上文对应的验证码逻辑类,该类的逻辑为 生成10以内的运算

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();
    }
}      

CustomCreatImage

当传入验证码之后,随机生成每个字符的颜色,样式。

@Component
public class CustomCreatImage {
 
    private static final long serialVersionUID = 1L;
 
    //给定范围获得随机颜色
    public Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > 255) {
            fc = 255;
        }
        if (bc > 255) {
            bc = 255;
        }
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }
 
    public BufferedImage creatImage(String code) {
        int width = 200, height = 40;
        //生成随机类
        Random random = new Random();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //获取图形上下文
        Graphics g = image.getGraphics();
        // 设定背景色
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, width, height);
        //设定字体 第二个参数为字体为加粗
        g.setFont(new Font("Times New Roman", Font.BOLD, 45));
        // 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
        g.setColor(getRandColor(160, 200));
        for (int i = 0; i < 155; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }
        // 取随机产生的认证码(4位数字)
        for (int i = 0; i < code.length(); i++) {
            String rand = code.substring(i, i + 1);
            // 将认证码显示到图象中
            g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
            //调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
            g.drawString(rand, 30 * i + 18, 35);
        }
        // 图象生效
        g.dispose();
        return image;
    }
}      

CodeController

验证码调用的接口

@Controller
public class CodeController {
 
    Logger logger = LoggerFactory.getLogger(getClass());
 
    @Autowired
    CustomCreatImage customCreatImage;
 
    @Autowired
    private DefaultKaptcha defaultKaptcha;
 
    @RequestMapping("/code/image")
    public void imageCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1. 获取验证码
        String capStr = null;
        String code = null;
        //此处调用的是KaptchaTextCreator规则
        String capText = defaultKaptcha.createText();
        // 显示的验证码
        capStr = capText.substring(0, capText.lastIndexOf("@"));
        // 运算结果
        code = capText.substring(capText.lastIndexOf("@") + 1);
        logger.info("生成的图形验证码是:" + code);
        // 2. 字符串把它放到session中
        request.getSession().setAttribute(CODE_SESSION_KEY, code);
        // 3. 获取验证码图片
        BufferedImage image = customCreatImage.creatImage(capStr);
        // 4. 将验证码图片把它写出去
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(image, "jpg", out);
    }
}      

继续阅读