【当当网】电子书城-02-验证码的实现
前文传送门:
【当当网】电子书城-01-市场背景与项目搭建-CSDN博客
完整源代码获取方式:关注+评论区留言获取
🌲 验证码功能
🌿 验证码作用
每次注册或者登录前都要求输入验证码,可以防止脚本程序恶意攻击服务器或者采用穷举法暴力破解账号对应的密码。
🌿 验证码工具类
在util包中,新建一个ImageCode类,编写生成验证码的方法,核心原理步骤:
- 创建图片,随机给图片添加背景。
- 在图片上采用随机颜色、随机字体绘制4个随机字符。
- 在图片上绘制一定数量的干扰线,防止机器自动识别验证码图片中的内容。
具体代码如下:
package com.softeem.dang.util;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 验证图片工具类
*/
public class ImageCode {
// 验证码的宽度
private int width = 100;
// 验证码的高度
private int height = 40;
// 验证码图片上的文本
private String text ;
// 随机数工具
Random rd = new Random();
// 验证码图片上文字字体数组
private String[] fontNames = {"宋体","Georgia"};
// 验证码图片上文字的字符池
// 从这个字符串中随机选取字符放入到验证码图片中
private String codes = "23456789qwertyuipasdfghjkzxcvbnmQWERTYUIPASDFGHJKLZXCVBNM";
/**
* 随机颜色
* @return
*/
public Color randomColor(){
// 随机生成红色的数值
int r = rd.nextInt(256);
// 随机生成绿色的数值
int g = rd.nextInt(256);
// 随机生成蓝色的数值
int b = rd.nextInt(256);
return new Color(r,g,b);
}
/**
* 随机字体
* @return
*/
public Font randomFont(){
// 随机获取字体名称
int index = rd.nextInt(fontNames.length);
// 随机获取字体的样式
int style = rd.nextInt(4); // 0 无样式 1加粗 2是斜体 3 加粗+斜体
// 随机字体大小
int size = rd.nextInt(10)+24;
// new Font(字体名称,字体样式,字体大小)
return new Font(fontNames[index],style,size);
}
/**
* 随机字符
* @return
*/
public char randomChar(){
// 随机字符下标
int index = rd.nextInt(codes.length());
// 根据下标获取字符,并返回
return codes.charAt(index);
}
/**
* 在指定的图片上画干扰线
* @param image
*/
public void drawLine(BufferedImage image){
// 随机干扰线数量
int num = rd.nextInt(10);
// 获取画笔
Graphics2D g =(Graphics2D) image.getGraphics();
for(int i=0;i<num;i++){
int x1 = rd.nextInt(width);
int y1 = rd.nextInt(height);
int x2 = rd.nextInt(width);
int y2 = rd.nextInt(height);
// 设置干扰线的颜色
g.setColor(randomColor());
// 画出干扰线
g.drawLine(x1,y1,x2,y2);
}
}
/**
* 创建图片的方法
* @return
*/
public BufferedImage createImage(){
// BufferedImage(宽度,高度,颜色类型)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
// 获取画笔
Graphics2D g =(Graphics2D) image.getGraphics();
// 随机背景颜色
// 设置画笔颜色
g.setColor(new Color(255,255,rd.nextInt(245)+10));
// 使用颜色填充矩形区域
g.fillRect(0,0,width,height);
// 返回图片
return image;
}
/**
* 获取验证码图片的方法
* @return
*/
public BufferedImage getImage(){
// 创建图片
BufferedImage image = createImage();
// 获取图片中的画笔对象
Graphics2D g =(Graphics2D) image.getGraphics();
StringBuilder sb = new StringBuilder();
// 随机4个字符
for (int i=0;i<4;i++){
// 随机选择一个字符
String s = randomChar()+"";
sb.append(s);
// 生成字符的横坐标
float x = i*1.0F*(width/4);
// 设置字体
g.setFont(randomFont());
// 设置颜色
g.setColor(randomColor());
// 将文字画到图片上
g.drawString(s,x,height-5);
}
text = sb.toString();
// 画干扰线
drawLine(image);
return image;
}
/**
* 获取验证码上的文字内容
* @return
*/
public String getText(){
return text;
}
}
🌿 请求验证码
在前端页面中,找到显示验证码图片的img标签,在其src属性中发送请求,如下图所示:
然后在服务器端编写处理生成验证码的请求,代码如下:
/**
*
* @param req 请求对象
* @param resp 响应对象
* @throws ServletException
* @throws IOException
*/
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建验证码生成工具
ImageCode ic = new ImageCode();
// 生成验证码图片
BufferedImage img = ic.getImage();
// 获取验证码中的文本
String code = ic.getText();
// 将验证码保存到session中,方便后面去判断验证码输入是否正确
req.getSession().setAttribute("code",code);
// 将验证码图片推送dao浏览器中显示
OutputStream out = resp.getOutputStream();
ImageIO.write(img,"JPEG",out);
}
运行结果如下图所示:
🌿 切换验证码功能
切换验证码图片功能原理:当点击链接时,找到验证码图片,使用src属性重新发送一次请求。但是需要注意的是由于浏览器的缓存机制,我们需要让浏览器认为每次发送的请求是不相同的。因此我们在请求的后面追加一个系统当前时间,让每次点击的请求不一样,具体代码如下:
// 根据ID找到a标签,并添加点击事件
$("#change").click(function (){
// 找到验证码图片,重新发送请求
// 因为浏览器有缓存,后面追加时间参数,目的是让每次发送的请求不一样,从而绕过浏览器缓存
$("#imgVcode").attr("src","getCode&a="+new Date().getTime())
});