##验证码的大致原理
首先了解到的是验证码是由服务端产生,以图片的形式展示在客户端或页面,用户端的用户根据图片识别验证码,并进行注册提交,提交的验证码在服务层进行校验,如果校验成功,则用户注册成功并登陆,如果失败,请用户重新注册。然后想一想这些图片是怎样生成的,验证码如何设计的,验证码为什么要设计成图片的格式,而且人们肉眼都难以识别其中的验证码。
图片是在服务端随机产生,这些图片可以通过设置规定他们的高度和宽度,然后再图片上绘制一些干扰线,当然,干扰线的数量也是可以控制的,不同验证码插件或者不同的网站验证码图片的干扰程度不同,一般来说干扰程度越高,防止恶意攻击的效果会更好一些。但是用户识别起来也会增加难度,制造干扰线也是防止别人编写程序识别图片中的验证码或者通过某种机器提取图片中的验证码,来进行恶意注册或搞破坏。如果人眼都不能一眼轻易识别图片中的验证码,相信机器的识别度在比人眼低的情况下,不容易获取图片中的验证码。图片上的验证码可以是数组和大小写字母的组合,也可以是汉字的形式,这些字符都是随机产生并进行拼接的。实现验证功能的图片合成之后,会转换为一串字符串,然后以字节数组输出流的形式传送到前端,并显示在页面的相应位置。不是,该验证码产生的同时,会伴随产生它的唯一标志的id,过期时间,然后这些数据一般会一同封装到服务端的缓存中,到用户输入验证码并返回时,在服务端进行校验,并把校验的结果返回到前端界面。这些是验证码的大致原理
接下来就是我的代码了,是怎么实现的
1、登录页面 index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录页面</title>
<style type="text/css">
*{
magin: 0 auto;
padding: 0px;
}
form{
width: 400px;
margin: 100px auto;
}
</style>
</head>
<body>
<form method=post action="result.jsp">
<input type=text name=input maxlength=4>
<img src="image.jsp" id="identity" onload="btn.disabled=false;" />
<input type=button value="换一张" onclick="reloadImage()" id="btn"></br>
<input type="submit" value="提交">
</form>
<script type="text/javascript">
function reloadImage(){
document.getElementById('btn').disabled=true;
document.getElementById('identity').src='image.jsp?ran'+Math.random();
}
</script>
</body>
</html>
2、生成验证码图片页面 image.jsp
[code=html]<%@ page contentType="image/JPEG"
import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*"
pageEncoding="UTF-8"%>
//生成验证码图片页面
//首先,验证码其实就是在服务端产生一张带有验证码数字或者算式的图片,所以,在这个过程要用到gui知识
<%!Color getRandColor(int fc, int bc) {
//给定范围获得随机颜色
Random random = new Random();
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}%>
<%
//1、验证码界面
//设置页面不缓存
//因为某些浏览器缓存验证码,导致重新打开该页面时总提示验证码过期。
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
// 在内存中创建图象
int width = 60, height = 20; //验证码的宽和高
//定义画布
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//得到画笔 在图片中绘制内容
Graphics g = image.getGraphics(); //方法获取画笔,
//1.设置颜色,画边框
g.setColor(getRandColor(200, 250));
g.drawRect(0, 0, width - 1, height - 1);
//2.设置颜色,填充内部
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
//设定字体
g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
//2、产生随机数
//生成随机类
Random random = new Random();
// 随机产生155条干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(160, 200));
for (int i = 0; i < 100; i++) {
int x = random.nextInt(width); // 起点的x坐标
int y = random.nextInt(height); // 起点的y坐标
int xl = random.nextInt(12); // x轴偏移量
int yl = random.nextInt(12); // y轴偏移量
g.drawLine(x, y, x + xl, y + yl);
}
//随机产生4位验证码
String[] codes = { "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K",
"L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
// 该变量用来保存系统生成的随机字符串
String sRand = "";
for (int i = 0; i < 4; i++) {
// 取得一个随机字符
String rand = codes[random.nextInt(codes.length)];
sRand += rand;
// 将认证码显示到图象中 将系统生成的随机字符添加到图形验证码图片上
g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));//调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.drawString(rand, 13 * i + 6, 16);
}
//3、发送验证码图片数据
// 将认证码存入SESSION 将系统生成的图形验证码添加
session.setAttribute("code", sRand);
// 图象生效
g.dispose(); //释放与Graphice2D有关的对象的资源
// 输出图象到页面 ImageIO 读取图片 // 输出图形验证码图片
ImageIO.write(image, "JPEG", response.getOutputStream());
//加上下面代码,运行时才不会出现java.lang.IllegalStateException: getOutputStream() has already been called ..........等异常
response.getOutputStream().flush();
response.getOutputStream().close();
response.flushBuffer();
out.clear();
out = pageContext.pushBody();
3、生成验证码图片页面 result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 结果页面 -->
<!-- JAVA绘制图片,然后将验证码的字符上传session,在登陆时候验证session 里的值和用户输入的值即可。 -->
<%
//从页面获取输入的值
String input=request.getParameter("input");
String code=(String)session.getAttribute("code");
if(input.equals(code)){
out.println("验证成功!");
}else{
out.println("验证失败!");
}
%>
</body>
</html>
###4、运行后的果
有什么不行的地方,欢迎大家给我指出!谢谢!