struts2 图片验证码

时间:2021-12-06 10:47:59
第一次做java项目现在遇到了图片验证码的问题 点击图片更新验证码 点击提交的时候验证
、现在不知道怎么做 大家还给出个主意最好有实例!我要的是struts2 ,action , jsp. 不要servlet的只要这三个的配合的
我说的不是很专业 就是在struts。xml配置好action的那种 大家帮帮忙!

6 个解决方案

#1


图片验证码网上还不是大把啊,你不想用人家写的就用现成的组件jcaptcha

#2


1、action类(相关的包省略)
public class ValidationCodeAction implements Action, SessionAware {
private Map<String, String> session;

public void setSession(Map session) {
this.session = session;
}

// 验证码图片的宽度。
private static final int WIDTH = 60;
// 验证码图片的高度。
private static final int HEIGHT = 20;
// 验证码的数量。
private static final int CODE_AMOUNT = 4;

// 验证码序列。
private static final char[] randomSequence = new char[] { 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2',
'3', '4', '5', '6', '7', '8', '9' };

// 保存验证码图像数据的字节数组
private byte[] imageBytes;

/**
 * 给定范围内获得随机颜色
 * 
 * @param fc
 * @param bc
 * @return
 */
private Color getRangeColor(int fc, int bc) {
Random random = new Random();
if (fc > 255)
fc = 200;
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);
}

/**
 * 产生验证码图像,将图像数据保存到字节数组中
 * 
 * @throws ImageFormatException
 * @throws IOException
 */
private void generateValidationCodeImage() throws ImageFormatException,
IOException {
// 输出验证码图像时要用到的数据
// 字体高度
int fontHeight;
// 验证码边框宽度和高度
int rectWidth, rectHeight;
// 验证码偏移量
int offsetWidth;
// 在图像中写入验证码的额外偏移。
int addition;
// 在图像中写入验证码时指定的高度。
int codeHight;

// 对输出验证码图像时要用到的数据进行初始化
fontHeight = HEIGHT - 2;
rectWidth = WIDTH - 1;
rectHeight = HEIGHT - 1;
offsetWidth = WIDTH / (CODE_AMOUNT + 1);
addition = offsetWidth / 2;
codeHight = HEIGHT - 4;

BufferedImage buffImg = new BufferedImage(WIDTH, HEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffImg.createGraphics();

// 创建一个随机数生成器类。
Random random = new Random();

// 设定背景色
g.setColor(getRangeColor(200, 250));

g.fillRect(0, 0, WIDTH, HEIGHT);

// 创建字体,字体的大小应该根据图片的高度来定。
Font font = new Font("Times New Roman", Font.PLAIN, fontHeight);
// 设置字体。
g.setFont(font);

// 画边框。
g.setColor(Color.BLACK);
g.drawRect(0, 0, rectWidth, rectHeight);

// 随机产生160条干扰线,使图象中的认证码不易被其它程序探测到。
g.setColor(getRangeColor(160, 200));
for (int i = 0; i < 160; 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);
}

// sb用于保存随机产生的验证码,以便用户登录后进行验证。
StringBuffer sb = new StringBuffer();

int red = 0, green = 0, blue = 0;

// 随机产生指定位数的验证码。
for (int i = 0; i < CODE_AMOUNT; i++) {
// 得到随机产生的验证码。
int index = random.nextInt(35);
String strRand = String.valueOf(randomSequence[index]);

// 将产生的验证码组合在一起。
sb.append(strRand);

// 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。
red = random.nextInt(110);
green = random.nextInt(50);
blue = random.nextInt(50);

// 用随机产生的颜色将验证码绘制到图像中。
g.setColor(new Color(20 + red, 20 + green, 20 + blue));
g.drawString(strRand, offsetWidth * i + addition, codeHight);

}
// 将验证码保存到Session中。
session.put("validationCode", sb.toString());

// 创建ByteArrayOutputStream对象
ByteArrayOutputStream baos = new ByteArrayOutputStream();

// 将验证码图像按照jpeg格式输出到ByteArrayOutputStream中。
ImageIO.write(buffImg, "jpeg", baos);

// 获取保存了图像数据的字节数组
imageBytes = baos.toByteArray();
baos.close();
}

public String execute() throws Exception {
generateValidationCodeImage();
return SUCCESS;
}

// 用于向自定义结果返回图像MIME类型
public String getContentType() {
return "image/jpeg";
}

// 用于向自定义结果返回图像数据的长度
public int getContentLength() {
return imageBytes.length;
}

// 用于向自定义结果返回图像数据
public byte[] getImageInBytes() {
return imageBytes;
}

}
2、validator类
public class ValidationCodeValidator extends FieldValidatorSupport {
// 接收Session中的验证码
private String sessionValidationCode;
// 指示是否删除字符串首尾的空格
private boolean trim = true;

public String getSessionValidationCode() {
return sessionValidationCode;
}

// 配置验证规则时,将保存在session中的验证码传递进来
public void setSessionValidationCode(String sessionValidationCode) {
this.sessionValidationCode = sessionValidationCode;
}

public boolean isTrim() {
return trim;
}

public void setTrim(boolean trim) {
this.trim = trim;
}

public void validate(Object object) throws ValidationException {
Object objValidateCode = getFieldValue(sessionValidationCode, object);

// 得到字段名
String fieldName = getFieldName();
// 得到字段的值
String fieldValue = (String) getFieldValue(fieldName, object);

// 如果字段值为null,直接返回
if (fieldValue == null)
return;

// 如果trim为ture,则删除字段值首尾的空格
if (trim)
fieldValue = fieldValue.trim();

// 如果字段值为"",直接返回
if (fieldValue.length() == 0)
return;

// 判断字段值是否和session中的验证码相等,如果不相等,则添加字段错误消息
if (!fieldValue.equals(objValidateCode)) {
addFieldError(fieldName, object);
}
}
}
3、jsp页面(给出一个例子)
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<s:head />
</head>
<body>
<s:form action="register" method="post">
<s:actionerror />
<s:textfield name="user.username" label="用户名" required="true" />
<br />
<s:password name="user.password" label="密码" required="true" />
<br />
<s:password name="user.repassword" label="重复密码" required="true" />
<br />
<s:textfield name="user.email" label="邮件地址" required="true" />
<tr>
<td>
<label for="register_validationCode">
<s:text name="验证码" />
</label>
</td>
<td>
<s:textfield name="validationCode" theme="simple" />
<img src="<s:url action='validationCode'/>" />
</td>
</tr>
<tr>
<td>
<s:submit value="注册" theme="simple" />
</td>
<td>
<s:reset value="重填" theme="simple" />
</td>
</tr>
</s:form>
</body>
</html>
其他的自己写吧!

#3


struts2里进行验证码验证还不是用的session,你不使用servlet的还使用什么的?输出图片本身就一个jsp ,网上搜jsp生成验证码,一大堆的。

生成的验证码数字都是存放到session中的,你进行验证时始终要使用session进行对比。在哪个框架中都是一样的

#4


我现在生成的图片为什么在页面上显示不出来!

#5


恩 是放在session的!谢谢楼上了!

#6


为什么不把session写到execute()方法中?怎么修改?
action已经继承了ActionSupport,再怎么继承FieldValidatorSupport?
如何在LoginAction中判断输入的验证码是否正确?LoginAction需要实现这里面的什么方法?

#1


图片验证码网上还不是大把啊,你不想用人家写的就用现成的组件jcaptcha

#2


1、action类(相关的包省略)
public class ValidationCodeAction implements Action, SessionAware {
private Map<String, String> session;

public void setSession(Map session) {
this.session = session;
}

// 验证码图片的宽度。
private static final int WIDTH = 60;
// 验证码图片的高度。
private static final int HEIGHT = 20;
// 验证码的数量。
private static final int CODE_AMOUNT = 4;

// 验证码序列。
private static final char[] randomSequence = new char[] { 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2',
'3', '4', '5', '6', '7', '8', '9' };

// 保存验证码图像数据的字节数组
private byte[] imageBytes;

/**
 * 给定范围内获得随机颜色
 * 
 * @param fc
 * @param bc
 * @return
 */
private Color getRangeColor(int fc, int bc) {
Random random = new Random();
if (fc > 255)
fc = 200;
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);
}

/**
 * 产生验证码图像,将图像数据保存到字节数组中
 * 
 * @throws ImageFormatException
 * @throws IOException
 */
private void generateValidationCodeImage() throws ImageFormatException,
IOException {
// 输出验证码图像时要用到的数据
// 字体高度
int fontHeight;
// 验证码边框宽度和高度
int rectWidth, rectHeight;
// 验证码偏移量
int offsetWidth;
// 在图像中写入验证码的额外偏移。
int addition;
// 在图像中写入验证码时指定的高度。
int codeHight;

// 对输出验证码图像时要用到的数据进行初始化
fontHeight = HEIGHT - 2;
rectWidth = WIDTH - 1;
rectHeight = HEIGHT - 1;
offsetWidth = WIDTH / (CODE_AMOUNT + 1);
addition = offsetWidth / 2;
codeHight = HEIGHT - 4;

BufferedImage buffImg = new BufferedImage(WIDTH, HEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = buffImg.createGraphics();

// 创建一个随机数生成器类。
Random random = new Random();

// 设定背景色
g.setColor(getRangeColor(200, 250));

g.fillRect(0, 0, WIDTH, HEIGHT);

// 创建字体,字体的大小应该根据图片的高度来定。
Font font = new Font("Times New Roman", Font.PLAIN, fontHeight);
// 设置字体。
g.setFont(font);

// 画边框。
g.setColor(Color.BLACK);
g.drawRect(0, 0, rectWidth, rectHeight);

// 随机产生160条干扰线,使图象中的认证码不易被其它程序探测到。
g.setColor(getRangeColor(160, 200));
for (int i = 0; i < 160; 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);
}

// sb用于保存随机产生的验证码,以便用户登录后进行验证。
StringBuffer sb = new StringBuffer();

int red = 0, green = 0, blue = 0;

// 随机产生指定位数的验证码。
for (int i = 0; i < CODE_AMOUNT; i++) {
// 得到随机产生的验证码。
int index = random.nextInt(35);
String strRand = String.valueOf(randomSequence[index]);

// 将产生的验证码组合在一起。
sb.append(strRand);

// 产生随机的颜色分量来构造颜色值,这样输出的每位数字的颜色值都将不同。
red = random.nextInt(110);
green = random.nextInt(50);
blue = random.nextInt(50);

// 用随机产生的颜色将验证码绘制到图像中。
g.setColor(new Color(20 + red, 20 + green, 20 + blue));
g.drawString(strRand, offsetWidth * i + addition, codeHight);

}
// 将验证码保存到Session中。
session.put("validationCode", sb.toString());

// 创建ByteArrayOutputStream对象
ByteArrayOutputStream baos = new ByteArrayOutputStream();

// 将验证码图像按照jpeg格式输出到ByteArrayOutputStream中。
ImageIO.write(buffImg, "jpeg", baos);

// 获取保存了图像数据的字节数组
imageBytes = baos.toByteArray();
baos.close();
}

public String execute() throws Exception {
generateValidationCodeImage();
return SUCCESS;
}

// 用于向自定义结果返回图像MIME类型
public String getContentType() {
return "image/jpeg";
}

// 用于向自定义结果返回图像数据的长度
public int getContentLength() {
return imageBytes.length;
}

// 用于向自定义结果返回图像数据
public byte[] getImageInBytes() {
return imageBytes;
}

}
2、validator类
public class ValidationCodeValidator extends FieldValidatorSupport {
// 接收Session中的验证码
private String sessionValidationCode;
// 指示是否删除字符串首尾的空格
private boolean trim = true;

public String getSessionValidationCode() {
return sessionValidationCode;
}

// 配置验证规则时,将保存在session中的验证码传递进来
public void setSessionValidationCode(String sessionValidationCode) {
this.sessionValidationCode = sessionValidationCode;
}

public boolean isTrim() {
return trim;
}

public void setTrim(boolean trim) {
this.trim = trim;
}

public void validate(Object object) throws ValidationException {
Object objValidateCode = getFieldValue(sessionValidationCode, object);

// 得到字段名
String fieldName = getFieldName();
// 得到字段的值
String fieldValue = (String) getFieldValue(fieldName, object);

// 如果字段值为null,直接返回
if (fieldValue == null)
return;

// 如果trim为ture,则删除字段值首尾的空格
if (trim)
fieldValue = fieldValue.trim();

// 如果字段值为"",直接返回
if (fieldValue.length() == 0)
return;

// 判断字段值是否和session中的验证码相等,如果不相等,则添加字段错误消息
if (!fieldValue.equals(objValidateCode)) {
addFieldError(fieldName, object);
}
}
}
3、jsp页面(给出一个例子)
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<s:head />
</head>
<body>
<s:form action="register" method="post">
<s:actionerror />
<s:textfield name="user.username" label="用户名" required="true" />
<br />
<s:password name="user.password" label="密码" required="true" />
<br />
<s:password name="user.repassword" label="重复密码" required="true" />
<br />
<s:textfield name="user.email" label="邮件地址" required="true" />
<tr>
<td>
<label for="register_validationCode">
<s:text name="验证码" />
</label>
</td>
<td>
<s:textfield name="validationCode" theme="simple" />
<img src="<s:url action='validationCode'/>" />
</td>
</tr>
<tr>
<td>
<s:submit value="注册" theme="simple" />
</td>
<td>
<s:reset value="重填" theme="simple" />
</td>
</tr>
</s:form>
</body>
</html>
其他的自己写吧!

#3


struts2里进行验证码验证还不是用的session,你不使用servlet的还使用什么的?输出图片本身就一个jsp ,网上搜jsp生成验证码,一大堆的。

生成的验证码数字都是存放到session中的,你进行验证时始终要使用session进行对比。在哪个框架中都是一样的

#4


我现在生成的图片为什么在页面上显示不出来!

#5


恩 是放在session的!谢谢楼上了!

#6


为什么不把session写到execute()方法中?怎么修改?
action已经继承了ActionSupport,再怎么继承FieldValidatorSupport?
如何在LoginAction中判断输入的验证码是否正确?LoginAction需要实现这里面的什么方法?