struts2登录验证码

折腾了两天的登录验证码终于折腾出来了,在此做个记录。

1、生成验证码图片的类VerificationCodeUtil.java,该类是网上找的,可以实现纯数字验证码、数字字母验证码、汉字数字验证码。

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.Random;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

/**
 * 验证码类,主要生成几种不同类型的验证码
 *  第一种:简单验证码,4位随机数字
 * 第二种:英文字符加数字的验证码
 * 第三种:像铁路订票系统一样的验证码
 *
 */
public class VerificationCodeUtil {
 private ByteArrayInputStream image;// 图像
 private String str;// 验证码
 private BufferedImage bufImage;
 private static final int WIDTH = 80;
 private static final int HEIGHT = 20;

 /**
  * 功能:获取一个验证码类的实例
  *
  * @return
  */
 public static VerificationCodeUtil Instance() {
  return new VerificationCodeUtil();
 }

 private VerificationCodeUtil() {
  BufferedImage image = new BufferedImage(WIDTH, HEIGHT,
    BufferedImage.TYPE_INT_RGB);
//  int randomNum = new Random().nextInt(3);
//  if (randomNum == 0) {
   initNumVerificationCode(image);//数字验证码
//  } else if (randomNum == 1) {
//   initLetterAndNumVerificationCode(image);//字母加数字验证码
//  } else {
//   initChinesePlusNumVerificationCode(image);//汉字加数字验证码
//  }
 }

 /**
  * 功能:设置第一种验证码的属性
  */
 public void initNumVerificationCode(BufferedImage image) {

  Random random = new Random(); // 生成随机类
  Graphics g = initImage(image, random);
  String sRand = "";
  for (int i = 0; i < 4; i++) {
   String rand = String.valueOf(random.nextInt(10));
   sRand += rand;
   // 将认证码显示到图象中
   g.setColor(new Color(20 + random.nextInt(110), 20 + random
     .nextInt(110), 20 + random.nextInt(110)));
   // 调用函数出来的颜色相同,可能是因为种子太接近,所以只能直接生成
   g.drawString(rand, 13 * i + 6, 16);
  }
  this.setStr(sRand);/* 赋值验证码 */
  // 图象生效
  g.dispose();
  this.setImage(drawImage(image));
  this.setBufImage(image);
 }

 /**
  * 功能:设置第二种验证码属性
  */
 public void initLetterAndNumVerificationCode(BufferedImage image) {

  Random random = new Random(); // 生成随机类
  Graphics g = initImage(image, random);
  String[] letter = { "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" };
  String sRand = "";
  for (int i = 0; i < 4; i++) {
   String tempRand = "";
   if (random.nextBoolean()) {
    tempRand = String.valueOf(random.nextInt(10));
   } else {
    tempRand = letter[random.nextInt(25)];
    if (random.nextBoolean()) {// 随机将该字母变成小写
     tempRand = tempRand.toLowerCase();
    }
   }
   sRand += tempRand;
   g.setColor(new Color(20 + random.nextInt(10), 20 + random
     .nextInt(110), 20 + random.nextInt(110)));
   g.drawString(tempRand, 13 * i + 6, 16);
  }
  this.setStr(sRand);/* 赋值验证码 */
  g.dispose(); // 图象生效
  this.setImage(drawImage(image));
  this.setBufImage(image);
 }

 /**
  * 功能:设置第三种验证码属性 即:肆+?=24
  */
 public  void initChinesePlusNumVerificationCode(BufferedImage image) {
  String[] cn = { "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "拾" };
  Random random = new Random(); // 生成随机类
  Graphics g = initImage(image, random);
  int x = random.nextInt(10) + 1;
  int y = random.nextInt(30);
  this.setStr(String.valueOf(y));
  g.setFont(new Font("楷体", Font.PLAIN, 14));// 设定字体
  g.setColor(new Color(20 + random.nextInt(10), 20 + random.nextInt(110),
    20 + random.nextInt(110)));
  g.drawString(cn[x - 1], 1 * 1 + 6, 16);
  g.drawString("+", 22, 16);
  g.drawString("?", 35, 16);
  g.drawString("=", 48, 16);
  g.drawString(String.valueOf(x + y), 61, 16);
  g.dispose(); // 图象生效
  this.setImage(drawImage(image));
        this.setBufImage(image);
 }

 public Graphics initImage(BufferedImage image, Random random) {
  Graphics g = image.getGraphics(); // 获取图形上下文
  g.setColor(getRandColor(200, 250));// 设定背景色
  g.fillRect(0, 0, WIDTH, HEIGHT);
  g.setFont(new Font("Times New Roman", Font.PLAIN, 14));// 设定字体
  g.setColor(getRandColor(160, 200)); // 随机产生165条干扰线,使图象中的认证码不易被其它程序探测到
  for (int i = 0; i < 165; 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);
  }
  return g;
 }

 public ByteArrayInputStream drawImage(BufferedImage image) {
  ByteArrayInputStream input = null;
  ByteArrayOutputStream output = new ByteArrayOutputStream();
  try {
   ImageOutputStream imageOut = ImageIO
     .createImageOutputStream(output);
   ImageIO.write(image, "JPEG", imageOut);
   imageOut.close();
   input = new ByteArrayInputStream(output.toByteArray());
  } catch (Exception e) {
   System.out.println("验证码图片产生出现错误:" + e.toString());
  }
  return input;
 }

 /*
  * 功能:给定范围获得随机颜色
  */
 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);
 }

 /**
  * 功能:获取验证码的字符串值
  *
  * @return
  */
 public String getVerificationCodeValue() {
  return this.getStr();
 }

 /**
  * 功能:取得验证码图片
  *
  * @return
  */
 public ByteArrayInputStream getImage() {
  return this.image;
 }

 public String getStr() {
  return str;
 }

 public void setStr(String str) {
  this.str = str;
 }

 public void setImage(ByteArrayInputStream image) {
  this.image = image;
 }

 public void setBufImage(BufferedImage bufImage) {
  this.bufImage = bufImage;
 }

 public BufferedImage getBufImage() {
  return bufImage;
 }
}

2、获取验证码图片的action。


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;

import com.goldpac.framework.utils.BaseAction;
import com.goldpac.framework.utils.VerificationCodeUtil;

@SuppressWarnings("serial")
public class RandomImageAction extends BaseAction{
 private ByteArrayInputStream inputStream;
 
 public String getRandomPictrue() throws IOException{
  VerificationCodeUtil vcu = VerificationCodeUtil.Instance(); 
  request.getSession().setAttribute("randomImage", vcu.getVerificationCodeValue()) ;
  System.out.println(vcu.getVerificationCodeValue());
  ByteArrayOutputStream output = new ByteArrayOutputStream(); 
        ImageOutputStream imageOut = ImageIO.createImageOutputStream(output);
        ImageIO.write(vcu.getBufImage(), "JPEG", imageOut); 
        imageOut.close(); 
        ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); 
        this.setInputStream(input); 
     return SUCCESS; 
 }
 
 public void setInputStream(ByteArrayInputStream inputStream) {
  this.inputStream = inputStream;
 }
 public ByteArrayInputStream getInputStream() {
  return inputStream;
 }
}

3、action的配置

<package name="randomImage"  extends="struts-default">
    <action name="randomImageAction_*" class="com.goldpac.pms.system.action.RandomImageAction" method="{1}">
    <result type="stream">
               <param name="contentType">image/jpeg</param>
               <param name="inputName">inputStream</param>
   </result>
    </action>
</package>

4、登录页面

<%@ page language="java" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3c.org/TR/1999/REC-html401-19991224/loose.dtd">

<html >
 <head>
  <title>验证码测试系统 Goldpac Project Data Management System</title>
  <link rel="stylesheet" type="text/css"
   href="${pageContext.request.contextPath}/stylesheets/application.css" media="all">
  <link rel="shortcut icon" href="favicon.ico" type="image/gif" />
  <script language="JavaScript" src="${pageContext.request.contextPath}/javascript/jquery-1.3.1.min.js"></script>
  <script type="text/javascript" src="${pageContext.request.contextPath}/javascript/jquery.js"></script>
  <script type="text/javascript" src="${pageContext.request.contextPath}/javascript/jquery.validate.js"></script>
  <script type="text/javascript">
  function changeValidateCode(obj) {    
           //获取当前的时间作为参数,无具体意义    
             var timenow = new Date().getTime();    
           //每次请求需要一个不同的参数,否则可能会返回同样的验证码    
           //这和浏览器的缓存机制有关系,也可以把页面设置为不缓存,这样就不用这个参数了。    
           obj.src="randomImageAction_getRandomPictrue?d="+timenow;    
        } 
   $().ready(function(){
    
    <s:if test='%{#request.tipMessage!=null}'>
     var $div=$("<div></div>");
     $div.attr("class","flash error");
     $div.text("<%= request.getAttribute("tipMessage") %>");
     $("#content").prepend($div);
    </s:if>


    $("#form1").validate({
     rules:{
      login:{
       required:true,
       maxlength:30
      },
      hashedPassword:{
       required:true,
       maxlength:30
      },
      randomImage:{
          required:true,
          maxlength:4
      }
     },
     messages:{
      login:{
       required:"请输入登录名",
       maxlength:"用户名过长"
      },
      hashedPassword:{
       required:"请输入密码",
       maxlength:"密码过长"
      },
      randomImage:{
          required:"请输入验证码",
          maxlength:"输入过长"
      }
     }
    });
    
   });
  </script>
  <STYLE type="text/css">
   #form1 label.error{
    margin-left: 0px;
    float:none;
    width:auto;
    color: red;
       font-style: italic;
   }
   #form1 input.error {
       border: 1px dotted red;
   }

   
  </STYLE>
 </head>
 <body>
  <div id="wrapper">
   <div id="wrapper2">
    <div id="top-menu"></div>
    <div id="header">
    <h1>验证码测试系统h1>
    <h1 style="font-size: 18px">Goldpac Project Data Management System</h1>
    </div>
    <div id="main" class="nosidebar">
     <div id="content">
      <div id="login-form">
      <s:form name="form1" id="form1" method="post" action="userAction_isLogin" namespace="/system" >
       <table>
       <tbody><tr>
           <td align="right"><label for="username">登录名:</label></td>
           <td align="left">
            <input name="login" tabIndex="1" id="login" type="text" size="20"/>
           </td>
       </tr>
       <tr>
           <td align="right"><label for="password" size="20">密码:</label></td>
           <td align="left">
            <input name="hashedPassword" tabIndex="2" id="hashedPassword" type="password" style="width: 95%"/>
           </td>
       </tr>
       <tr>
           <td></td>
           <td align="left">
           </td>
       </tr>
       
       <tr> 
                                <td align="right"><label>验证码</label></td> 
                               <td ><input type="text"  maxlength=4 name="randomImage" id="randomImage"></td> 
                              <td ><img alt="单击换一张" src="randomImageAction_getRandomPictrue"  οnclick="changeValidateCode(this)"/></td> 
                            </tr>
       
       <tr>
           <td align="left">
                   <a style="display:none" href="/account/lost_password">忘记密码</a>
           </td>
           <td align="right">
            <s:submit value="登录 »"></s:submit>
           </td>
       </tr>
       </tbody></table>
      </s:form>
      </div>
     </div>
    </div>
    
   </div>
  </div>
 </body>
</html>

5、登录验证码验证

String randomImage = request.getParameter("randomImage");
  if (randomImage
    .equals(request.getSession().getAttribute("randomImage"))) {

     //验证码正确,进行用户名密码验证

}else{

     //验证码错误,提示页面

}

6、如果你的系统配置有过滤器或者拦截器,注意不要过滤或者拦截了验证码,否则会导致图片不显示。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值