Java生成图形验证码与前端输入验证
在刷牛客时,遇到了关于web表单登陆中图形验证码实现的问题,所以试着将其编码实现。后端使用springboot,前端使用react。实现的基本思路是:由服务器端生成验证码后通过图片将验证码返回给前台,同时在服务器端保存文本的验证码,由服务端验证输入内容是否正确,并将验证结果返回给前台。
1.java实现生成图形验证码
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.io.IOException;
import java.util.Random;
public class valiPhoto {
//图片的宽度
private int width = 150;
//图片的高度
private int height = 50;
//每张图片验证码字符的个数
private int charnum = 5;
//验证码干扰线
private int linenum = 100;
//验证码
private Stringvalicode = "";
//创建一个BufferedImage对象,可访问图像数据缓冲区,利用缓冲区
//操作图片
private BufferedImageimg = null;
//验证码字符取值范围,去除‘0(数字0)’和‘O(字母)’
private char[]charrange = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
public valiPhoto(int width,int height){
this.width = width;
this.height = height;
this.makeValiPho();
}
public valiPhoto(int width,int height,int charnum,int linenum){
this.width = width;
this.height = height;
this.charnum = charnum;
this.linenum = linenum;
this.makeValiPho();
}
public void makeValiPho(){
int x = 0,fontHeight = 0,charBline = 0;
int red = 0,green = 0,blue = 0;
x = width / (charnum + 2); //最终生成的验证码左右两边各空一个字符
fontHeight = height - 2; //字体的高度
charBline = height - 4;
img = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//创建一个Graphics2D对象,可以将它绘制到BufferedImage中
Graphics2D g = img.createGraphics();
//生成随机数
Random ran = new Random();
g.setColor(Color.white);
g.fillRect(0,0,width,height);
//设置图片上字体的样式,字体类型,字体风格(普通),字体大小
Font font = new Font("宋体",Font.PLAIN,fontHeight);
g.setFont(font);
//设置干扰线
for(int i = 0; i = linenum; i++) {
//设置每条干扰线的开始和结束的坐标
int xs = ran.nextInt(width);
int ys = ran.nextInt(height);
int xe = xs + ran.nextInt(width / 8);
int ye = ys + ran.nextInt(height / 8);
//随机生成颜色值
red = ran.nextInt(225);
green = ran.nextInt(225);
blue = ran.nextInt(225);
g.setColor(new Color(red, green, blue));
g.drawLine(xs, ys, xe, ye);
}
//存放生成的验证码
StringBuffer valichars = new StringBuffer();
//生成验证码
for(int i = 0; i < charnum; i++) {
String valistr=String.valueOf(charrange[ran.nextInt(charrange.length)]);
red = ran.nextInt(225);
green = ran.nextInt(225);
blue = ran.nextInt(225);
g.setColor(new Color(red,green,blue));
g.drawString(valistr, (i + 1) * x, charBline);
valichars.append(valistr);
}
valicode = valichars.toString();
}
public void write(OutputStream sos)throws IOException{
//将图片写入ImageIO流
ImageIO.write(img,"png",sos);
}
//返回文本验证码
public StringgetValicode(){
return valicode;
}
}
controller层实现
输出验证码
//存储文本验证码
private String valiCode;
@RequestMapping(value="/validateCode")
public StringvalidateCode(HttpServletResponse response)throws Exception{
//通过response对象改变响应信息
//设置响应的类型格式为图片格式
response.setContentType("image/jpeg");
//禁止图像缓存。
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
valiPhoto vCode =new valiPhoto(120, 40, 5, 100);
//保存数据
valiCode = vCode.getValicode();
vCode.write(response.getOutputStream());
return null;
}
输入验证
@RequestMapping(value="/valiRight")
public String valiRight(HttpServletRequest request){
JSONObject jsonObject = new JSONObject();
//获取前端发送的数据
String valicode = request.getParameter("valicode");
if(!StringUtils.equalsIgnoreCase(valicode,valiCode)){
jsonObject.put("valiMessage","验证失败");
}else{
jsonObject.put("valiMessage","验证成功");
}
return jsonObject.toString();
}
效果截图:
2.Web端输入验证
页面基本结构
{this.state.valimessage}
主要操作函数
//刷新图片
changeImg = () => {
var url = this.state.Imgurl;
var newurl = this.changeUrl(url);
this.setState({
Imgurl:newurl
})
}
changeUrl = url => {
//加上时间戳,避免浏览器进行缓存
var timestamp = (new Date()).valueOf();
var index=url.indexOf("?");
if(index>0)
url = url.substring(0,index);
if((url.indexOf("&")>=0)){
url += "&tamp="+timestamp;
}else{
url += "?timestamp="+timestamp;
}
return url;
}
//提交输入验证码,并获取返回的验证结果
handleSubmit = e => {
e.preventDefault();
//使用formData对表单数据进行封装,如果直接采用json格式提交输入
//至后台,后台request.getParameter("valicode")值有可能为null
var formData = new FormData();
formData.append('valicode',this.state.valival);
fetch('http://localhost:8080/valiRight',{
method : 'POST',
mode : 'cors',
body : formData
}).then(response => {
response.json().then(data => {
console.log(data);
this.setState({
valimessage:data.valiMessage
})
})
})
}
运行结果
参考文章:https://blog.csdn.net/zhulin40/article/details/51899487