实现步骤:
验证码设置类;
页面;
登录验证中检测验证码;
Xml设置;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
代码:
页面;
<s:textfield name="rand" size="5" label="验证码"/>
<img src="rand.action" onclick="changeValidateCode(this)" title="点击图片刷新验证码"/>
<script type="text/javascript">
function changeValidateCode(obj) {
var timenow = new Date().getTime();
obj.src="rand.action?d="+timenow;
}
</script>
登录验证中检测验证码;
//从session中取出RandomCode.java 中生成的验证码random
String random=(String)(session.get(Struts2PortfolioConstants.CHECK_CODE));
rand = rand.toUpperCase();
if(random.equals(rand)){
...
}
private String rand; //省略get/set
Xml:
<action name="rand" class="service.commonality.RandomCode">
<result type="stream">
<param name="contentType">image/jpeg</param>
<param name="inputName">inputStream</param>
</result>
</action>
验证码设置类;
package service.commonality;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Calendar;
import java.util.Map;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import model.bean.Struts2PortfolioConstants;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;
public class RandomCode extends ActionSupport implements SessionAware{
private ByteArrayInputStream inputStream;
// 得到规定字符范围的随机字符串,长度自己确定
//Calendar.getInstance().getTimeInMillis() 获得相异的随机数;
private int codeCount = 5; //随机数长度;
private String CreateRandomCode(int codeCount){
String allChar = "2,3,4,5,6,7,8,9,Q,W,E,R,T,Y,U,P,A,S,D,F,G,H,J,K,L,Z,X,C,V,B,N,M";//32
String[] allCharArray = allChar.split(",");
String randomCode = "";
int temp = -1;
Random rand = new Random();
for (int i = 0; i < codeCount; i++)
{
if (temp != -1)
{
rand = new Random(i * temp * ((int)Calendar.getInstance().getTimeInMillis()));
}
int t = rand.nextInt(32);
if (temp == t)
{
return CreateRandomCode(codeCount);
}
temp = t;
randomCode += allCharArray[t];
}
return randomCode;
}
public String execute() throws Exception{
//在内存中创建图象
int width=70, height=20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//获取图形上下文
Graphics g = image.getGraphics();
//生成随机类
Random random = new Random();
//设定背景色
//g.setColor(Color.white);
g.setColor(getRandColor(200,250));
g.fillRect(0, 0, width, height);
//设定字体 ,字体的大小应该根据图片的高度来定。
g.setFont(new Font("Times New Roman",Font.PLAIN,18));
//画边框
//g.setColor(Color.gray);
//g.drawRect(0, 0, width - 1, height - 1);
//随机产生i条干扰线,使图象中的认证码不易被其它程序探测到
g.setColor(getRandColor(160,200));
//g.setColor(Color.gray); 可以直接指定。
for (int i=0;i<7;i++)
{
int x = random.nextInt(width);
int y = random.nextInt(height);
int xl = random.nextInt(12);
int yl = random.nextInt(12);
g.drawLine(x,y,x+xl,y+yl);
}
// 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。
//int red = 0, green = 0, blue = 0;
//red = random.nextInt(200);
//green = random.nextInt(200);
//blue = random.nextInt(200);
//取自定义的认证码
String sRand = CreateRandomCode(codeCount);
for (int i=0;i<codeCount;i++){
//用随机产生的颜色将验证码绘制到图像中。
//g.setColor(new Color(red, green, blue)); 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
//sRand,每次取一位
g.drawString(sRand.substring(i, i+1),13*i+6,16);
}
//将认证码存入session
session.put(Struts2PortfolioConstants.CHECK_CODE, sRand);
//图象生效
g.dispose();
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
ImageIO.write(image, "JPEG", imageOut);
imageOut.close();
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
this.setInputStream(input);
return SUCCESS;
}
/*
* 给定范围获得随机颜色
*/
private Color getRandColor(int fc,int bc){
Random random = new Random();
if(fc>255) fc=255;
if(bc>255) bc=255;
int r=fc+random.nextInt(bc-fc);
int g=fc+random.nextInt(bc-fc);
int b=fc+random.nextInt(bc-fc);
return new Color(r,g,b);
}
public void setInputStream(ByteArrayInputStream inputStream) {
this.inputStream = inputStream;
}
public ByteArrayInputStream getInputStream() {
return inputStream;
}
private Map session;
public void setSession(Map session) {
// TODO Auto-generated method stub
this.session = session;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
参考:
http://tmq.iteye.com/blog/286022 这个的实现很好,没问题。