`

验证码三种实现(一般,依赖颜色,问答)

 
阅读更多

原来做验证码都是通过patchca 一个类库生成的

今天上信息安全的课的时候 老师提到了原来的学生有做验证码识别的(通过OpenCV)

 

    http://zh.wikipedia.org/wiki/验证码 写道

全自动区分计算机和人类的图灵测试(英语:Completely Automated Public Turing test to tell Computers and Humans Apart,简称CAPTCHA),俗称验证码,是一种区分用户是计算机和人的公共全自动程序。在CAPTCHA测试中,作为服务器的计算机会自动生成一个问题由用户来解答。这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类。

 

     做网页用验证码的目的之一是为了对用户密码进行暴力破解.当然还有其他的目的.

 

然后我想无聊做做就做做吧 空着也空着

我就想到了三个形式的:

  1. 最普通的形式
  2. 依赖颜色的(填写的是指定颜色的验证码)
  3. 问答形式的

先看下实现的图吧:



 最普通的 也就是通过一些线来扰乱视线 没通过Path(Path好像是android的API里的吧..)之类的进行弧度显示 这个普通的没做颜色处理(都是很深的颜色) 要处理的可以自己修改

 



 输入的字符是指定颜色的(指定的颜色就是下面那一行的颜色 之所以要画在图上 是发现网页上显示的和图上的会有差别)

这边为了能更好让用户看出来 所以要输入的验证码的颜色都是很深的

R:0-50 G:0-50 B:0-50 个数随机(最少1个 最多全部都是) 可以自己再设定下验证码的颜色以免太容易被识别出来

 



 问答形式的 最多只能45个字符 每行15个 可以3行(更多就显示不出来了... ...自己设定下宽高)

 

 

具体的实现如下

都是蛮简单的 (我把一些本来应该作为常量的放在了方法里面 我就不移动了)

package org.cc.servlet;

// 省略了import 下同
/**
 * 这是最基本的验证码形式
 * 也就是一排数字和字母的组合
 * 不做验证的处理了 定义一个属性放在session(每个连接一个session 不用担心数据共享的问题)
 * 运行后控制台直接打印验证码
 * @author cc fairjm
 * {@link http://fair-jm.iteye.com/}
 *
 */
@WebServlet(name="verifyCode",urlPatterns={"/verifyCode"})
public class VerifyCode extends HttpServlet {

	

    // 作为验证码的字符
	private final 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'};
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 图像的高度
		int height = 60;
		
		// 图像的宽度
	    int width = 200;

	    // 字体大小
	    int fontSize=40;

	    //字体高度
        int fontHeight=-1;
        
        // 创建一个随机数生成器类。
        Random random = new Random();
        random.setSeed(new Date().getTime());
        
        //显示的验证码字符数量
	    int number=random.nextInt(3)+4;
		
	    
		BufferedImage buffImg = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g = buffImg.createGraphics();
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, width, height);

		
		// 创建字体,字体的大小应该根据图片的高度来定。
		Font font = new Font("consolas", Font.BOLD,fontSize);
		
		// 设置字体
		g.setFont(font);
		FontMetrics fm=g.getFontMetrics();
		
		// 得到高度
		fontHeight=fm.getHeight();
		
		// 画边框。
		g.setColor(Color.BLACK);
		g.drawRect(0, 0, width - 1, height - 1);

		
		
		// 随机产生40条干扰线,使图象中的认证码不易被其它程序探测到。
		for (int i = 0; i < 40; i++) {
			Color color=new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255));
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(width/2);
			int yl = random.nextInt(height/2);
			g.setColor(color);
			g.drawLine(x, y, x + xl, y + yl);
		}
		
		
		StringBuffer randomCode = new StringBuffer();
		int red = 0, green = 0, blue = 0;
		for (int i = 0; i < number; i++) {
			// 得到随机产生的验证码数字。
			String strRand = String.valueOf(codeSequence[random.nextInt(36)]);

			// 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。
			red = random.nextInt(50);
			green = random.nextInt(50);
			blue = random.nextInt(50);

			// 用随机产生的颜色将验证码绘制到图像中。
			g.setColor(new Color(red, green, blue));
			g.drawString(strRand, width/(number+1)*(i+1),fontHeight+random.nextInt(fontHeight)/5);

			// 将产生的四个随机数组合在一起。
			randomCode.append(strRand);
		}
		
		
		HttpSession session = req.getSession();
		session.setAttribute("randomCode", randomCode.toString());

		// 禁止图像缓存。
		resp.setHeader("Pragma", "no-cache");
		resp.setHeader("Cache-Control", "no-cache");
		resp.setDateHeader("Expires", 0);

		resp.setContentType("image/jpeg");

		// 将图像输出到Servlet输出流中。
		ServletOutputStream sos = resp.getOutputStream();
		ImageIO.write(buffImg, "jpeg", sos);
		sos.close();
		
		
		System.out.println("I:"+session.getAttribute("randomCode"));
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doGet(req, resp);
	}

}

 

 

 

 

颜色:

package org.cc.servlet;

/**
 * 指定颜色的
 * @author cc fairjm
 * {@link http://fair-jm.iteye.com/}
 *
 */
@WebServlet(name="verifyColor",urlPatterns={"/verifyColor"})
public class VerifyColor extends HttpServlet {

	

    // 作为验证码的字符
	private final 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'};
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 图像的高度
		int height = 60;
		
		// 图像的宽度
	    int width = 200;

	    // 字体大小
	    int fontSize=40;

	    //字体高度
        int fontHeight=-1;
        
        // 创建一个随机数生成器类。
        Random random = new Random();
        random.setSeed(new Date().getTime());
        
        //显示的验证码字符数量
	    int number=random.nextInt(6)+4;
		
	    
		BufferedImage buffImg = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g = buffImg.createGraphics();
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, width, height);

		
		// 创建字体,字体的大小应该根据图片的高度来定。
		Font font = new Font("consolas", Font.BOLD,fontSize);
		
		// 设置字体
		g.setFont(font);
		FontMetrics fm=g.getFontMetrics();
		
		// 得到高度
		fontHeight=fm.getHeight();
		
		// 画边框。
		g.setColor(Color.BLACK);
		g.drawRect(0, 0, width - 1, height - 1);

		
		

		
		
		Color usedColor=new Color(random.nextInt(100),random.nextInt(100),random.nextInt(100));
		
		
		StringBuffer randomCode = new StringBuffer();
		
		for (int i = 0; i < number; i++) {
			int red = 0, green = 0, blue = 0;
			// 得到随机产生的验证码数字。
			String strRand = String.valueOf(codeSequence[random.nextInt(36)]);

			if(random.nextBoolean()||i==number/2){
				g.setColor(usedColor);
				g.drawString(strRand, width/(number+1)*(i+1),fontHeight);
				randomCode.append(strRand);
				continue;
			 }
			do{		
			  red = random.nextInt(50)+200;
			  green = random.nextInt(50)+200;
			  blue = random.nextInt(50)+200;
			}while(
					Math.abs(red-usedColor.getRed())<20&&
					Math.abs(green-usedColor.getGreen())<20&&
					Math.abs(blue-usedColor.getBlue())<20);
			g.setColor(new Color(red,green,blue));
			g.drawString(strRand, width/(number+1)*(i+1),fontHeight);		
		}
		
		g.setColor(usedColor);	
		g.fillRect(0, fontHeight, width, height-fontHeight);
		
		// 随机产生40条干扰线,使图象中的认证码不易被其它程序探测到。
		for (int i = 0; i < 40; i++) {
			Color color=new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255));
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(width/2);
			int yl = random.nextInt(height/2);
			g.setColor(color);
			g.drawLine(x, y, x + xl, y + yl);
		}
		
		HttpSession session = req.getSession();
		session.setAttribute("randomCode", randomCode.toString());

		// 禁止图像缓存。
		resp.setHeader("Pragma", "no-cache");
		resp.setHeader("Cache-Control", "no-cache");
		resp.setDateHeader("Expires", 0);

		resp.setContentType("image/jpeg");

		// 将图像输出到Servlet输出流中。
		ServletOutputStream sos = resp.getOutputStream();
		ImageIO.write(buffImg, "jpeg", sos);
		sos.close();
		
		
		System.out.println("color:"+session.getAttribute("randomCode"));
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doGet(req, resp);
	}
}

 

 

 

 

package org.cc.servlet;

/**
 * 这个就是指定问题的了...
 * @author cc fairjm
 * {@link http://fair-jm.iteye.com/}
 *
 */
@WebServlet(name="verifyQuestion",urlPatterns={"/verifyQuestion"})
public class VerifyQuestion extends HttpServlet {

	private static final List<Question> ques=new ArrayList<Question>(); 

  /*	 
   *  如果要用数据库 如下 
    private static  Connection conn;
               // 以下代码会在类的初始化过程中被执行(类只会被初始化一次除非卸载或者容器关闭了)
               // 也可以放在类的构造方法中  
	static{
    	try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
    	try {
			conn=DriverManager.getConnection("数据库地址", "user", "password");
		    System.out.println(conn);
    	} catch (SQLException e) {
			e.printStackTrace();
		}
    	 
    	 进行list的赋值操作
    }
  */
	public VerifyQuestion(){
		ques.add(new Question("这是第一个问题", "第一个问题的答案"));
		ques.add(new Question("校名的英文缩写", "zjut"));
		ques.add(new Question("问题xxxxxxxxxxxxxxxxxxxxxxxxx", "xx"));
		ques.add(new Question("问题xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "xx"));
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 图像的高度
		int height = 65;
		
		// 图像的宽度
	    int width = 200;

	    // 字体大小
	    int fontSize=15;

	    //字体高度
        int fontHeight=-1;
        
        //每行多少字
        int wordsOfRow=15;
        
        // 创建一个随机数生成器类。
        Random random = new Random();
        random.setSeed(new Date().getTime());
        
      
		int use=random.nextInt(ques.size());
		Question usedQuestion=ques.get(use);
		
		
		BufferedImage buffImg = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g = buffImg.createGraphics();
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, width, height);

		
		// 创建字体 自行调整本机有的字体
		Font font = new Font("微软雅黑", Font.BOLD,fontSize);
		
		// 设置字体
		g.setFont(font);
		FontMetrics fm=g.getFontMetrics();
		
		// 得到高度
		fontHeight=fm.getHeight();
		
		// 画边框。
		g.setColor(Color.BLACK);
		g.drawRect(0, 0, width - 1, height - 1);

		String question=usedQuestion.getQuestion();
		int rows=question.length()/wordsOfRow;
		rows=rows==0?1:rows;
		// 没做处理 字数太多的话会画到下面去
		for(int i=0;i<rows;i++){
			int last=i*wordsOfRow+wordsOfRow;
			if(i*wordsOfRow+10>question.length()){
				last=question.length();
			}
			g.drawString(question.substring(i*wordsOfRow,last), 10,fontHeight*(i+1));
		}
		
		
		
		HttpSession session = req.getSession();
		session.setAttribute("randomCode", usedQuestion.getAnswer());
		// 禁止图像缓存。
		resp.setHeader("Pragma", "no-cache");
		resp.setHeader("Cache-Control", "no-cache");
		resp.setDateHeader("Expires", 0);

		resp.setContentType("image/jpeg");

		// 将图像输出到Servlet输出流中。
		ServletOutputStream sos = resp.getOutputStream();
		ImageIO.write(buffImg, "jpeg", sos);
		sos.close();
		
		
		System.out.println("answer:"+session.getAttribute("randomCode"));
	}


	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doGet(req, resp);
	}
	
	
	
}

// entity
class Question implements Serializable{
	private static final long serialVersionUID = 1L;
	private String question;
	private String answer;
	public Question(String question, String answer) {
		super();
		this.question = question;
		this.answer = answer;
	}
	public String getAnswer() {
		return answer;
	}
	public void setAnswer(String answer) {
		this.answer = answer;
	}
	public String getQuestion() {
		return question;
	}
	public void setQuestion(String question) {
		this.question = question;
	}

}

 

代码欢迎随便使用

如有问题请留言.

  • 大小: 22.8 KB
  • 大小: 18.6 KB
  • 大小: 2.7 KB
0
0
分享到:
评论
2 楼 alvin198761 2013-05-08  
我见过几种比较好的,一个就是打广告的,请输入广告中红色的字

第二种是选食物,上面一排图片,让你输出第三个图片是什么,比如是苹果,
1 楼 steafler 2013-05-08  
挺不错的,不过项目中直接用封装好的captcha

相关推荐

    java开源包3

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包4

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包1

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包11

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包2

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包6

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包5

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包10

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包8

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包7

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包9

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    java开源包101

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    Java资源包01

    GWT Spring 使得在 Spring 框架下构造 GWT 应用变得很简单,提供一个易于理解的依赖注入和RPC机制。 Java扫雷游戏 JVMine JVMine用Applets开发的扫雷游戏,可在线玩。 public class JVMine extends java.applet....

    JAVA上百实例源码以及开源项目源代码

     util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码...

    asp.net知识库

    在ASP.Net中两种利用CSS实现多界面的方法 如何在客户端调用服务端代码 页面一postback,它就显示页面的最顶端,怎样让它定位在某一位置? 如何保证页面刷新后的滚动条位置 清除网页历史记录,屏蔽后退按钮! 如何传值...

    JAVA上百实例源码以及开源项目

     util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码...

Global site tag (gtag.js) - Google Analytics