zoukankan      html  css  js  c++  java
  • 验证码的生成和验证

    大多网站登录时需要输入一个验证码,这主要是基于安全性方面的考虑。在这里将详细的说明一下验证码的生成和验证。

    首先是java文件(这段java主要写了验证码图片的生成及各种特效,比如旋转、干扰线、噪点等,并将其用流的方式传到前端页面):

    package com.servlet;
    import java.awt.BasicStroke;
    import java.awt.Color; 
    import java.awt.Font; 
    import java.awt.Graphics; 
    import java.awt.Graphics2D;
    import java.awt.Stroke;
    import java.awt.image.BufferedImage; 
    import java.io.IOException; 
    import java.util.Random; 
    import javax.imageio.ImageIO; 
    import javax.servlet.ServletException; 
    import javax.servlet.ServletOutputStream; 
    import javax.servlet.http.HttpServlet; 
    import javax.servlet.http.HttpServletRequest; 
    import javax.servlet.http.HttpServletResponse; 
    import javax.servlet.http.HttpSession; 
    
    public class ImageServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response) 
       throws ServletException, IOException { 
                doPost(request, response); 
    } 
    public void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
      int width=100;//验证码图片宽度 
      int height=40;//验证码图片高度 
      BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR); 
      Graphics g=image.getGraphics(); 
      Graphics2D g2d = (Graphics2D) g; 
      Random random=new Random();
      g.setColor(Color.white);//背景颜色(或getRandColor(160,250)) 
      g.fillRect(0, 0, width, height);//画背景 
      //g.setColor(getRandColor(0,255));//边框颜色 
      //      g.drawRect(0, 0, width-1, height-1);//画边框 
    
    // 随机产生20条干扰线,使图象中的认证码不易被其它程序探测到 
      g.setColor(getRandColor(160,200));  
      //Stroke stroke=new BasicStroke(3.0f);//设置线宽为3.0
      for(int i=0;i<20;i++){ 
       int x=random.nextInt(width); 
       int y=random.nextInt(height); 
       int x1=random.nextInt(20); 
       int y1=random.nextInt(20); 
       g.drawLine(x,y,x+x1,y+y1);
       //g2d.setStroke(stroke);
      } 
    
    // 随机产生20点,使图象中的认证码不易被其它程序探测到  
      g.setColor(getRandColor(160,200)); 
      for(int i=0;i<20;i++){ 
       int x=random.nextInt(width); 
       int y=random.nextInt(height); 
       g.drawLine(x, y, x, y); 
      } 
    
    //随机生成不同的字体、字体样式和字体大小
      String[] fontName = {"微软雅黑","黑体","Georgia","Verdana","Arial","Comic Sans MS","Lucida Console"};
      int [] fontEffect = {Font.PLAIN, Font.ITALIC, Font.BOLD};
      int [] fontSize = {28, 30, 32, 26};
      Font[] fonts = new Font[fontName.length*fontEffect.length*fontSize.length];
      int fontsIndex=0;
      for(String str: fontName){
          for(int effect: fontEffect){
              for(int size : fontSize){
                  Font font = new Font(str, effect, size);
                  fonts[fontsIndex]=font;
                  fontsIndex = fontsIndex +1;
              }
          }
      }
      String s="abcdefghijknpqrstuvxyzABCDEFGHJKLNPQRSTUVXYZ23456789"; // 设置备选验证码
      String sRand=""; 
            // 用随机产生的颜色将验证码绘制到图像中。
      int length = 4;  // 设置默认生成4个验证码
      for(int i=0;i<length;i++){
      g.setColor(new Color(20+random.nextInt(110), 20+random.nextInt(110), 20+random.nextInt(110))); // 生成随机颜色(因为是做前景,所以偏深)
          g.setFont(fonts[random.nextInt(fonts.length)]);  //调用上方的随机字体
       String ch=String.valueOf(s.charAt(random.nextInt(s.length()))); 
    
    //设置字体旋转
       int zhuan = random.nextInt(20);
       int fzhuan = -random.nextInt(20);
          g2d.rotate(Math.toRadians(zhuan),25*(i-1),20);     /// 坐标系顺时针转
          g2d.rotate(Math.toRadians(fzhuan),25*(i-1),20);    /// 坐标系逆时针转
      
          sRand+=ch; 
         g.drawString(ch, 18 * i + 15, 30); //将认证码用 drawString 函数显示到图象里
    
       g2d.rotate(Math.toRadians(-1*zhuan),25*(i-1),20);
       g2d.rotate(Math.toRadians(-1*fzhuan),25*(i-1),20);
      } 
      //将生成的字符串存储在session中 
      HttpSession session=request.getSession();   
      
    //在认证码的上端画一条不规则的线
      int visit[] = new int[6];  
      for (int i = 0; i < visit.length; i++) {  
          visit[i] = 1 + (int) (Math.random() * 10);  
      }
      int visitValue = 0;  
     g.setColor(Color.BLACK);  
     int drawHigh[] = new int[6];  
     int drawwidth[] = new int[6];  
     //折点坐标  
     for (int i = 0; i < 6; i++) {  
         drawHigh[i] = 40 - (int) (Math.ceil(visit[i] * 3.8));  
         drawwidth[i] = 5 + i * 17;  
     }  
     //g2d.setXORMode(Color.WHITE); 
      g2d.setStroke(new BasicStroke(3.0f));  //折线粗细
      g2d.setPaint(Color.gray);//折线的颜色 
      g2d.drawPolyline(drawwidth, drawHigh, 6);  //画折线  
     
      session.setAttribute("checkCode", sRand); 
      g.dispose();//图像生效 
      //禁止图像缓存 
      response.setHeader("Pragma", "No-cache"); 
      response.setHeader("Cache-Control", "no-cache"); 
      response.setDateHeader("Expires", 0);   
      response.setContentType("image/jpeg"); 
      //创建二进制的输出流 
      ServletOutputStream sos=response.getOutputStream(); 
            // 将图像输出到Servlet输出流中。 
            ImageIO.write(image, "jpeg", sos); 
            sos.flush(); 
            sos.close(); 
    } 
    public Color getRandColor(int lower,int upper){ 
          Random random = new Random(); 
          if(upper>255) 
           upper=255; 
          if(upper<1) 
           upper=1; 
          if(lower<1) 
           lower=1; 
          if(lower>255) 
           lower=255; 
          int r=lower+random.nextInt(upper-lower); 
          int g=lower+random.nextInt(upper-lower); 
          int b=lower+random.nextInt(upper-lower); 
          return new Color(r,g,b); 
        } 
    } 

    然后是前端的jsp展示页面(这里主要是写了一个方法来调用后端,将生成的验证码图片展示出来)

    <%@ 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>验证码的生成和验证</title>  
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
    
        <script type="text/javascript"  src="http://code.jquery.com/jquery-1.9.1.js"></script>
        <script type="text/javascript" language="javascript"> 
              function changeImg(){
                  $("#img").attr("src", "ImageServlet?time="+new Date());
            } 
              $(function(){
                   $("#button").click(function(){
                      changeImg();
                      var v_inputCode = document.getElementById("validate").value.toLowerCase();
                      if(v_inputCode == ""){
                          alert("请输入验证码");
                      }else{
                          $.post("<%=basePath%>test.htm",{inputCode:v_inputCode},
                        function(data){
                            data = $.parseJSON(data);
                            if(data.test== 1){
                                alert("请输入正确的验证码");
                            }else{
                                alert("验证码输入正确");
                                location.href='../jsp/index.html';//跳转页面
                            }
                          });
                      }
                });
              });
        </script> 
     </head>
      
     <body>
        <form  action="#"> 
            <table>
                <caption>验证码测试</caption>
                <tr>
                    <td>验证码</td>
                    <td colspan="2">
                        <input type="text" id="validate" />
                        <a href='javascript:changeImg();' title="看不清请点我" >
                            <img id="img" align="middle" src="ImageServlet" />
                        </a>
                    </td>
                </tr>
                <tr>
                    <td colspan="2"><input id="button" type="button" value="查&nbsp;&nbsp;询" /></td>
                </tr>
             </table>
        </form>
    </body>  
    </html>

    最后是验证(这里主要是将前端传入的用户输入的验证码与session中的验证码作对比,再返回给前端):

    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.annotation.Resource;
    import javax.mail.Session;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import net.sf.json.util.NewBeanInstanceStrategy;
    
    import org.omg.CORBA.PUBLIC_MEMBER;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.util.StringUtil;
    
    @Controller
    public class TestController {
        @Resource(name = "stringutil")
        private StringUtil stringUtil;
        
        @RequestMapping(value = "test.htm",method = RequestMethod.POST)
        public @ResponseBody Map<String, Object> querycard(HttpServletRequest request,
                HttpServletResponse response){
            Map<String, Object> result = new HashMap<String, Object>();
            String string = request.getSession().getAttribute("checkCode").toString();
            Map<String, Object> requestMap = stringUtil.getParamsForJqgrid(request);
            Map<String, Object> map = (Map<String, Object>) requestMap.get("paraMap");
            if((string.toLowerCase()).equals(map.get("inputCode").toString().toLowerCase())){//不区分大小写(将两个值都转换成小写再进行比较)
                result.put("test",0);//true
            }else {
                result.put("test",1);//false
            }
            return result;
        }
    }
  • 相关阅读:
    控件不能与用户交互的情况
    iOS常见的延时执行有2种方式
    网络-URLConnection & URLSession
    多线程-相关定义
    单例模式
    Targeted Resumes How to Write a Targeted Resume By Alison Doyle
    Email Cover Letter Format
    什么是目标、度量、KPI、维度和细分
    在美国公司架构中,LLC、LLP 和 Corporation 的区别何在?
    (转)给明年依然年轻的我们:欲望、外界、标签、天才、时间、人生目标、现实、后悔、和经历(500强高管力荐)
  • 原文地址:https://www.cnblogs.com/intime-dev/p/3593880.html
Copyright © 2011-2022 走看看