前言:验证码(Completely Automated Public Turing test to tell Computers and Humans Apart),缩写为CAPTCHA,是一种区分用户是计算机还是人的公共全自动程序。应用验证码是很多网站通行的方式,不仅可以防止恶意破解密码、刷票、论坛灌水,还能有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
思路:在内存中生成一张图片(默认背景色是黑色)> 获取笔刷工具 > (修改背景颜色、字体)> 添加干扰元素
- BufferedImage类:BufferedImage是Image实现类,是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中(BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片),提供获得绘图对象、图像缩放、选择图像平滑度等功能,通常用来做图片大小变换、图片变灰、设置透明不透明等。
//在内存中生成一张图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//宽,高,图片的色彩模式
- Graphics类:提供基本绘图和显示格式化文字的方法,画图用的坐标系原点在左上角,纵轴向下。主要有画线段、矩形、圆、椭圆、圆弧、多边形等各种颜色的图形、线条。Graphics2D类提供更强大的绘图能力。
//获得图片的笔刷
Graphics graphics = image.getGraphics();//默认背景为黑色
实现代码如下↓
/**
* @author JaneWay Chen
*/
package cn.edu.mju.project24.contoller;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/capctha")
public class CapcthaServlet extends HttpServlet {
int width = 400;
int height = 300;
//生成随机数
Random random = new Random();
//在内存中生成一张图片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);//宽,高,图片的色彩模式
//获得图片的笔刷
Graphics graphics = image.getGraphics();//默认背景为黑色
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//流
ServletOutputStream sos = response.getOutputStream();
//输出内存中的图片
ImageIO.write(generatePic(width, height),"JPEG",sos);
sos.flush();
sos.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
/**
* 生成图片
* @param width
* @param height
* @return
*/
private BufferedImage generatePic(int width, int height){
//随机生成一个颜色并设置为图片背景颜色
graphics.setColor(randomColor());
//填充背景色
graphics.fill3DRect(0, 0, width,height, true);
//设置字体
graphics.setFont(new Font("幼圆", Font.ITALIC, 100));
//添加干扰元素
generateDistrub(width, height);
//产生验证字符串,位置随机
graphics.drawString(randomCode(), random.nextInt(200) + 50, random.nextInt(200) + 50);
return image;
}
/**
* 随机产生一个颜色
* @return Color
*/
public Color randomColor() {
int r = random.nextInt(256);
int g = random.nextInt(256);
int b = random.nextInt(256);
return new Color(r, g, b);
}
/**
* 生成直线对图片的干扰
* @return null
*/
public void generateDistrub(int width, int height){
for(int i = 0; i<=50; i++){
//设置干扰线的颜色
graphics.setColor(randomColor());
//画直线
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
int x2 = random.nextInt(width);
int y2 = random.nextInt(height);
graphics.drawLine(x1, y1, x2, y2);
}
}
/**
* 随机产生一个验证码的字符串
* @return String
*/
public String randomCode(){
//验证字符串库
char[] arr = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', '我','是','好','坏','人'};
StringBuilder sb = new StringBuilder();
//随机产生四个索引
for (int i = 0; i < 4; i++) {
int index = random.nextInt(arr.length);
//从字符数组中取出对应的字符,存储到StringBuilder
sb.append(arr[index]);
}
return sb.toString();
}
}
成果如下