Java如何生成简单的JSP彩色验证码

1.生成彩色验证码的原理

 使用Java生成彩色验证码利用的就是Java动态生成和操作图片的技术。因为验证码的特点,需要每次生成一个随机的字符串,然后将生成的字符串以某种特殊的字体画到背景图片上。一个好的验证码,要求图片的背景也是随机的,而且要与数字有一定的混淆程度,这样即使攻击程序使用了OCR技术也很难识别出验证码来。

2.应用示例

 由于生成验证码图片的操作也可能是经常被调用的,所以我们将它封装成一个JavaBean,其文件名为imageEnsure.java,具体代码实现如下所示。

 

package imageEnsure;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

public class imageEnsure {
	
	public imageEnsure() {
	}
	
	private char mapTable[] = {
		'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'};
	
	 public String getEnsure(int width,int height,OutputStream os) {
		 if(width<=0) width=60;
		 if(height<=0) height=20;
		 
		 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		 
		 //获取图形上下文
		 Graphics g = image.getGraphics();
		 
		 //设置背景色
		 g.setColor(new Color(0xDCDCDC));
		 g.fillRect(0, 0, width, height);
		 
		 //画边框
		 g.setColor(Color.black);
		 g.drawRect(0, 0, width-1, height-1);
		 
		 //取随机产生的验证码
		 String strEnsure="";
		 
		 //4代表4位验证码
		 for(int i=0;i<4;i++) {
			 strEnsure += mapTable[(int)(mapTable.length*Math.random())];
		 }
		 
		 //将验证码显示到图像中
		 g.setColor(Color.black);
		 g.setFont(new Font("Atlantic Inline",Font.PLAIN,18));
		 
		 String str = strEnsure.substring(0,1);
		 g.drawString(str, 8, 17);
		 str = strEnsure.substring(1, 2);
		 g.drawString(str, 20, 15);
		 
		 str = strEnsure.substring(2, 3);
		 g.drawString(str, 35, 18);
		 str = strEnsure.substring(3, 4);
		 g.drawString(str, 45, 15);
		 
		 //随机产生100个干扰点
		 Random rand = new Random();
		 for(int i=0;i<100;i++) {
			 int x=rand.nextInt(width);
			 int y=rand.nextInt(height);
			 g.drawOval(x, y, 1, 1);
		 }
		 
		 //释放图形上下文
		 g.dispose();
		 
		 try {
			 //输出图形到页面
			 ImageIO.write(image, "JPEG", os);
		 } catch(IOException e) {
			 return "";
		 }	 
		 return strEnsure;
	 }
}
 程序首先创建一个内存图像的实例,然后获得此内存图像的图形上下文,然后利用图形上下文对象在内存图像中画背景、画边框。

 随后在一个循环里随机产生4个介于0到mapTable大小之间的整数,然后以此整数为索引将其所对应的在mapTable中的字符捏起来作为验证字符串,并在内存对象中输出,最后再在内存对象中随机画了100个位置不确定的干扰点并调用ImageIO的静态方法write输入内存对象到response输出流中去。

 函数的返回值为验证码对应的字符串。

 读者也可以根据自己的的需要定义自己的mapTable字符集,由于输出的字符很模糊,所以读者在挑选字符集时应该尽量避免一些外形相似的字符,如大写字母O和数字0,小写字母l和数字1等。因为这里只是注重阐述原理,所以忽略了这些细节问题。

 文件index.jsp用于调用这个Bean,生成验证码图片并将验证码字符添加到session的属性表中以供稍后使用。

 

<%@ page language="java" import="java.util.*" contentType="image/jpeg"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<jsp:useBean id="image" scope="page" class="imageEnsure.imageEnsure"/>

<%
	String str=image.getEnsure(0, 0, response.getOutputStream());
	//将验证码存入session
	session.setAttribute("strEnsure", str);
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>My JSP 'index.jsp' starting page</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->
  </head>
  
  <body>
    This is my JSP page. <br>
  </body>
</html>
 image/jpeg指明这个JSP页面的输出内容的类型为JPEG图像,因此,在其他页面中可以将此页面当作图片文件来引用,不同的只是此图片是动态生成的,而且每次输出的都是不一样的。下面来介绍页面文件imageEnsure.jsp是怎么使用它的:

 

<%@ page language="java" import="java.util.*" contentType="text/html; charset=GBK"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>验证码输入页面</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta  http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<meta http-equiv="Content-Type" content="text/html;charset=GB2312">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
    <p>验证码:<img src="index.jsp">
    <form method="post" action="action_imageEnsure.jsp">
      <p>
               请输入上面的验证码:<input type="text" name="code" maxlength="4">
      <p>
      <input type="submit" value="提交检测"></td>
    </form>
  </body>
</html>
 可以看到,对image.jsp的引用放在了HTML语言的img标签中当成输出图片的源。该页面的作用是显示image.jsp动态生成的图片并提供一个输入框供用户输入所看到的验证码。而文件action_imageEnsure.jsp用于响应用户的输入,并执行最终的验证逻辑。

<%@ page language="java" import="java.util.*" contentType="text/html; charset=GBK"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>验证码输入页面</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<meta http-equiv="Content-Type" content="text/html;charset=GB2312">
	<!--
	<link rel="stylesheet" type="text/css" href="styles.css">
	-->

  </head>
  
  <body>
    <%
      String ensure = (String)session.getAttribute("strEnsure");
      String code = request.getParameter("code");
      out.print("<p>"+ensure);
      if(ensure.equals(code))
    	  out.print("验证通过");
      else
    	  out.print("验证不通过");
    %>
  </body>
</html>
 以下是执行效果:


最后好像还有点问题,贴出来大家看看。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值