代码以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