JavaWeb之验证码识别
开发环境
首先来介绍一下我此次使用的工具以及环境,没有的可以去官网自行下载使用。
jdk:1.8
开发工具:IntelliJ IDEA 2020.1 x64
服务器:TomCat8.5
效果图
分析:实现这个效果,首页得有这个界面吧,在index.jsp里写就行就行,一个input输入框,一个image,一个a标签,再一个button提交按钮,再添加js的onclick事件;再来说说逻辑上的思路,我们平时登录应用程序,这个验证码肯定都是随机生成,所以这里我们也要随机生成,使用java的Random()生成,要将数字和字符混合在一起随其生成的验证码,同时还需要给它添加干扰线,防止非真人的机器识别。
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang=" en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
function changeImg() {
document.getElementById("validateCodeImg").src = "/generateCode?" + Math.random();
}
</script>
</head>
<body>
<form action="/checkCode" method="post">
验证码:<input type="text" name="validateCode" />
<img alt="验证码看不清,换一张" src="/generateCode" id="validateCodeImg" onclick="changeImg()">
<a href="javascript:void(0)" onclick="changeImg()">看不清,换一张</a>
<br />
<input type="submit" value="提交">
</form>
</body>
</html>
我将整个项目依次分成9个步骤来写
1.在内存中生成一张图片
2.获取内存中的图片
3.设置图片背景
4.设置图片边框
5.设置干扰线
6.获取验证码内容
7.将验证码保存到session
8.设置浏览器以图片格式读取验证码
9.将验证码发送给浏览器
首先创建一个GenerateCode类,继承HttpServlet,定义两个私有变量:width,height 用来表示图片的宽高,重写doGet和doPost方法
private static final int WIDTH =120;//设置图片宽度
private static final int HEIGHT =30;//设置图片高度
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1-9步
}
1.在内存中生成一张图片
BufferedImage bufferedImage = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
Image是一个抽象类,BufferedImage是其实现类,是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中(BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片),提供获得绘图对象、图像缩放、选择图像平滑度等功能,通常用来做图片大小变换、图片变灰、设置透明不透明等。
BufferedImage.TYPE_INT_RGB : 表示一个图像,该图像具有整数像素的 8 位 RGB 颜色
2.获取内存中的图片
Graphics graphics = bufferedImage.getGraphics();
getGraphics()调用此方法相当于给了你一只画笔让你使用。得到画笔后你可以用它画图形,将获取到的图片画出来。
3.设置图片背景
setBackground(graphics);
这里是自定义了一个setBackground方法,设置一下验证码背景的颜色为白色,然后填充
/**
* 设置验证码背景
* @param graphics
*/
private void setBackground(Graphics graphics){
graphics.setColor(Color.WHITE);//设置颜色
graphics.fillRect(0,0,WIDTH,HEIGHT);//填充图片
}
4.设置图片边框
setBorder(graphics);
也是定义了一个setBorder方法,为graphics这个图片对象添加边框,也就是咱们的验证码图片添加一个边框
/**
* 设置边框
* @param graphics
*/
private void setBorder(Graphics graphics){
graphics.setColor(Color.BLUE);
//画边框
graphics.drawRect(1,1,WIDTH-2,HEIGHT-2);
}
5.设置干扰线
setRandomLine(graphics);
同理,调用封装好的setRandomLine方法,干扰线颜色为绿色
/**
* 设置干扰线
* @param graphics 图片对象
*/
private void setRandomLine(Graphics graphics){
//设置颜色
graphics.setColor(Color.GREEN);
//画干扰线
for (int i = 0; i < 5; i++) {
int x1 = new Random().nextInt(WIDTH);//0-120之间,不包括120
int y1 = new Random().nextInt(HEIGHT);
int x2 = new Random().nextInt(WIDTH);
int y2 = new Random().nextInt(HEIGHT);
graphics.drawLine(x1,y1,x2,y2);
}
}
6.获取验证码内容
String randomString =getRandomString((Graphics2D) graphics,"mixed");
用字符串来保存验证码内容,调用封装好的getRandomString方法传达验证码的类型,这里选择的是数字+字母混合,然后返回的是随机字符串,通过类型的判断也调用了setRandomString()返回验证码字符串
/**
* 获取随机字符串
* @param graphics 图片对象
* @param type 随机字符串类型
* @return 随机字符串
*/
private String getRandomString(Graphics graphics, String type) {
//设置颜色
graphics.setColor(Color.RED);
//设置字体
graphics.setFont(new Font("宋体",Font.BOLD,20));
String number = "0123456789";
String character = "ABCDEFGHIJKLMNOPQRSTUVWSXYZ";
String mixed = "0123456789ABCDEFGHIJKLMNOPQRSTUVWSXYZ";
if("number".equals(type)){
//生成纯数字验证码
return setRandomString((Graphics2D) graphics,number);
}else if("character".equals(type)){
return setRandomString((Graphics2D) graphics,character);
}else {
return setRandomString((Graphics2D) graphics,mixed );
}
}
/**
* 生成验证码字符串
* @param graphics 图片对象
* @param level 类型
* @return 验证码字符串
*/
private String setRandomString(Graphics2D graphics, String level) {
//用于存储生成的随机字符串
StringBuilder stringBuilder = new StringBuilder();
int x =5;
String ch = "";
//生成随机单词
for (int i = 0; i < 4; i++) {
//设置旋转角度
int degree= new Random().nextInt() % 30;
//获取随机字母
ch = level.charAt(new Random().nextInt(level.length())) +"";
stringBuilder.append(ch);
//设置正向旋转
graphics.rotate(degree * Math.PI /180,x,20);
graphics.drawString(ch,x,20);
//设置反向旋转
graphics.rotate(-degree * Math.PI /180,x,20);
x += 30;
}
return stringBuilder.toString();
}
7.将验证码保存到session
req.getSession().setAttribute("yunqinanhai",randomString);
8.设置浏览器以图片格式读取验证码
resp.setContentType("image/jpg");
9.将验证码发送给浏览器
ImageIO.write(bufferedImage,"jpg",resp.getOutputStream());
到这里验证码的生成和回传以及干扰线等都写完了,接下来要写一个验证类,用来验证用户输入的验证码是否正确?
创建一个CheckCode类,继承HttpServlet,重写doGet,doPost方法
在doPost方法里写验证程序,doGet里写this.doPost(req, resp);
为防止编码错误,这里将编码设置为UTF-8,通过index.jsp的输入框属性绑定,获取用户输入的验证码,创建一个字符串来获取session里的验证码数据,再通过equals判断是否正确
注意:由于验证码应该不区分大小写,所以这里不能使用equals()来判断两个验证码是否相等,要用equalsIgnoreCase()来判断
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
resp.setCharacterEncoding("UTF-8");
//获取用户输入的验证码
String validateCode = req.getParameter("validateCode");
String yunqinanhai = (String) req.getSession().getAttribute("yunqinanhai");
if(validateCode.equalsIgnoreCase(yunqinanhai)){
resp.getWriter().println("验证码正确");
}else{
resp.getWriter().println("验证码错误");
}
}
最后,为了让index.jsp找到对应的java文件,需要添加映射路径:
@WebServlet("/generateCode")
@WebServlet("/checkCode")
到这里,这个项目基本完成了,现在run一下tomcat服务器,默认跳转index.jsp。端口号默认是8080
点击图片或者旁边的文字均可以换一张验证码
现在我们来验证是不是区分大小写了
不出所料,确实区分大小写了,此次关于验证码的生成与验证就到这里结束了。感恩能与大家在华为云遇见!希望能与大家一起在华为云社区共同成长。
- 点赞
- 收藏
- 关注作者
评论(0)