您的位置:首页 > 编程语言 > Java开发

JAVA实现验证码

2010-05-19 17:02 316 查看
一、主要功能:

1、支持纯数字、大写字母、小写字母,及两两混合或三者混合类型验证码;

2、支持自定义特殊字符排除(如0oOi1jI);

3、支持图片及文字两种类型验证码;

4、支持自定义验证码图片大小;

5、支持自定义干扰线条数;

6、支持自定义及随机定义图片、文字、干扰线颜色;

其他:示例页面提供了<iframe>和<img>两种页面显示验证码的方式。

a、仅阿拉伯数字

二、主要代码

1.index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>

<%

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>

<title><%=basePath%></title>

</head>

<script type="text/javascript">

var req;

//提交留言

function pubMsg(){

msgTitle = document.msgForm.msgTitle.value;

msgContent = document.msgForm.msgContent.value;

verifyCode = document.msgForm.verifyCode.value;

//检查输入内容格式

if(msgTitle.length<5||msgContent.length<5){

alert("标题和内容不能少于5个字符");

return;

}

if(verifyCode.length==0){

alert("请输入验证码");

return;

}

//获得 XMLHttpRequest对象

if(window.XMLHttpRequest)

req=new XMLHttpRequest();

else if(window.ActiveXObject)

req=new ActiveXObject("Microsoft.XMLHTTP");

//提交请求

if(req){

req.onreadystatechange=callBack;//指定服务器响应结果处理函数(注意仅函数名无括号)

url="<%=path%>/servlet/PubMsgServlet?msgTitle="+msgTitle+"&msgContent="+msgContent+"&verifyCode="+verifyCode;

req.open("GET",url,false);

req.send();

}

}

//服务器响应结果处理函数

function callBack(){

if(req.readyState==4){

if(req.status==200){

next=req.responseText;//获得服务器处理结果

if(next=="this"){

alert("验证码不正确,请重新输入");

verifyCodeFrame.location.reload();//刷新验证码

}else{

document.msgForm.msgTitle.value="";

document.msgForm.msgContent.value="";

window.location=next;//跳转页面

}

}else{

alert(req.status+":"+req.statusText);

}

}

document.msgForm.verifyCode.value="";

}

//更换验证码

function changeVerifyCode(){

//1、如果用<iframe>实现,则重新加载<iframe>的内容

//verifyCodeFrame.location.reload();

//2、如果用<img>实现,则修改<img src=url>的url

//这里有一个小技巧,如果给url赋相同的值,浏览器不会重新发出请求,因此用js生成一个即时毫秒数做url中的参数

t=new Date().getTime();

document.msgForm.verifyCodeImg.src="<%=path%>/servlet/VerifyCodeServlet?t="+t;

}

</script>

<body>

<form name="msgForm" action="" method="post">

<table border=0>

<tr>

<td>标题:</td>

<td><input name="msgTitle" size="65" /></td>

</tr>

<tr>

<td>内容:</td>

<td><textarea name="msgContent" rows="10" cols="64"></textarea></td>

</tr>

<tr>

<td>验证码:</td>

<td>

<input name="verifyCode" style="height: 29px; width =70px; font-size: 25px" />

<!-- 以下:两种显示验证码的方式 -->

<!-- 1、采用<iframe>实现 -->

<!--

<iframe name="verifyCodeFrame" src="<%=path + "/servlet/VerifyCodeServlet"%>"

width="100" height="30" frameborder=0 align="top" marginheight=0 marginwidth=0 scrolling=no></iframe>

-->

<!-- 2、采用<img>实现 -->

<img name="verifyCodeImg" src="<%=path%>/servlet/VerifyCodeServlet" style="cursor:hand" align="align" onClick="changeVerifyCode()" />

<!-- 以上:两种显示验证码的方式 -->

<font style="color: blue;"><a href="javascript:changeVerifyCode()">看不清?</a> </font>     

<input type="button" value=" 发表留言 " onClick="pubMsg()" />

</td>

</tr>

</table>

</form>

</body>

</html>

2.org.javachina.util.VerifyCode.java

package org.javachina.util;

import java.util.Random;

import java.awt.image.BufferedImage;

import java.awt.Graphics;

import java.awt.Font;

import java.awt.Color;

/**

* 验证码生成器类,可生成数字、大写、小写字母及三者混合类型的验证码。 支持自定义验证码字符数量; 支持自定义验证码图片的大小; 支持自定义需排除的特殊字符;

* 支持自定义干扰线的数量; 支持自定义验证码图文颜色

*

* @author org.javachina

* @version 1.01

*/

public class VerifyCode {

/**

* 验证码类型为仅数字 0~9

*/

public static final int TYPE_NUM_ONLY = 0;

/**

* 验证码类型为仅字母,即大写、小写字母混合

*/

public static final int TYPE_LETTER_ONLY = 1;

/**

* 验证码类型为数字、大写字母、小写字母混合

*/

public static final int TYPE_ALL_MIXED = 2;

/**

* 验证码类型为数字、大写字母混合

*/

public static final int TYPE_NUM_UPPER = 3;

/**

* 验证码类型为数字、小写字母混合

*/

public static final int TYPE_NUM_LOWER = 4;

/**

* 验证码类型为仅大写字母

*/

public static final int TYPE_UPPER_ONLY = 5;

/**

* 验证码类型为仅小写字母

*/

public static final int TYPE_LOWER_ONLY = 6;

private VerifyCode() {

}

/**

* 生成验证码字符串

*

* @param type

* 验证码类型,参见本类的静态属性

* @param length

* 验证码长度,大于0的整数

* @param exChars

* 需排除的特殊字符(仅对数字、字母混合型验证码有效,无需排除则为 null)

* @return 验证码字符串

*/

public static String generateTextCode(int type, int length, String exChars) {

if (length <= 0)

return "";

StringBuffer code = new StringBuffer();

int i = 0;

Random r = new Random();

switch (type) {

// 仅数字

case TYPE_NUM_ONLY:

while (i < length) {

int t = r.nextInt(10);

if (exChars == null || exChars.indexOf(t + "") < 0) {// 排除特殊字符

code.append(t);

i++;

}

}

break;

// 仅字母(即大写字母、小写字母混合)

case TYPE_LETTER_ONLY:

while (i < length) {

int t = r.nextInt(123);

if ((t >= 97 || (t >= 65 && t <= 90)) && (exChars == null || exChars.indexOf((char) t) < 0)) {

code.append((char) t);

i++;

}

}

break;

// 数字、大写字母、小写字母混合

case TYPE_ALL_MIXED:

while (i < length) {

int t = r.nextInt(123);

if ((t >= 97 || (t >= 65 && t <= 90) || (t >= 48 && t <= 57)) && (exChars == null || exChars.indexOf((char) t) < 0)) {

code.append((char) t);

i++;

}

}

break;

// 数字、大写字母混合

case TYPE_NUM_UPPER:

while (i < length) {

int t = r.nextInt(91);

if ((t >= 65 || (t >= 48 && t <= 57)) && (exChars == null || exChars.indexOf((char) t) < 0)) {

code.append((char) t);

i++;

}

}

break;

// 数字、小写字母混合

case TYPE_NUM_LOWER:

while (i < length) {

int t = r.nextInt(123);

if ((t >= 97 || (t >= 48 && t <= 57)) && (exChars == null || exChars.indexOf((char) t) < 0)) {

code.append((char) t);

i++;

}

}

break;

// 仅大写字母

case TYPE_UPPER_ONLY:

while (i < length) {

int t = r.nextInt(91);

if ((t >= 65) && (exChars == null || exChars.indexOf((char) t) < 0)) {

code.append((char) t);

i++;

}

}

break;

// 仅小写字母

case TYPE_LOWER_ONLY:

while (i < length) {

int t = r.nextInt(123);

if ((t >= 97) && (exChars == null || exChars.indexOf((char) t) < 0)) {

code.append((char) t);

i++;

}

}

break;

}

return code.toString();

}

/**

* 已有验证码,生成验证码图片

*

* @param textCode

* 文本验证码

* @param width

* 图片宽度

* @param height

* 图片高度

* @param interLine

* 图片中干扰线的条数

* @param randomLocation

* 每个字符的高低位置是否随机

* @param backColor

* 图片颜色,若为null,则采用随机颜色

* @param foreColor

* 字体颜色,若为null,则采用随机颜色

* @param lineColor

* 干扰线颜色,若为null,则采用随机颜色

* @return 图片缓存对象

*/

public static BufferedImage generateImageCode(String textCode, int width, int height, int interLine, boolean randomLocation, Color backColor,

Color foreColor, Color lineColor) {

BufferedImage bim = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

Graphics g = bim.getGraphics();

// 画背景图

g.setColor(backColor == null ? getRandomColor() : backColor);

g.fillRect(0, 0, width, height);

// 画干扰线

Random r = new Random();

if (interLine > 0) {

int x = 0, y = 0, x1 = width, y1 = 0;

for (int i = 0; i < interLine; i++) {

g.setColor(lineColor == null ? getRandomColor() : lineColor);

y = r.nextInt(height);

y1 = r.nextInt(height);

g.drawLine(x, y, x1, y1);

}

}

// 写验证码

// g.setColor(getRandomColor());

// g.setColor(isSimpleColor?Color.BLACK:Color.WHITE);

// 字体大小为图片高度的80%

int fsize = (int) (height * 0.8);

int fx = height - fsize;

int fy = fsize;

g.setFont(new Font(Font.DIALOG, Font.PLAIN, fsize));

// 写验证码字符

for (int i = 0; i < textCode.length(); i++) {

fy = randomLocation ? (int) ((Math.random() * 0.3 + 0.6) * height) : fy;// 每个字符高低是否随机

g.setColor(foreColor == null ? getRandomColor() : foreColor);

g.drawString(textCode.charAt(i) + "", fx, fy);

fx += fsize * 0.9;

}

g.dispose();

return bim;

}

/**

* 生成图片验证码

*

* @param type

* 验证码类型,参见本类的静态属性

* @param length

* 验证码字符长度,大于0的整数

* @param exChars

* 需排除的特殊字符

* @param width

* 图片宽度

* @param height

* 图片高度

* @param interLine

* 图片中干扰线的条数

* @param randomLocation

* 每个字符的高低位置是否随机

* @param backColor

* 图片颜色,若为null,则采用随机颜色

* @param foreColor

* 字体颜色,若为null,则采用随机颜色

* @param lineColor

* 干扰线颜色,若为null,则采用随机颜色

* @return 图片缓存对象

*/

public static BufferedImage generateImageCode(int type, int length, String exChars, int width, int height, int interLine, boolean randomLocation,

Color backColor, Color foreColor, Color lineColor) {

String textCode = generateTextCode(type, length, exChars);

BufferedImage bim = generateImageCode(textCode, width, height, interLine, randomLocation, backColor, foreColor, lineColor);

return bim;

}

/**

* 产生随机颜色

*

* @return

*/

private static Color getRandomColor() {

Random r = new Random();

Color c = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));

return c;

}

public static void main(String[] args) {

}

}

3.org.javachina.servlet.VerifyCodeServlet.java

package org.javachina.servlet;

import java.awt.Color;

import java.awt.image.BufferedImage;

import java.io.IOException;

import javax.imageio.ImageIO;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.javachina.util.VerifyCode;

public class VerifyCodeServlet extends HttpServlet {

public VerifyCodeServlet() {

super();

}

public void destroy() {

super.destroy();

}

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

// 设置浏览器不缓存本页

response.setHeader("Cache-Control", "no-cache");

// 生成验证码,写入用户session

String verifyCode = VerifyCode.generateTextCode(VerifyCode.TYPE_UPPER_ONLY, 4, null);

request.getSession().setAttribute("verifyCode", verifyCode);

// 输出验证码给客户端

response.setContentType("image/jpeg");

BufferedImage bim = VerifyCode.generateImageCode(verifyCode, 60, 20, 3, true, Color.WHITE, Color.BLACK, null);

ImageIO.write(bim, "JPEG", response.getOutputStream());

}

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

}

public void init() throws ServletException {

}

}

4.org.javachina.servlet.PubMsgServlet.java

package org.javachina.servlet;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class PubMsgServlet extends HttpServlet {

public PubMsgServlet() {

super();

}

public void destroy() {

super.destroy(); // Just puts "destroy" string in log

// Put your code here

}

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

// 得到留言标题、内容及用户输入的验证码

String msgTitle = request.getParameter("msgTitle");

String msgContent = request.getParameter("msgContent");

String verifyCode = request.getParameter("verifyCode");

// 取session中的正确验证码

String legalCode = null;

if (request.getSession().getAttribute("verifyCode") != null)

legalCode = (String) (request.getSession().getAttribute("verifyCode"));

String next;

// 比较session中的验证码与用户输入是否一致(这里忽略了大小写)

if (verifyCode != null && verifyCode.equalsIgnoreCase(legalCode)) {

/*

* 保存留言内容(省略)

*/

// 指定下一个URL

next = request.getContextPath() + "/ok.jsp";

} else

next = "this";

response.setContentType("text/plain");

PrintWriter out = response.getWriter();

out.print(next);

out.flush();

out.close();

}

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

}

public void init() throws ServletException {

}

}

5. ok.jsp

<%@ page language="java" import="java.util.*" pageEncoding="gbk"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<body>

您的留言已提交!<input type="button" value=" OK " onClick="window.history.go(-1)"/><br>

</body>

</html>

6.修改web.xml 添加如下内容:

<servlet>

<servlet-name>VerifyCodeServlet</servlet-name>

<servlet-class>org.javachina.servlet.VerifyCodeServlet</servlet-class>

</servlet>

<servlet>

<servlet-name>PubMsgServlet</servlet-name>

<servlet-class>org.javachina.servlet.PubMsgServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>VerifyCodeServlet</servlet-name>

<url-pattern>/servlet/VerifyCodeServlet</url-pattern>

</servlet-mapping>

<servlet-mapping>

<servlet-name>PubMsgServlet</servlet-name>

<url-pattern>/servlet/PubMsgServlet</url-pattern>

</servlet-mapping>

转载地址: http://www.java3z.com/cwbwebhome/article/article3/3468.html?id=2132
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: