`
kong0itey
  • 浏览: 306016 次
社区版块
存档分类
最新评论

我写的验证码生成方案,可防止绝大多数机械识别。

    博客分类:
  • java
阅读更多
web.xml
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
	<!-- ******************************************** -->
	<!-- **********验证码生成器************************** -->
	<!-- ******************************************** -->
	<servlet>
		<servlet-name>CaptchaServlet</servlet-name>
		<servlet-class>com.lowca.activity.web.servlet.CaptchaServlet</servlet-class>
		<init-param>
			<param-name>width</param-name>
			<param-value>150</param-value>
		</init-param>
		<init-param>
			<param-name>height</param-name>
			<param-value>100</param-value>
		</init-param>
		<init-param>
			<param-name>bgColor</param-name>
			<param-value>255,255,255</param-value>
		</init-param>
		<init-param>
			<param-name>fontColor</param-name>
			<param-value>0,255,0</param-value>
		</init-param>
		<init-param>
			<param-name>fontSize</param-name>
			<param-value>44</param-value>
		</init-param>
		<init-param>
			<param-name>fontCount</param-name>
			<param-value>4</param-value>
		</init-param>
		<init-param>
			<param-name>fontName</param-name>
			<param-value>宋体</param-value>
		</init-param>
		<init-param>
			<param-name>chars</param-name>
			<!-- 去掉了容易造成误解的字符,例如:i o z 和 1 0 2 -->
			<param-value>ABCDEFGHJKLMNPQRSTUVWXYabcdefghjkmnpqrstuvwxy3456789</param-value>
		</init-param>
		<init-param>
			<param-name>sessionKey</param-name>
			<param-value>com.lowca.activity.captcha</param-value>
		</init-param>
		<init-param>
			<param-name>maxRotateAngle</param-name>
			<param-value>40</param-value>
		</init-param>
		<init-param>
			<param-name>fontPadding</param-name>
			<param-value>-15</param-value>
		</init-param>
	</servlet>

	<servlet-mapping>
		<servlet-name>CaptchaServlet</servlet-name>
		<url-pattern>/captcha.jpg</url-pattern>
	</servlet-mapping>
</web-app>


servlet类文件
package com.lowca.activity.web.servlet;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;

public class CaptchaServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private static final String CONTENT_TYPE = "image/jpeg";

	// ==================以下变量用于保存配置参数的默认值 ==================
	/**
	 * 验证码的宽度
	 */
	private int width = 200;
	/**
	 * 验证码的高度
	 */
	private int height = 150;
	/**
	 * 验证码背景色
	 */
	private Color bgColor = Color.WHITE;
	/**
	 * 文字颜色
	 */
	private Color fontColor = Color.GREEN;
	/**
	 * 验证码字符字号
	 */
	private int fontSize = 42;
	/**
	 * 验证码字符个数
	 */
	private int fontCount = 4;
	/**
	 * 验证码字符间距,单位是像素
	 */
	private int fontPadding = -15;
	/**
	 * 验证码字符最大旋转角度
	 */
	private int maxRotateAngle = 40;
	/**
	 * 验证码字体
	 */
	private String fontName = "宋体";
	/**
	 * 验证码用到的字符
	 */
	private String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
	/**
	 * 验证码在session中的键名
	 */
	private String sessionKey = "com.lowca.activity.captcha";

	// ==================以下变量用于在初始化时候保存数据,减少重复计算 ==================

	private Font font;

	private char[] seedArray;

	private int offsetX = 0;

	private int offsetY = 0;

	/**
	 * 生成由数字和字母随机组成的图片
	 */
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, java.io.IOException {
		BufferedImage buffImg = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g2d = buffImg.createGraphics();
		g2d.setColor(bgColor);
		g2d.fillRect(0, 0, width, height);
		g2d.setPaint(fontColor);
		g2d.setFont(font);
		// 旋转文本

		StringBuffer randCode = new StringBuffer();
		for (int i = 0; i < fontCount; i++) {
			g2d.setStroke(new BasicStroke((float) (Math.random() * 5)));
			double angle = Math.random() * maxRotateAngle * Math.PI / 180;
			int p = (int) (Math.random() * chars.length());
			String word = String.valueOf(seedArray[p]);
			randCode.append(word);
			int x = offsetX + i * (fontSize + fontPadding);

			AffineTransform origXform = g2d.getTransform();
			AffineTransform newXform = (AffineTransform) (origXform.clone());
			newXform.rotate(angle, x, offsetY);
			g2d.setTransform(newXform);
			g2d.drawString(word, x, offsetY);
			g2d.setTransform(origXform);
		}
		g2d.setStroke(new BasicStroke(2.0f));
		int x = offsetX - (int) (20 * Math.random());
		int y = offsetY - (int) (20 * Math.random());
		int w = (int) (width - 10 - Math.random() * 6);
		int h = (int) (height - 10 - Math.random() * 6);
		int startAngle = (int) (Math.random() * 16 + 45);
		int arcAngle = (int) (Math.random() * 45 + 90);
		g2d.drawArc(x, y, w, h, startAngle, arcAngle);
		g2d.dispose();

		// 将四位数字的验证码保存到Session里面
		HttpSession session = req.getSession();
		session.setAttribute(sessionKey, randCode);

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

		// 将图像输出到Servelt输出流中
		ServletOutputStream out = resp.getOutputStream();
		ImageIO.write(buffImg, "jpeg", out);
		out.close();
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType(CONTENT_TYPE);
	}

	public void init() throws ServletException {
		// 初始化配置参数
		String param = getInitParameter("width");
		if (NumberUtils.isDigits(param)) {
			width = Integer.parseInt(param);
		}
		param = getInitParameter("height");
		if (NumberUtils.isDigits(param)) {
			height = Integer.parseInt(param);
		}
		param = getInitParameter("bgColor");
		if (param != null && param.matches("^\\d+,\\d+,\\d+$")) {
			bgColor = getColor(param);
		}
		param = getInitParameter("fontColor");
		if (param != null && param.matches("^\\d+,\\d+,\\d+$")) {
			fontColor = getColor(param);
		}
		param = getInitParameter("fontSize");
		if (NumberUtils.isDigits(param)) {
			fontSize = Integer.parseInt(param);
		}
		param = getInitParameter("maxRotateAngle");
		if (NumberUtils.isDigits(param)) {
			maxRotateAngle = Integer.parseInt(param);
		}
		param = getInitParameter("fontPadding");
		if (param != null && param.matches("-?\\d+")) {
			fontPadding = Integer.parseInt(param);
		}
		param = getInitParameter("fontName");
		if (StringUtils.isNotBlank(param)) {
			fontName = param;
		}
		param = getInitParameter("chars");
		if (StringUtils.isNotBlank(param)) {
			chars = param;
		}
		param = getInitParameter("sessionKey");
		if (StringUtils.isNotBlank(sessionKey)) {
			sessionKey = param;
		}
		// 初始化状态变量
		font = new Font(fontName, Font.ITALIC, fontSize);
		seedArray = chars.toCharArray();
		offsetX = width / 2 - fontCount * fontSize / 2 - (fontCount - 1)
				* fontPadding / 2 - 8;
		offsetY = height / 2 + fontSize / 2 - 8;
	}

	private Color getColor(String rgb) {
		String[] array = rgb.split(",");
		return new Color(Integer.parseInt(array[0]),
				Integer.parseInt(array[1]), Integer.parseInt(array[2]));
	}

}


在我的机器上,这个程序每秒钟可以产生大约83张验证码。验证码图样如下
  • 大小: 2.6 KB
  • 大小: 2.5 KB
  • 大小: 2.4 KB
  • 大小: 2.4 KB
分享到:
评论
1 楼 我会是微博 2015-03-11  
<img src="CaptchaServlet" />是这样调用么?为何显示不了?

相关推荐

    旋转验证码生成与识别(Python版)

    在网络安全领域,验证码(CAPTCHA)是一种用于验证用户是否为人类的工具,它通常用于防止自动脚本或机器人进行恶意操作。"旋转验证码"是一种特殊类型的验证码,它通过扭曲、旋转字母或数字来增加机器识别的难度。在...

    验证码生成识别工具

    验证码生成识别工具识别,可用于密码爆破或者破解邮箱密码或者,也可快速多帐

    验证码生成类大全

    验证码生成类大全是一种用于网络安全验证的重要工具,它主要用于防止恶意自动化程序(如机器人)进行非法操作,例如批量注册、刷票或数据抓取。在Web应用中,验证码通常需要用户在提交表单前输入图像上显示的一串...

    验证码生成工具类

    验证码生成工具类是一种在Web应用中广泛使用的安全机制,它主要用于防止自动化的恶意操作,比如机器人注册、垃圾邮件发送等。这个工具类是用Java语言编写的,因此我们可以深入探讨一下Java验证码生成的相关技术和...

    图片验证码生成demo

    验证码(CAPTCHA)是一种用于验证用户是否为人类的在线安全机制。它通常表现为一组随机生成的、难以由计算机程序自动识别...通过深入研究和实践,你将能够创建自己的定制化验证码解决方案,以适应各种应用场景的需求。

    页面验证码生成器

    本项目“页面验证码生成器”提供了一种自定义化的解决方案,允许开发者根据需求调整验证码的字符集、长度、图像尺寸以及干扰纹样式。 在Java中实现验证码生成,通常涉及到以下几个核心知识点: 1. **随机数生成**...

    .NET验证码生成组件

    2. **API调用**:理解并使用组件提供的API,如生成验证码图片的方法、设置验证码长度、字符集、颜色方案等。 3. **服务器端验证**:当用户提交表单时,服务器端需要验证用户输入的验证码是否与服务器生成的原始...

    java验证码生成类

    验证码(CAPTCHA)是一种用于验证用户身份的安全机制,通常用于防止自动机器人或恶意软件进行非法操作,如批量注册、垃圾邮件发送等。在Java中,我们可以创建一个自定义的验证码生成类来实现这一功能。这篇博客文章...

    表单验证码生成_js

    例如,如果我们想要生成包含大小写字母和数字的验证码,可以定义如下字符串: ```javascript let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; ``` 接下来,我们设定验证码的长度...

    php高安全验证码生成类

    对于这个验证码生成类,readme.md可能会详细解释如何配置字体目录、如何引入类文件、示例代码以及可能出现的问题和解决方案。 通过以上方法,我们可以构建一个具有较高安全性的PHP验证码生成类,有效防止自动化攻击...

    易语言简单验证码生成和识别

    易语言简单验证码生成和识别源码,简单验证码生成和识别,生成随机验证码,比对文本子程序

    简单验证码生成jar包

    这个“简单验证码生成jar包”提供了一个便捷的解决方案,帮助开发者在他们的应用中集成验证码功能。一个`.jar`文件是Java应用程序的归档文件,它可以包含代码、资源文件和元数据。`code_kyle_1.1.jar`很可能是这个...

    VC++验证码生成Base64验证码png图片程序

    VC++验证码生成Base64验证码png图片程序,如何使用VC++生成验证码图片,输出Base64图片给网页调用

    验证码生成

    2. **复杂度**:验证码可能包含不同的字符集(数字、大小写字母、特殊符号),并可能扭曲、倾斜、加噪或混淆字符,以增加机器识别的困难。 3. **时限性**:验证码在一定时间内有效,过期后需重新生成,防止被重复...

    验证码生成(java)包

    验证码生成在IT行业中是一项重要的安全技术,主要用于防止自动化的机器人程序或者恶意用户进行非法操作,如批量注册、恶意登录等。本压缩包提供了一个基于Java的验证码生成解决方案,包括了必要的库文件,如jcaptcha...

    旋转验证码生成及识别.rar

    验证码(CAPTCHA)是一种用于防止自动化程序(如机器人)滥用网站服务的安全机制。它通过让用户执行人类可以轻松完成但机器难以自动解决的任务来验证用户是真实的人。在这个主题中,我们将专注于“旋转验证码”的...

    转载 旋转验证码识别 github:双旋转验证码解决方案

    转载。旋转验证码识别。 github:双旋转验证码解决方案

    验证码识别接口生成器-源码

    验证码识别接口生成器是一种用于自动化处理验证码的工具,它基于JAVA编程语言,旨在简化验证码的识别过程。在本文中,我们将深入探讨这个源码实现的关键技术、步骤以及学习要点。 首先,验证码识别的核心在于图像...

    java jcaptcha 验证码 生成

    Java JCaptcha验证码生成详解 验证码(CAPTCHA)是一种防止机器自动操作的安全机制,它通过让用户输入图片或音频中显示的随机字符来验证用户是否为真实的人。在Java开发中,JCaptcha是一个广泛使用的开源库,它提供...

    验证码生成类-最好用的

    常见的复杂度调整包括验证码长度、字符类型(大小写字母、数字、特殊字符)、扭曲程度等。 3. **可读性**:虽然复杂度很重要,但验证码必须保证人类可以轻松识别。这可能涉及到合理的字符间距、合适的字体大小和...

Global site tag (gtag.js) - Google Analytics