JAVA实现验证码

一、主要功能:

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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值