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和前端页面存在着异步,所以我们验证码的校对需要通过请求放到后台来进行,下面附上效果图