验证码校验

代码以SpringBoot+ThymeLeaf为例

验证码校验基本都是套路操作,各种工具用法都大差不差.记住套路即可

验证码工具类源代码会放在文章最后.

JavaWeb实现验证码校验

1.下载验证码生成工具(源代码在文章最后),再放入项目中

2.HTML代码

验证码 : <img th:src="@{/verifyCode}" onclick="this.src='/verifyCode?d=' + Math.random()"/>
输入验证码 : <input name="verifyText" type="text">
<!--在form表单中-->
<!--点击事件中,src记得加上随机数防止缓存-->

3.Controller层写法

//自动注入验证码生成工具,不要忘了在工具类上加@Component
@Autowired
VerifyCode vc;

//........其他代码

@RequestMapping("/verifyCode")
public void verifyCode(HttpServletRequest request, HttpServletResponse response) throws IOException{

    //response设置禁止缓存
    response.setHeader("Cache-Control", "no-store");
    response.setHeader("Pragma", "no-cache");
    response.setDateHeader("Expires", 0);
    response.setContentType("image/jpeg");
    //byte数组和两种输出流
    byte[] imageByte;
    ByteArrayOutputStream bytesOutputStream = null;
    ServletOutputStream responseOutputStream = null;
    //先获取图像,再获取验证码(顺序不要错)
    BufferedImage image = vc.getImage();
    String verifyText = vc.getText();
    verifyText.toUpperCase();
    //把文本写入Session
    request.getSession().setAttribute("verifyText", verifyText);
    try{
        //创建ByteArrayOutputStream和ResponseOutputStream
        bytesOutputStream = new ByteArrayOutputStream();
        responseOutputStream = response.getOutputStream();
        //把验证码图像写入bytes输出流
        ImageIO.write(image, "JPEG", bytesOutputStream);
        //获取byte数组
        imageByte = bytesOutputStream.toByteArray();
        //将byte数组写入reponse输出流
        responseOutputStream.write(imageByte);
        responseOutputStream.flush();
    }finally{
        //关闭输出流
        responseOutputStream.close();
        bytesOutputStream.close();
    }

}

  注意 : 不要设置跳转地址,原路返回即可!

4.注册账号的Controller

@RequestMapping("/createUser")
public String createUser(User user, String verifyText, Model m, HttpServletRequest request){
    //校验验证码
    HttpSession session = request.getSession();
    String vfText_session = (String)session.getAttribute("verifyText");
    verifyText.toUpperCase();
    if(!vfText_session.equals(verifyText)){
        m.addAttribute("info", "验证码错误");
        return "regist";
    }else{
        session.removeAttribute("verifyText");
    }
    //注册流程省略......
}

至此就完成了验证码校验

BufferedImage类和ImageIO类

 BufferedImage :

  用于在内存中保存图片

  验证码工具生成的图像就是一个BufferedImage对象,

ImageIO : 

  public static boolean write(RenderedImage im, String formatName, OutputStream output)

  给write()方法传入(BufferedImage对象, 图像格式,  ByteArrayOutputStream输出流),

  把图像写入到ByteArrayOutputStream输出流中,在用ByteArrayOutputStream的toByteArray()方法

  得到byte数组,再把byte数组写入到reponse的输出流中就完事了!

验证码生成工具源码

我这次练习中使用的是

package com.jy.test.utils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
@Component
public class VerifyCode {
    private int w = 70;
    private int h = 35;
    private Random r = new Random();
    // {"宋体", "华文楷体", "黑体", "华文新魏", "华文隶书", "微软雅黑", "楷体_GB2312"}
    private String[] fontNames  = {"宋体", "华文楷体", "黑体", "微软雅黑", "楷体_GB2312"};
    // 可选字符
    private String codes  = "0123456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ";
    // 背景色
    private Color bgColor  = new Color(255, 255, 255);
    // 验证码上的文本
    private String text ;

    // 生成随机的颜色
    private Color randomColor () {
        int red = r.nextInt(150);
        int green = r.nextInt(150);
        int blue = r.nextInt(150);
        return new Color(red, green, blue);
    }

    // 生成随机的字体
    private Font randomFont () {
        int index = r.nextInt(fontNames.length);
        String fontName = fontNames[index];//生成随机的字体名称
        int style = r.nextInt(4);//生成随机的样式, 0(无样式), 1(粗体), 2(斜体), 3(粗体+斜体)
        int size = r.nextInt(5) + 24; //生成随机字号, 24 ~ 28
        return new Font(fontName, style, size);
    }

    // 画干扰线
    private void drawLine (BufferedImage image) {
        int num  = 3;//一共画3条
        Graphics2D g2 = (Graphics2D)image.getGraphics();
        for(int i = 0; i < num; i++) {//生成两个点的坐标,即4个值
            int x1 = r.nextInt(w);
            int y1 = r.nextInt(h);
            int x2 = r.nextInt(w);
            int y2 = r.nextInt(h);
            g2.setStroke(new BasicStroke(1.5F));
            g2.setColor(Color.BLUE); //干扰线是蓝色
            g2.drawLine(x1, y1, x2, y2);//画线
        }
    }

    // 随机生成一个字符
    private char randomChar () {
        int index = r.nextInt(codes.length());
        return codes.charAt(index);
    }

    // 创建BufferedImage
    private BufferedImage createImage () {
        BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = (Graphics2D)image.getGraphics();
        g2.setColor(this.bgColor);
        g2.fillRect(0, 0, w, h);
        return image;
    }

    // 调用这个方法得到验证码
    public BufferedImage getImage () {
        BufferedImage image = createImage();//创建图片缓冲区
        Graphics2D g2 = (Graphics2D)image.getGraphics();//得到绘制环境
        StringBuilder sb = new StringBuilder();//用来装载生成的验证码文本
        // 向图片中画4个字符
        for(int i = 0; i < 4; i++)  {//循环四次,每次生成一个字符
            String s = randomChar() + "";//随机生成一个字母
            sb.append(s); //把字母添加到sb中
            float x = i * 1.0F * w / 4; //设置当前字符的x轴坐标
            g2.setFont(randomFont()); //设置随机字体
            g2.setColor(randomColor()); //设置随机颜色
            g2.drawString(s, x, h-5); //画图
        }
        this.text = sb.toString(); //把生成的字符串赋给了this.text
        drawLine(image); //添加干扰线
        return image;
    }

    // 返回验证码图片上的文本
    public String getText () {
        return text;
    }

    // 保存图片到指定的输出流
    public static void output (BufferedImage image, OutputStream out)
            throws IOException {
        ImageIO.write(image, "JPEG", out);
    }
}

  

以上

f

原文地址:https://www.cnblogs.com/jinyu59/p/10837114.html