验证码的作用:区分用户是计算机还是人;验证码有图片、拖拽、短信等各种形式,其中图片形式最为常见:
工具类:
public class VerifyCodeUtils {
/**
* 创建验证码
* @param width 图片宽度
* @param height 图片高度
* @param length 字符数
* @param fontName 字体名
* @return
*/
public static BufferedImage createValidate(int width, int height, int length, String fontName,
HttpServletRequest request) {
HttpSession session = request.getSession();
// BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
// 创建一个不带透明色的BufferedImage对象
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 产生Image对象的Graphics对象,该对象可以在图像上进行各种绘制操作
Graphics graphics = image.createGraphics();
graphics.fillRect(0, 0, width, height);// 图片大小
// 绘制边框
graphics.setColor(Color.LIGHT_GRAY);
graphics.drawRect(0, 0, width - 1, height - 1);
graphics.drawRect(1, 1, width - 2, height - 2);
// 生成指定长度的[a-z]的随机字符串, 包含大小写
String str = RandomStringUtils.randomAlphabetic(length);
char[] chs = str.toCharArray();
Random random = new Random();
// 将正确验证码存入Session
session.setAttribute("verifyCode", str);
// 填充length个字符
for (int i = 0; i < length; i++) {
// 设置字体颜色
int R = random.nextInt(256);
int G = random.nextInt(256);
int B = random.nextInt(256);
Color color = new Color(R, G, B);
graphics.setColor(color);
// 设置字体(第二个参数为style)
Font font = new Font(fontName, random.nextInt(3), 30);
graphics.setFont(font);
// 画字符(横纵坐标可优化)
graphics.drawString(String.valueOf(chs[i]), 30*i + random.nextInt(20), 24+ random.nextInt(20));
}
// 随机噪声线(还可以添加噪声点等)
for (int i = 0; i < 4; i++) {
int beginX = random.nextInt(width);
int beginY = random.nextInt(height);
int endX = random.nextInt(width);
int endY = random.nextInt(height);
int R = random.nextInt(256);
int G = random.nextInt(256);
int B = random.nextInt(256);
Color color = new Color(R, G, B);
graphics.setColor(color);
// 画直线
graphics.drawLine(beginX, beginY, endX, endY);
}
return image;
}
}
验证码传递:
@RequestMapping("/verifyCode")
public void verifyCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
BufferedImage image = VerifyCodeUtils.createValidate(180, 60, 4, "黑体", request);
// 设置互联网媒体类型
response.setContentType("image/jpeg");
ImageIO.write(image, "jpeg", response.getOutputStream());
}
页面:
<div>
验证码:
<input type="text" id="verifyCode" name="verifyCode">
<img th:src="@{/verifyCode}" id="realVerifyCode">
<a href="#" onclick="changeVerify()" id="changeVerify">看不清,换一张a>
div>
JavaScript代码:
<script>
var wait = 10;
var timer;
function changeVerify() {
// 添加参数, 让浏览器觉得是一次新的请求, 达到刷新页面的效果
$("#realVerifyCode").attr("src", "/verifyCode?"+Math.random());
$("#changeVerify").removeAttr("onclick").text("请等待" + wait + "秒.");
setText();
}
function setText() {
timer = setInterval(function(){
if(wait > 0){
wait--;
var text = "请等待" + wait + "秒.";
$("#changeVerify").text(text);
} else {
// 清除定时器
clearInterval(timer);
wait = 10;
// 参数要加双引号,否则changeVerify()方法会被重复调用
$("#changeVerify").attr("onclick", "changeVerify()");
$("#changeVerify").text("看不清,换一张");
}
}, 1000)
}
</script>