zoukankan      html  css  js  c++  java
  • 关于<验证码>的实现和执行流程 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);
            }
    
    
        }
    
    }


     

  • 相关阅读:
    Android 音视频开发(六): MediaCodec API 详解
    Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
    Android 音视频开发(四):使用 Camera API 采集视频数据
    Android 音视频开发(三):使用 AudioTrack 播放PCM音频
    Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件
    Android 音视频开发(一) : 通过三种方式绘制图片
    Android 使用View绘制文字(DrawText)技术总结
    Mac OS 中安装 autoconf 和 automake
    Android 自定义 View 绘制
    关于 Socket 设置 setSoTimeout 误用的说明
  • 原文地址:https://www.cnblogs.com/GoAhead/p/2828207.html
Copyright © 2011-2022 走看看