关于<验证码>的实现和执行流程 http://www.cnblogs.com/androidhtml5/archive/2012/05/19/2533650.html

验证码是一个很常见的一个功能,验证码可以防止黑客通过某种手段无间隔的注册等等

验证码是通过服务器端生成的一张图片,传到客户端

具体实现步骤(流程):

1)由服务器端比如servlet,随机产生几个字符数字等等,把这几个字符拼接成一个字符串,存到session域中

2)以图片的方式传给客户端,验证码上的具体值是在服务器端验证的,如果具体值在客户端验证的话,恐怕不太方便比如第一次访问静态登录界面的话,去取session的值是为空的,除非你再次刷新整个页面

3)客户端对验证码,验证是否为空,输入的字符的长度是否达到标准,

4)把输入的验证码传到服务器端,服务端在session中取到值,做具体判断

5)根据输入对否,跳转到另一界面,如果输入错误,一般跳回当前界面,验证码改变又被刷新一次

具体实现的页面:

产生验证码的 Response_3类  参考-------->点击打开链接

package cn.response;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.PrintWriter;
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;

//输出随机认证码图片
public class Response_3 extends HttpServlet {

    private static final int WIDTH=120, HEIGHT=50;
    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        //创建一幅图形
        BufferedImage image = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        
        //1.设置背景色
        setBackGround(g);
        
        //2.设置边框
        setBorder(g);
        
        //3.画干扰线
        drawRandomLine(g);
        
        //4.写随机数  返回  具体的验证值 
        String validateValue = drawRandomNum((Graphics2D)g);
        System.out.println("验证码:"+validateValue);
        //把验证码的具体值 存到session中
        request.getSession().setAttribute("validateValue", validateValue);
        
        //5.图形写给浏览器
        
        //控制浏览器缓存      System.currentTimeMillis() 获取当前时间 
        //response.setDateHeader("Expires",System.currentTimeMillis() + 1000*3600); //缓存1小时
        
        //控制浏览器不要缓存数据
        response.setDateHeader("Expires", -1); 
        response.setHeader("cache-control", "no-cache");
        response.setHeader("pragma", "no-cache");
        
        response.setContentType("image/jpeg");//告诉浏览器用什么方式打开
        //把图形以JPG的格式存到流中然后调用 ImageIO.write输到浏览器 
        ImageIO.write(image,"jpg",response.getOutputStream());
        
    }
    
    private void setBackGround(Graphics g)
    {
        g.setColor(Color.lightGray);//设置背景色
        g.fillRect(0, 0, WIDTH, HEIGHT);//让颜色去填充这个矩形
        
    }
    
    private void setBorder(Graphics g)
    {
        //设置边框的颜色 随机出现
        if(0 == new Random().nextInt(3))
        {
            g.setColor(Color.cyan);//设置边框颜色
        }
        else if(1 == new Random().nextInt(5))
        {
            g.setColor(Color.red);//设置边框颜色
        }
        else
        {
            g.setColor(Color.yellow);//设置边框颜色
        }
    
        g.drawRect(1, 1, WIDTH-2, HEIGHT-2);//绘制边框
    }
    
    private void drawRandomLine(Graphics g)
    {
        g.setColor(Color.green);
        for(int i=0; i<5; i++)
        {
            //随机获得初始坐标,和结束坐标
            int x1 = new Random().nextInt(WIDTH);//横坐标要在宽度之内
            int y1 = new Random().nextInt(HEIGHT);//纵坐标要在高度之内
            int x2 = new Random().nextInt(WIDTH);
            int y2 = new Random().nextInt(HEIGHT);
            
            g.drawLine(x1, y1, x2, y2);//画干扰线
        }
    }
    
    private String drawRandomNum(Graphics2D g)
    {
        String validateValue = "" ; // 具体验证码的值
        
        g.setColor(Color.red);
        g.setFont(new Font("宋体",Font.BOLD,28));//设置字体
        
        //汉字
        //String base="\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09";
        String base= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz" ;
        int x=5;
        //中文字体范围 [\u4e00-\u9fa5]
        for(int i=0; i<4; i++)
        {
            int theta = new Random().nextInt()%30;//获取-30到30的数
            //String x1 = new Random().nextInt(9)+""; 随机输出数字
            String ch = base.charAt( new Random().nextInt(base.length()) )+"";//获取字
    
            g.rotate(theta*Math.PI/180, x, 30);//设置旋转角度(弧度)
            g.drawString(ch, x, 30);//写字到方框内
            
            g.rotate(-theta*Math.PI/180, x, 30);//把位置旋转回去
            //g.drawString(x1, x, 20);
            x+=30;
            //g.drawString(x1, x, 20);
            //x+=30;
            validateValue = validateValue + ch ;
        }
        
        return validateValue;
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

    
    }

}

Myeclipse 环境下

这里当然还要在WEB-INF目录下,配一个web.xml
 

总结:

                控制浏览器要缓存

        response.setDateHeader("Expires",System.currentTimeMillis() + 1000*3600);注意:如果这句没添加     System.currentTimeMillis() 则没有缓存截止日期,默认是 1970年开始 缓存1小时,也就是过期了,所以System.currentTimeMillis() 这句的作用是获取当前日期时间,然后加上你要缓存的时间,1000代表1秒。

               控制浏览器不要缓存

        response.setDateHeader("Expires", -1); 或者 response.setDateHeader("Expires", 0); 都一样

        response.setHeader("cache-control", "no-cache");

        response.setHeader("pragma", "no-cache");

     这里设置了颜色,别忘了设置 把颜色填充,绘制边框,等等

       绘制边框:g.drawRect(1, 1, WIDTH-2, HEIGHT-2);// 边框的宽和高,都要比背景色的宽高小1,这个边框是从x=1,y=1 (起使坐标(1,1) )开始画的,本来是从x=0,y=0画的,但贴近最左边效果不好所以WIDTH-2, HEIGHT-2 要减2

     中文字体范围 [\u4e00-\u9fa5]

                   获取随机字符:String ch = base.charAt( new Random().nextInt(base.length()) )+""; 

               然后把字符转化为字符串

                注意 设置字的旋转角度,g.rotate(theta*Math.PI/180, x, 20);//设置旋转角度(一定要是弧度),把度转化为弧度(公式:theta*Math.PI/180 ;这个theta是度):int theta = new Random().nextInt()%30;//获取-30到30的数,

               当你旋转完,把字放到方框里去后,还得注意一点就是把旋转角度,旋转为初始状态,以便下一个字进行旋转

<%@ 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>
    <base href="<%=basePath%>">
    
    <title>My JSP 'ValidateLogin.jsp' starting page</title>
    
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->

  </head>

 <BODY style="background-color:66CCFF" >
 <table cellspacing="10"
 border=1 background="" align="center">
 <tr>
 <td>

 <b  style="font-size:20;color:green;" >会员--登录</b>
 <hr width=220 align=left>
  
  <form name=form1 Action="LoginServlet" method="get"  >
  

  
  <br />
   用户名:
   <input type="text" name="usename" value=543806053@qq.com size=19 maxlength=16 />
   <br />
   <br />
   密  码:
   <input type="password" name="password" maxlength=16 />
   <br /><br />
   认证码: <input type="text" name="validateValue" size=19  onblur="checkVlidte(this)"/><br>
   
   <img id="image" src="servlet/Response_3"/> 
   <a href="javascript:changeimage()" >看不清?换一张</a>
   <br /><br />

   
   <br /><br />
            <input type="submit" value="登录"/>
     <input type="reset" value="重置" />
   <hr width=220 align=left>
  </form>
  </td>
  </tr>

 </table>


  </body>
  
  <script type="text/javascript">
   function validate_required(field,alerttxt)
   {
        with(field)
        {
             
             /*if(value==null||value=="")
             {
                 alert(alerttxt);
                 return false ;
             }
             else   
                 return true ;
             */

             i = value.indexOf("@");  //邮箱认证
             j = value.lastIndexOf(".");
             if(i < 1 || j-i <2)
             {
                 alert(alerttxt) ;
                 return false ;
             }
             else
                 return true ;
        }
   }
   
   function password_validate (_pass,alerttxt)
   {
       with(_pass)
       {
            if(value!="")
               return true ;
            else
            { 
               alert(alerttxt) ;
               return false ;
            }
       }
   }


   function validate_form(thisform)
   {
        with(thisform)
        {
             if(validate_required(name1,"请输入有效的邮箱账号!") == false)
             {
                  name1.focus();
                  return false ;
             }

             if(password_validate(pass,"请输入正确的密码!") == false)
             {
                  pass.focus();
                  return false ;
             }
                  
        }
   }

  </script>

  <script type="text/javascript">

   function proving()
   {
       if(form1.pass.value!="")
          window.open("http://www.baidu.com/","_self");
       else
          window.open("http://www.google.com/","_self");

      
   }

  </script>

<!--认证码按钮脚本-->
  <script type="text/javascript">
      function changeimage()
      {
         var img = document.getElementById("image") ;
         if(img)
           img.src=img.src+ "?" + new Date().getTime();
      }

      function checkVlidte(object)
      {
          
          if(object.value.length != 4 )
          {
             alert("验证码错误!");

             //object.focus() ;//重新定位到该输入框
             //object.select() ;//把已有的内容选中
          }
      }

  </script>
  
</html>


服务器端验证,这里只对验证码进行验证

package cn.request;

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 LoginServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        this.doPost(request, response);


    }


    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        String usename = request.getParameter("usename");
        String password = request.getParameter("password");
        String validateValue = request.getParameter("validateValue");
        
        String vv = (String)request.getSession().getAttribute("validateValue");
        
        //把验证码全转为小写在进行比较
        if( (validateValue.toLowerCase()).equals(vv.toLowerCase()) )
        {
            response.sendRedirect("index.jsp");
        }
        else
        {
            request.getRequestDispatcher("ValidateLogin.jsp").forward(request, response);
        }


    }

}


 

原文地址:https://www.cnblogs.com/GoAhead/p/2828207.html