Java实现校验码校验功能

Java实现校验码校验功能逻辑:

首先前端传入一个时间戳,作为唯一标识,然后后端根据时间戳生成一个验证码的图片响应给前端。代码如下:

首先添加一个生成验证码的工具类:

package com.xiaojukeji.it.common.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Properties;
import java.util.Random;

/**
 * 

Description: [验证码生成器]

*/ public class CaptchaUtils { // 图片的宽度。 private int width = 120; // 图片的高度。 private int height = 40; // 验证码字符个数 private int codeCount = 4; // 验证码干扰线数 private int lineCount = 50; // 验证码 private String code = null; // 验证码图片Buffer private BufferedImage buffImg = null; private char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9' }; // 生成随机数 private Random random = new Random(); public CaptchaUtils() { this.createCode(); } /** * * @param width * 图片宽 * @param height * 图片高 */ public CaptchaUtils(int width, int height) { this.width = width; this.height = height; this.createCode(); } /** * * @param width * 图片宽 * @param height * 图片高 * @param codeCount * 字符个数 * @param lineCount * 干扰线条数 */ public CaptchaUtils(int width, int height, int codeCount, int lineCount) { this.width = width; this.height = height; this.codeCount = codeCount; this.lineCount = lineCount; this.createCode(); } public void createCode() { int codeX = 0; int fontHeight = 0; fontHeight = height - 5;// 字体的高度 codeX = width / (codeCount + 3);// 每个字符的宽度 // 图像buffer buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = buffImg.createGraphics(); // 将图像填充为白色 g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); // 创建字体 ImgFontByte imgFont = new ImgFontByte(); // Font font = imgFont.getFont(fontHeight); Font font = getFont(fontHeight); g.setFont(font); // 绘制干扰线 for (int i = 0; i < lineCount; i++) { int xs = getRandomNumber(width); int ys = getRandomNumber(height); int xe = xs + getRandomNumber(width / 8); int ye = ys + getRandomNumber(height / 8); g.setColor(getRandomColor()); g.drawLine(xs, ys, xe, ye); } StringBuffer randomCode = new StringBuffer(); // 随机产生验证码字符 for (int i = 0; i < codeCount; i++) { String strRand = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]); // 设置字体颜色 g.setColor(getRandomColor()); // 设置字体位置 g.drawString(strRand, (i + 1) * codeX, getRandomNumber(height / 2) + 25); randomCode.append(strRand); } code = randomCode.toString(); } /** 获取随机颜色 */ private Color getRandomColor() { int r = getRandomNumber(255); int g = getRandomNumber(255); int b = getRandomNumber(255); return new Color(r, g, b); } /** 获取随机数 */ private int getRandomNumber(int number) { return random.nextInt(number); } public void write(String path) throws IOException { OutputStream sos = new FileOutputStream(path); this.write(sos); } public void write(OutputStream sos) throws IOException { ImageIO.write(buffImg, "JPEG", sos); sos.close(); } public BufferedImage getBuffImg() { return buffImg; } public String getCode() { return code; } /** 字体样式类 */ class ImgFontByte { public Font getFont(int fontHeight) { try { Font baseFont = Font.createFont(Font.TRUETYPE_FONT, new ByteArrayInputStream(hex2byte(getFontByteStr()))); return baseFont.deriveFont(Font.PLAIN, fontHeight); } catch (Exception e) { return new Font("Arial", Font.PLAIN, fontHeight); } } private byte[] hex2byte(String str) { if (str == null) return null; str = str.trim(); int len = str.length(); if (len == 0 || len % 2 == 1) return null; byte[] b = new byte[len / 2]; try { for (int i = 0; i < str.length(); i += 2) { b[i / 2] = (byte) Integer.decode("0x" + str.substring(i, i + 2)).intValue(); } return b; } catch (Exception e) { return null; } } } private String getFontByteStr() { Properties prop = new Properties(); try { BufferedReader in = new BufferedReader(new FileReader("config.properties")); prop.load(in); String property = prop.getProperty("FontByteStr"); in.close(); return property; } catch (Exception e) { e.printStackTrace(); } return null; } private Font getFont(int size) { Random random = new Random(); Font font[] = new Font[2]; //font[0] = new Font("Ravie", Font.PLAIN, size); font[0] = new Font("Antique Olive Compact", Font.PLAIN, size); font[1] = new Font("Fixedsys", Font.PLAIN, size); int nextInt = random.nextInt(2); System.out.println(nextInt); return font[nextInt]; } }

控制类里面添加如下方法,生成验证码并存储到Redis里面(如果项目中没有使用Redis,可以考虑落到数据也行),并响应给前端:

public void getPin(Long timeStamp, HttpServletRequest request, HttpServletResponse response) {
        try {
            if (null == timeStamp) {
                return;
            }
            response.setContentType("image/jpeg");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            CaptchaUtils captcha = new CaptchaUtils();    //生成验证码
            //存入到redis。时间戳,验证码,标识
            redisDB.setAndExpire(timeStamp.toString(), captcha.getCode(), Const.REDIS_USER_CODE);
            captcha.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("获取验证码异常!");
            exceptionService.handler("获取验证码异常", e, request);
        }
    }

前端再次将验证码提交到后台,我们从Redis中取出来进行比较验证。

// redis中查找验证码,图片验证码
            String redisImgCode = redisDB.get(person.getImgTimeStamp());
            // redis中获取不到验证码, 验证码过期
            if (StringUtils.isBlank(redisImgCode)) {
                return AjaxInfo.renderError(AjaxInfo.CODE_PIN_OVERDUE);
            }
            // 判断图片验证码是否正确
            if (StringUtils.isBlank(person.getImgCode()) || !redisImgCode.toLowerCase().equalsIgnoreCase(person.getImgCode().toLowerCase())) {
                redisDB.del(person.getImgCode());
                return AjaxInfo.renderError(AjaxInfo.CODE_PIN_ERROR);
            }

你可能感兴趣的:(Java实现校验码校验功能)