在J2ee Web 项目中经常用到验证码,现在总结下
1.生成验证码的Servlet PictureCheckCode.java
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import tools.MD5;
public class PictureCheckCode extends HttpServlet{
private static final long serialVersionUID = 1L;
private Random rand=new Random();
/**
* 生成随机颜色
*
* @param start [int]
* @param end [int]
* @return Color [object]
*/
public Color getRandColor(int start,int end){
int randNum;
if(start>255) start=255;
if(end>255) end=255;
if(start>end) randNum=start-end;
else randNum=end-start;
int r=start+rand.nextInt(randNum);
int g=start+rand.nextInt(randNum);
int b=start+rand.nextInt(randNum);
return new Color(r,g,b);
}
/**
* 着色\旋转\缩放
*
* @param word 文字
* @param g 图片对象
*/
public void coloredAndRotation(String word,int i,Graphics g){
/**着色**/
g.setColor(new Color(20+rand.nextInt(110),20+rand.nextInt(110),20+rand.nextInt(110)));
/**旋转**/
Graphics2D g2d=(Graphics2D)g;
AffineTransform trans=new AffineTransform();
trans.rotate(rand.nextInt(45)*3.14/180,15*i+8,7);
/**缩放**/
float scaleSize=rand.nextFloat()+0.8f;
if(scaleSize>1f) scaleSize=1f;
trans.scale(scaleSize, scaleSize);
g2d.setTransform(trans);
g.drawString(word,15*i+20,20);
}
/**
* 生成100条干扰线
*
* @param g2d
* @param width
* @param height
*/
public void getRandLine(Graphics2D g2d,int width,int height){
for(int i=0;i<100;i++){
int x=rand.nextInt(width-1);
int y=rand.nextInt(height-1);
int z=rand.nextInt(6)+1;
int w=rand.nextInt(12)+1;
BasicStroke bs=new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL);
Line2D line=new Line2D.Double(x,y,x+z,y+w);
g2d.setStroke(bs);
g2d.draw(line);
}
}
/**
* 获取随机文字
*
* @param length [int] 验证码长度
* @param g [Graphics] 图片对象
* @return String
* @case1:A-Z
* @case2:chinese
* @default:0-9
*/
@SuppressWarnings("unused")
public String getRandWord(int length,Graphics g){
String finalWord="",firstWord="";
int tempInt=0;
String[] array={
"0","1","2","3",
"4","5","6","7",
"8","9","a","b",
"c","d","e","f"};
for(int i=0;i<length;i++){
switch(rand.nextInt(2)){
case 1:
tempInt=rand.nextInt(26)+65;
firstWord=String.valueOf((char)tempInt);
break;
/*case 2:
int r1,r2,r3,r4;
String strH,strL;//high&low
r1=rand.nextInt(3)+11; //前闭后开[11,14)
if(r1==13){
r2=rand.nextInt(7);
}else{
r2=rand.nextInt(16);
}
r3=rand.nextInt(6)+10;
if(r3==10){
r4=rand.nextInt(15)+1;
}else if(r3==15){
r4=rand.nextInt(15);
}else{
r4=rand.nextInt(16);
}
strH=array[r1]+array[r2];
strL=array[r3]+array[r4];
byte[] bytes=new byte[2];
bytes[0]=(byte)(Integer.parseInt(strH,16));
bytes[1]=(byte)(Integer.parseInt(strL,16));
firstWord=new String(bytes);
break;*/
default:
tempInt=rand.nextInt(10)+48;
firstWord=String.valueOf((char)tempInt);
break;
}
finalWord+=firstWord;
this.coloredAndRotation(firstWord,i, g);
}
return finalWord;
}
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设制不缓存图片
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","No-cache");
response.setDateHeader("Expires",0);
//生成图片
response.setContentType("image/jpeg");
int width=100;
int height=40;
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g=image.getGraphics();
Graphics2D g2d=(Graphics2D)g;
Font mFont=new Font("宋体",Font.BOLD,22);
g.setColor(this.getRandColor(200,250));
g.fillRect(0, 0, width, height);
g.setFont(mFont);
g.setColor(this.getRandColor(180,200));
this.getRandLine(g2d, width, height);
String randCode=this.getRandWord(4, g);
HttpSession session=request.getSession();
session.setAttribute("randCode",MD5.code(randCode.toLowerCase()));
g.dispose();
ImageIO.write(image,"JPEG",response.getOutputStream());
}
}
2.Structs2 web.xml 配置
因为要使Structs2和servlet 共存,所以要配置下 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>JJBC6</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.do</url-pattern>
<url-pattern>*.htm</url-pattern>
<url-pattern>*.action</url-pattern>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>RandImg</servlet-name>
<servlet-class>web.PictureCheckCode</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RandImg</servlet-name>
<url-pattern>/RandImg</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/jsp/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
3.前台Jsp页面的应用
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>论坛登陆</title>
<script type="text/javascript" src="js/jquery-latest.js"></script>
<script type="text/javascript">
function refresh() {
$("#randimg").attr("src","RandImg?time="+ new Date().getTime());
};
function showCode(){
$(".varcode").show();
};
</script>
</head>
<body>
<h3>论坛登陆 </h3>
<s:form action="/Login" validate="true">
用户名 <s:textfield name="user.name" key="name"/><br>
<s:textfield name="user.date" key="date"/><br>
密码 <s:password name="user.password" key="password"/>
<s:submit/>
</s:form>
<div class="varcodeinput">
验证码: <input type="text" id="code" name="code" οnfοcus="showCode();" οnclick="showCode();" size="4" maxlength="4"/>
[ 点击输入框获取验证码,不区分大小写 ]
</div>
<div class="varcode" style="display:none">
<img src="RandImg" id="randimg" />
<a href="javascript:refresh()" title="看不清左边的字符?点下换个!">看不清?换一个</a>
</div>
</body>
</html>
1.生成验证码的Servlet PictureCheckCode.java
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import tools.MD5;
public class PictureCheckCode extends HttpServlet{
private static final long serialVersionUID = 1L;
private Random rand=new Random();
/**
* 生成随机颜色
*
* @param start [int]
* @param end [int]
* @return Color [object]
*/
public Color getRandColor(int start,int end){
int randNum;
if(start>255) start=255;
if(end>255) end=255;
if(start>end) randNum=start-end;
else randNum=end-start;
int r=start+rand.nextInt(randNum);
int g=start+rand.nextInt(randNum);
int b=start+rand.nextInt(randNum);
return new Color(r,g,b);
}
/**
* 着色\旋转\缩放
*
* @param word 文字
* @param g 图片对象
*/
public void coloredAndRotation(String word,int i,Graphics g){
/**着色**/
g.setColor(new Color(20+rand.nextInt(110),20+rand.nextInt(110),20+rand.nextInt(110)));
/**旋转**/
Graphics2D g2d=(Graphics2D)g;
AffineTransform trans=new AffineTransform();
trans.rotate(rand.nextInt(45)*3.14/180,15*i+8,7);
/**缩放**/
float scaleSize=rand.nextFloat()+0.8f;
if(scaleSize>1f) scaleSize=1f;
trans.scale(scaleSize, scaleSize);
g2d.setTransform(trans);
g.drawString(word,15*i+20,20);
}
/**
* 生成100条干扰线
*
* @param g2d
* @param width
* @param height
*/
public void getRandLine(Graphics2D g2d,int width,int height){
for(int i=0;i<100;i++){
int x=rand.nextInt(width-1);
int y=rand.nextInt(height-1);
int z=rand.nextInt(6)+1;
int w=rand.nextInt(12)+1;
BasicStroke bs=new BasicStroke(2f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL);
Line2D line=new Line2D.Double(x,y,x+z,y+w);
g2d.setStroke(bs);
g2d.draw(line);
}
}
/**
* 获取随机文字
*
* @param length [int] 验证码长度
* @param g [Graphics] 图片对象
* @return String
* @case1:A-Z
* @case2:chinese
* @default:0-9
*/
@SuppressWarnings("unused")
public String getRandWord(int length,Graphics g){
String finalWord="",firstWord="";
int tempInt=0;
String[] array={
"0","1","2","3",
"4","5","6","7",
"8","9","a","b",
"c","d","e","f"};
for(int i=0;i<length;i++){
switch(rand.nextInt(2)){
case 1:
tempInt=rand.nextInt(26)+65;
firstWord=String.valueOf((char)tempInt);
break;
/*case 2:
int r1,r2,r3,r4;
String strH,strL;//high&low
r1=rand.nextInt(3)+11; //前闭后开[11,14)
if(r1==13){
r2=rand.nextInt(7);
}else{
r2=rand.nextInt(16);
}
r3=rand.nextInt(6)+10;
if(r3==10){
r4=rand.nextInt(15)+1;
}else if(r3==15){
r4=rand.nextInt(15);
}else{
r4=rand.nextInt(16);
}
strH=array[r1]+array[r2];
strL=array[r3]+array[r4];
byte[] bytes=new byte[2];
bytes[0]=(byte)(Integer.parseInt(strH,16));
bytes[1]=(byte)(Integer.parseInt(strL,16));
firstWord=new String(bytes);
break;*/
default:
tempInt=rand.nextInt(10)+48;
firstWord=String.valueOf((char)tempInt);
break;
}
finalWord+=firstWord;
this.coloredAndRotation(firstWord,i, g);
}
return finalWord;
}
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设制不缓存图片
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","No-cache");
response.setDateHeader("Expires",0);
//生成图片
response.setContentType("image/jpeg");
int width=100;
int height=40;
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics g=image.getGraphics();
Graphics2D g2d=(Graphics2D)g;
Font mFont=new Font("宋体",Font.BOLD,22);
g.setColor(this.getRandColor(200,250));
g.fillRect(0, 0, width, height);
g.setFont(mFont);
g.setColor(this.getRandColor(180,200));
this.getRandLine(g2d, width, height);
String randCode=this.getRandWord(4, g);
HttpSession session=request.getSession();
session.setAttribute("randCode",MD5.code(randCode.toLowerCase()));
g.dispose();
ImageIO.write(image,"JPEG",response.getOutputStream());
}
}
2.Structs2 web.xml 配置
因为要使Structs2和servlet 共存,所以要配置下 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>JJBC6</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.do</url-pattern>
<url-pattern>*.htm</url-pattern>
<url-pattern>*.action</url-pattern>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>RandImg</servlet-name>
<servlet-class>web.PictureCheckCode</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RandImg</servlet-name>
<url-pattern>/RandImg</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/jsp/index.jsp</welcome-file>
</welcome-file-list>
</web-app>
3.前台Jsp页面的应用
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>论坛登陆</title>
<script type="text/javascript" src="js/jquery-latest.js"></script>
<script type="text/javascript">
function refresh() {
$("#randimg").attr("src","RandImg?time="+ new Date().getTime());
};
function showCode(){
$(".varcode").show();
};
</script>
</head>
<body>
<h3>论坛登陆 </h3>
<s:form action="/Login" validate="true">
用户名 <s:textfield name="user.name" key="name"/><br>
<s:textfield name="user.date" key="date"/><br>
密码 <s:password name="user.password" key="password"/>
<s:submit/>
</s:form>
<div class="varcodeinput">
验证码: <input type="text" id="code" name="code" οnfοcus="showCode();" οnclick="showCode();" size="4" maxlength="4"/>
[ 点击输入框获取验证码,不区分大小写 ]
</div>
<div class="varcode" style="display:none">
<img src="RandImg" id="randimg" />
<a href="javascript:refresh()" title="看不清左边的字符?点下换个!">看不清?换一个</a>
</div>
</body>
</html>