Java生成图形验证码,并传输至前端

前段时间想要做一个登录的验证码功能,在网上查找了许多资料后实现了,在此记录并巩固一下,其实原理很简单,就是让Java来充当“画笔的角色”来绘制图片,并将图片通过二进制流的方式传输至前端即可,废话不多说上代码

1.使用Java绘制图片

package com.wzh.util;

import lombok.Data;


import java.awt.*;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * @author Wzh
 * @date 2019/1/10
 */
@Data
public class IdentifyCode {


    private String code;
    private Graphics g;

    /**
     * 获取随机生成的颜色
     * @param s
     * @param e
     * @return
     */
    public Color getRandColor(int s,int e){

        Random random = new Random();
        if (s>255){
            s = 91;
        }
        if (e>255){
            e = 97;
        }

        int r,g,b;
        r = s+random.nextInt(e-s);
        g = s+random.nextInt(e-s);
        b = s+random.nextInt(e-s);
        return new Color(r,g,b);

    }

    /**
     * 获取验证码图片
     */
    public BufferedImage getIdentifyImg(){

        int width = 100;
        int height = 28;
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        //创建Graphics对象,相当于画笔
        Graphics g = image.getGraphics();
        //创建Graphics2D对象
        Graphics2D g2d = (Graphics2D) g;
        Random random = new Random();
        //定义字体样式
        Font font = new Font("华文宋体", Font.BOLD,19);
        g.setColor(this.getRandColor(200,250));
        g.fillRect(0,0,width,height);
        g.setFont(font);
        g.setColor(this.getRandColor(180,200));

        //绘制100条颜色和位置全部随机的线条 该线条为2f
        for (int i = 0;i<100;i++){
            int x = random.nextInt(width-1);
            int y =random.nextInt(height-1);
            int x1 = random.nextInt(6)+1;
            int y1 =random.nextInt(12)+1;
            //绘制线条样式
            BasicStroke bs = new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL);
            Line2D line = new Line2D.Double(x,y,x1+x,y1+y);
            g2d.setStroke(bs);
            g2d.draw(line);

        }

        //输出由英文中文数字随机组成的验证码
        String sRand = "";
        String ctmp = "";
        int itmp = 0;
        for (int i=0;i<4;i++){
            switch(random.nextInt(3)){
                case 1:
                    itmp = random.nextInt(26)+65;
                    ctmp = String.valueOf((char)itmp);
                    break;
                case 2:
                    itmp = random.nextInt(26)+65;
                    ctmp = String.valueOf((char)itmp);
                    break;
                default:
                    itmp = random.nextInt(10)+48;
                    ctmp = String.valueOf((char)itmp);
                    break;
            }
            sRand+=ctmp;
            Color color = new Color(20+random.nextInt(110),20+random.nextInt(110),random.nextInt(110));
            g.setColor(color);
            g.drawString(ctmp,19*i+19,19);
        }
        this.setCode(sRand);
        this.setG(g);
        return image;
    }
}

需要提醒一下的是上面代码中使用了lombok工具,如果没有的话请自行添加变量的get 和set方法

2.传输图片IO流至前端

/**
     * 生成随机验证码图片
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/identifyCode/img")
    public void getIdentifyImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //设置不缓存图片
        response.setHeader("Pragma","No-cache");
        response.setHeader("Cache-Control","No-cache");
        response.setDateHeader("Expires",0);
        //指定生成的响应图片
        response.setContentType("image/jpeg");
        IdentifyCode ic = new IdentifyCode();
        BufferedImage image = ic.getIdentifyImg();
        HttpSession session = request.getSession(true);
        //存储验证码数据到Session中
        session.setAttribute("IdentifyCode",ic.getCode());
        ic.getG().dispose();
        //将图形验证码IO流传输至前端
        ImageIO.write(image,"JPEG",response.getOutputStream());
    }

在前端页面使用标签接收

<img src="../identifyCode/img">

3.题外话

需要注意的是因为服务器session和前端页面存在着异步,所以我们验证码的校对需要通过请求放到后台来进行,下面附上效果图

Java生成图形验证码,并传输至前端