原理:页面端通过定义img的src直接请求到服务器端,服务器端生成验证码图片,保存验证码值,并将图片通过流的方式返回到页面端。
生成验证码图片:通过java绘制2D图片。下面代码:
/**
* 随机生成验证码
*/
public ModelAndView createCheckCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
//加个线程休眠2秒是为了查看页面loading效果
// Thread t = new Thread();
// try {
// t.sleep(2000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//获取一个参数,是为区别html的img元素每次提交过来的src不同,达到更换验证码图片效果
String nowCode = request.getParameter("nowCode");
if(nowCode == null){
return null;
}
//验证码图片的宽度。
int width = 60;
//验证码图片的高度。
int height = 20;
//验证码字符个数
int codeCount = 4;
//随机字符左右距离
int marginLeft = 12;
//字体高度
int fontHeight = 15;
//验证码字符与图片上边距的距离
int marginTop = 15;
//基础字符
char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
//初始化图像的Buffer对象
BufferedImage bufferedImage = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
//创建图像画布
Graphics2D g = bufferedImage.createGraphics();
//初始化一个随机数生成器类
Random random = new Random();
//将图像填充为白色
g.setColor(Color.WHITE);
//图像上实心白色矩形框
g.fillRect(0, 0, width, height);
//在图像上画一个空心的黑色边框
g.setColor(Color.BLACK);
g.drawRect(0, 0, width - 1, height - 1);
//随机产生10条干扰线,使图象中的验证码不易被自动识别程序解析出来,干扰线多了字符看不清
//g.setColor(Color.GRAY);
g.setColor(new Color(127, 131, 142)); //灰色的干扰线容易看点
for(int i = 0; i < 10; i++){
int gx = random.nextInt(width); //在整个图像区域内产生干扰线
int gy = random.nextInt(height);
int gxl = random.nextInt(width);
int gyl = random.nextInt(height);
g.drawLine(gx, gy, gx + gxl, gy + gyl); //画线,两头的XY坐标
}
//randomCode用于保存随机产生的验证码,以便用户登录后进行验证。
StringBuffer randomCode = new StringBuffer();
int red = 0;
int green = 0;
int blue = 0;
//创建字体,字体的大小应该根据图片的高度来定。
Font fontCode = new Font("Microsoft YaHei", Font.BOLD, fontHeight);
//设置字体。
g.setFont(fontCode);
//随机产生基础字符内的验证码。
for (int i = 0; i < codeCount; i++) {
//在上面定义的基础字符内随机产生验证码
String strRand = String.valueOf(codeSequence[random.nextInt(36)]);
//RGB随机产生值,这样输出的每位数字的颜色值都不同
red = random.nextInt(255);
green = random.nextInt(255);
blue = random.nextInt(255);
//将随机产生的颜色值配置在验证码中
g.setColor(new Color(red, green, blue));
//旋转文本
//g.rotate(random.nextInt(2) * Math.PI / 180);
//平移原点到图形环境的中心 ,这个方法的作用实际上就是将字符串移动到某一个位置
//g.translate(1, 1);
g.drawString(strRand, (i + 1) * marginLeft - 5, marginTop);
//组合产生的验证码
randomCode.append(strRand);
}
//System.out.println(randomCode.toString());
//将产生的随机数存在session中,用作比对页面上输入的验证码值
request.getSession().setAttribute("checkCodeValue", randomCode.toString());
//禁止图像缓存。
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//设置图像返回客户端类型
response.setContentType("image/jpeg");
//将图像以流的方式输出
ServletOutputStream sos = response.getOutputStream();
ImageIO.write(bufferedImage, "jpeg", sos);
sos.close();
return null;
}
下面一断是验证:
/**
* 验证码校验
*/
public ModelAndView checkCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
String nowCheckCodeValue = request.getParameter("checkCodeValue");
String checkCodeValue = (String) request.getSession().getAttribute("checkCodeValue");
//输入的验证码值和session中的进行比对,都转换成大写,因为基础字符中就是全大写,这样页面端可以忽略大小写
if(nowCheckCodeValue.toUpperCase().equals(checkCodeValue)){
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("成功");
return null;
}else{
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("失败");
return null;
}
}
下面是jsp:
<%@ page language="java" pageEncoding="UTF-8"%>
<%String path = request.getContextPath();%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>验证码测试</title>
<script type="text/javascript" src="<%=path%>/resources/easyui/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#img-checkcode').bind('click', function () { /**为验证码图片绑定更换验证码事件**/
$("#img-checkcode").attr("src",'loading.gif');
var url = '/swmis/manage/init.do?method=createCheckCode';
url += "&nowCode=" + (new Date()).getTime();
this.src = url;
});
setTimeout(function(){ /**初始化生成验证码,写个setTimeout是为了查看loading图片效果**/
$("#img-checkcode").attr("src",'/swmis/manage/init.do?method=createCheckCode&nowCode=' + (new Date()).getTime());
},2000);
});
function subOk(){ /**提交验证码比对**/
var checkCodeValue = $("#txtCheckCode").val();
$.ajax({
type:'POST',
async:true,
url: '/swmis/manage/init.do?method=checkCode',
data: {
checkCodeValue : checkCodeValue
},
success:function(data){
alert(data);
}
});
}
</script>
</head>
<body>
<table style="margin: 26px auto;" cellpadding="2" cellspacing="2" width="600px" height="80px">
<tr>
<td width="100px" align="right">
<label>用户名:</label>
</td>
<td width="200px">
<input type="text" class="txt" id="txtUserName" name="txtUserName" value="admin" />
</td>
<td rowspan="2" align="left" width="200px">
<a href=javascript:login() class="btnLogin"></a>
</td>
</tr>
<tr>
<td width="100px" align="right">
<label>密码:</label>
</td>
<td width="200px">
<input type="password" class="txt" id="txtPassword" name="txtPassword" value="admin" />
</td>
</tr>
<tr>
<td width="100px" align="right">
<label>验证码:</label>
</td>
<td width="200px">
<input type="text" style="vertical-align: middle;" id="txtCheckCode" name="txtCheckCode" value="" />
<img style="vertical-align: middle;" id="img-checkcode" alt="猛击更换!" title="猛击更换!" src="loading.gif" style=" cursor:pointer" />
<!-- <img style="vertical-align: middle;" id="img-checkcode" alt="猛击更换!" title="猛击更换!" src="/swmis/manage/init.do?method=createCheckCode&nowCode=1" style=" cursor:pointer" /> -->
</td>
</tr>
<tr>
<td width="200px" colspan="2">
<input type="button" class="txt" id="btnSub" name="btnSub" value="提交" οnclick="subOk()" />
</td>
</tr>
</table>
</body>
</html>