场景
作用
3. 有效防止用其他病毒或者软件自动申请用户及自动登陆的问题
实现方式
验证码的生命周期
在web应用中,验证码常用于登录注册。验证码本质就是一张图片。
我们来看一下验证码的生命周期:
1. 客户端请求验证码
2. 服务端渲染验证码:
- 渲染一张包含随机字符串的图片
- 随机字符串写入session
- 读取图片并返回响应
3. 客户端提交:- 显示响应(即验证码图片)
- 获取用户输入字符串
- 提交用户输入
4. 服务端验证:- 取出session中保存的随机字符串与用户提交的字符串进行对比
- 字符串信息一致,进行下一步处理
- 字符串信息不一致,返回错误信息
字母数字混合验证码
CaptcahCode.java(制作验证码的方法)
package com.imooc.code;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Random;
/**
* 验证码工具类
*/
public class CaptcahCode {
/**
* 字母数字混合验证码生成的方法
* @param response
* @return
*/
public static String drawImage(HttpServletResponse response){
//为什么要传递一个参数呢?验证码其实是后端产生一张图片,通过流的方式传递给浏览器,通过image标签产生图片;因为是往浏览器输出,所以需要一个响应流的对象(跟servlet一样)
//1:定义以字符串的拼接的StringBuilder(字符串流)
StringBuilder builder = new StringBuilder();
//准备产生4个字符串的随机数
for(int i=0;i<4;i++){
builder.append(randomChar());
}
String code = builder.toString();
//2:定义图片的宽度和高度
int width = 70;
int height = 25;
//简历bufferedImage对象(图片缓冲流,对下面的Graphics2D 绘制对象进行缓冲),制定图片的长度和宽度以及色彩(blue、green 和 red 三种颜色) --->画布
BufferedImage bi = new BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR);
//3:获取到 Graphics2D 绘制对象,开始绘制验证码 (画笔)
Graphics2D g = bi.createGraphics();
//4:设置文字的字体和大小
Font font = new Font("微软雅黑",Font.PLAIN,20);
//设置字体的颜色(白色)
Color color = new Color(0,0,0);
//设置字体
g.setFont(font);
//设置颜色
g.setColor(color);
//设置背景
g.setBackground(new Color(226,226,240)); //偏白色(与画笔的黑色形成对比)
//开始绘制对象
g.clearRect(0,0,width,height); //在给定的画布上清除出一个矩形用来放验证码
//绘制形状,获取矩形对象
FontRenderContext context = g.getFontRenderContext(); //文字读取的上下文
Rectangle2D bounds = font.getStringBounds(code,context); // 获取字体的像素范围对象,有阴影(矩形对象)---->可理解为给要书写的文字设置外面套一层矩形
//计算文件的坐标和间距
double x = (width - bounds.getWidth())/2;
double y = (height - bounds.getHeight())/2;
double ascent = bounds.getY();
double baseY = y - ascent; //看图可知
g.drawString(code,(int)x,(int)baseY); //用画笔g在指定坐标上绘制文字字符串code
//结束绘制
g.dispose();
//因为是输出流所以肯定要捕获IO异常
try {
ImageIO.write(bi,"jpg",response.getOutputStream()); //该步相当于我们用ps软件设计完图片要把图片进行保存(这里是以jpg的格式往网页输出)
//刷新响应流
response.flushBuffer();
}catch(Exception ex){
ex.printStackTrace();
}
return code;
}
/**
* 此方法用户产生单个随机数字母或数字
* @return
*/
private static char randomChar(){
//1:定义验证需要的字母和数字
String string = "QWERTYUIOPASDFGHJKLZXCVBNM0123456789";
//2:定义随机对象
Random random = new Random();
return string.charAt(random.nextInt(string.length())); //charAt() 方法用于返回指定索引处的单个字符