最近做验证码,参考网上案例,发现有不少问题,特意进行了修改和完善。

验证码生成器:

  1. import javax.imageio.ImageIO;    
  2. import java.awt.*;    
  3. import java.awt.image.BufferedImage;    
  4. import java.io.FileOutputStream;    
  5. import java.io.IOException;    
  6. import java.io.OutputStream;    
  7. import java.util.Date;    
  8. import java.util.Random;    
  9.     
  10. /**   
  11.  * 验证码生成器   
  12.  *   
  13.  * @author    
  14.  */    
  15. public class ValidateCode {    
  16.     // 图片的宽度。    
  17.     private int width = 160;    
  18.     // 图片的高度。    
  19.     private int height = 40;    
  20.     // 验证码字符个数    
  21.     private int codeCount = 5;    
  22.     // 验证码干扰线数    
  23.     private int lineCount = 150;    
  24.     // 验证码    
  25.     private String code = null;    
  26.     // 验证码图片Buffer    
  27.     private BufferedImage buffImg = null;    
  28.     
  29.     // 验证码范围,去掉0(数字)和O(拼音)容易混淆的(小写的1和L也可以去掉,大写不用了)    
  30.     private char[] codeSequence = {\’A\’, \’B\’, \’C\’, \’D\’, \’E\’, \’F\’, \’G\’, \’H\’, \’I\’, \’J\’,    
  31.             \’K\’, \’L\’, \’M\’, \’N\’, \’P\’, \’Q\’, \’R\’, \’S\’, \’T\’, \’U\’, \’V\’, \’W\’,    
  32.             \’X\’, \’Y\’, \’Z\’, \’1\’, \’2\’, \’3\’, \’4\’, \’5\’, \’6\’, \’7\’, \’8\’, \’9\’};    
  33.     
  34.     /**   
  35.      * 默认构造函数,设置默认参数   
  36.      */    
  37.     public ValidateCode() {    
  38.         this.createCode();    
  39.     }    
  40.     
  41.     /**   
  42.      * @param width  图片宽   
  43.      * @param height 图片高   
  44.      */    
  45.     public ValidateCode(int width, int height) {    
  46.         this.width = width;    
  47.         this.height = height;    
  48.         this.createCode();    
  49.     }    
  50.     
  51.     /**   
  52.      * @param width     图片宽   
  53.      * @param height    图片高   
  54.      * @param codeCount 字符个数   
  55.      * @param lineCount 干扰线条数   
  56.      */    
  57.     public ValidateCode(int width, int height, int codeCount, int lineCount) {    
  58.         this.width = width;    
  59.         this.height = height;    
  60.         this.codeCount = codeCount;    
  61.         this.lineCount = lineCount;    
  62.         this.createCode();    
  63.     }    
  64.     
  65.     public void createCode() {    
  66.         int x = 0fontHeight = 0codeY = 0;    
  67.         int red = 0green = 0blue = 0;    
  68.     
  69.         x = width / (codeCount + 2);//每个字符的宽度(左右各空出一个字符)    
  70.         fontHeight = height – 2;//字体的高度    
  71.         codeY = height – 4;    
  72.     
  73.         // 图像buffer    
  74.         buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);    
  75.         Graphics2D g = buffImg.createGraphics();    
  76.         // 生成随机数    
  77.         Random random = new Random();    
  78.         // 将图像填充为白色    
  79.         g.setColor(Color.WHITE);    
  80.         g.fillRect(0, 0, width, height);    
  81.         // 创建字体,可以修改为其它的    
  82.         Font font = new Font(“Fixedsys”, Font.PLAIN, fontHeight);    
  83. //        Font font = new Font(“Times New Roman”, Font.ROMAN_BASELINE, fontHeight);    
  84.         g.setFont(font);    
  85.     
  86.         for (int i = 0; i < lineCount; i++) {    
  87.             // 设置随机开始和结束坐标    
  88.             int xs = random.nextInt(width);//x坐标开始    
  89.             int ys = random.nextInt(height);//y坐标开始    
  90.             int xe = xs + random.nextInt(width / 8);//x坐标结束    
  91.             int ye = ys + random.nextInt(height / 8);//y坐标结束    
  92.     
  93.             // 产生随机的颜色值,让输出的每个干扰线的颜色值都将不同。    
  94.             red = random.nextInt(255);    
  95.             green = random.nextInt(255);    
  96.             blue = random.nextInt(255);    
  97.             g.setColor(new Color(red, green, blue));    
  98.             g.drawLine(xs, ys, xe, ye);    
  99.         }    
  100.     
  101.         // randomCode记录随机产生的验证码    
  102.         StringBuffer randomCode = new StringBuffer();    
  103.         // 随机产生codeCount个字符的验证码。    
  104.         for (int i = 0; i < codeCount; i++) {    
  105.             String strRand = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);    
  106.             // 产生随机的颜色值,让输出的每个字符的颜色值都将不同。    
  107.             red = random.nextInt(255);    
  108.             green = random.nextInt(255);    
  109.             blue = random.nextInt(255);    
  110.             g.setColor(new Color(red, green, blue));    
  111.             g.drawString(strRand, (i + 1) * x, codeY);    
  112.             // 将产生的四个随机数组合在一起。    
  113.             randomCode.append(strRand);    
  114.         }    
  115.         // 将四位数字的验证码保存到Session中。    
  116.         code = randomCode.toString();    
  117.     }    
  118.     
  119.     public void write(String path) throws IOException {    
  120.         OutputStream sos = new FileOutputStream(path);    
  121.         this.write(sos);    
  122.     }    
  123.     
  124.     public void write(OutputStream sos) throws IOException {    
  125.         ImageIO.write(buffImg, “png”, sos);    
  126.         sos.close();    
  127.     }    
  128.     
  129.     public BufferedImage getBuffImg() {    
  130.         return buffImg;    
  131.     }    
  132.     
  133.     public String getCode() {    
  134.         return code;    
  135.     }    
  136.     
  137.     /**   
  138.      * 测试函数,默认生成到d盘   
  139.      * @param args   
  140.      */    
  141.     public static void main(String[] args) {    
  142.         ValidateCode vCode = new ValidateCode(160,40,5,150);    
  143.         try {    
  144.             String path=“D:/”+new Date().getTime()+”.png”;    
  145.             System.out.println(vCode.getCode()+” >“+path);    
  146.             vCode.write(path);    
  147.         } catch (IOException e) {    
  148.             e.printStackTrace();    
  149.         }    
  150.     }    
  151. }    
import javax.imageio.ImageIO;  
import java.awt.*;  
import java.awt.image.BufferedImage;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.OutputStream;  
import java.util.Date;  
import java.util.Random;  

/**

  • 验证码生成器

  • @author
    */
    public class ValidateCode {
    // 图片的宽度。
    private int width = 160;
    // 图片的高度。
    private int height = 40;
    // 验证码字符个数
    private int codeCount = 5;
    // 验证码干扰线数
    private int lineCount = 150;
    // 验证码
    private String code = null;
    // 验证码图片Buffer
    private BufferedImage buffImg = null;

    // 验证码范围,去掉0(数字)和O(拼音)容易混淆的(小写的1和L也可以去掉,大写不用了)
    private char[] codeSequence = {\’A\’, \’B\’, \’C\’, \’D\’, \’E\’, \’F\’, \’G\’, \’H\’, \’I\’, \’J\’,
    \’K\’, \’L\’, \’M\’, \’N\’, \’P\’, \’Q\’, \’R\’, \’S\’, \’T\’, \’U\’, \’V\’, \’W\’,
    \’X\’, \’Y\’, \’Z\’, \’1\’, \’2\’, \’3\’, \’4\’, \’5\’, \’6\’, \’7\’, \’8\’, \’9\’};

    /**

    • 默认构造函数,设置默认参数
      */
      public ValidateCode() {
      this.createCode();
      }

    /**

    • @param width 图片宽
    • @param height 图片高
      */
      public ValidateCode(int width, int height) {
      this.width = width;
      this.height = height;
      this.createCode();
      }

    /**

    • @param width 图片宽
    • @param height 图片高
    • @param codeCount 字符个数
    • @param lineCount 干扰线条数
      */
      public ValidateCode(int width, int height, int codeCount, int lineCount) {
      this.width = width;
      this.height = height;
      this.codeCount = codeCount;
      this.lineCount = lineCount;
      this.createCode();
      }

    public void createCode() {
    int x = 0, fontHeight = 0, codeY = 0;
    int red = 0, green = 0, blue = 0;

     x = width / (codeCount + 2);//每个字符的宽度(左右各空出一个字符)  
     fontHeight = height - 2;//字体的高度  
     codeY = height - 4;  
    
     // 图像buffer  
     buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
     Graphics2D g = buffImg.createGraphics();  
     // 生成随机数  
     Random random = new Random();  
     // 将图像填充为白色  
     g.setColor(Color.WHITE);  
     g.fillRect(0, 0, width, height);  
     // 创建字体,可以修改为其它的  
     Font font = new Font("Fixedsys", Font.PLAIN, fontHeight);  
    

// Font font = new Font(“Times New Roman”, Font.ROMAN_BASELINE, fontHeight);
g.setFont(font);

    for (int i = 0; i &lt; lineCount; i++) {  
        // 设置随机开始和结束坐标  
        int xs = random.nextInt(width);//x坐标开始  
        int ys = random.nextInt(height);//y坐标开始  
        int xe = xs + random.nextInt(width / 8);//x坐标结束  
        int ye = ys + random.nextInt(height / 8);//y坐标结束  

        // 产生随机的颜色值,让输出的每个干扰线的颜色值都将不同。  
        red = random.nextInt(255);  
        green = random.nextInt(255);  
        blue = random.nextInt(255);  
        g.setColor(new Color(red, green, blue));  
        g.drawLine(xs, ys, xe, ye);  
    }  

    // randomCode记录随机产生的验证码  
    StringBuffer randomCode = new StringBuffer();  
    // 随机产生codeCount个字符的验证码。  
    for (int i = 0; i &lt; codeCount; i++) {  
        String strRand = String.valueOf(codeSequence[random.nextInt(codeSequence.length)]);  
        // 产生随机的颜色值,让输出的每个字符的颜色值都将不同。  
        red = random.nextInt(255);  
        green = random.nextInt(255);  
        blue = random.nextInt(255);  
        g.setColor(new Color(red, green, blue));  
        g.drawString(strRand, (i + 1) * x, codeY);  
        // 将产生的四个随机数组合在一起。  
        randomCode.append(strRand);  
    }  
    // 将四位数字的验证码保存到Session中。  
    code = randomCode.toString();  
}  

public void write(String path) throws IOException {  
    OutputStream sos = new FileOutputStream(path);  
    this.write(sos);  
}  

public void write(OutputStream sos) throws IOException {  
    ImageIO.write(buffImg, "png", sos);  
    sos.close();  
}  

public BufferedImage getBuffImg() {  
    return buffImg;  
}  

public String getCode() {  
    return code;  
}  

/** 
 * 测试函数,默认生成到d盘 
 * @param args 
 */  
public static void main(String[] args) {  
    ValidateCode vCode = new ValidateCode(160,40,5,150);  
    try {  
        String path="D:/"+new Date().getTime()+".png";  
        System.out.println(vCode.getCode()+" &gt;"+path);  
        vCode.write(path);  
    } catch (IOException e) {  
        e.printStackTrace();  
    }  
}  

}

下面是页面JS调用验证码

[javascript] view plain copy

print?

  1. // 刷新图片    
  2.         function changeImg() {    
  3.             var imgSrc = $(“#imgObj”);    
  4.             var url = imgSrc.attr(“src”);   
  5.             imgSrc.attr(“src”, changeUrl(url));    
  6.         }    
  7.         //为了使每次生成图片不一致,即不让浏览器读缓存,所以需要加上时间戳    
  8.         function changeUrl(url) {    
  9.             var timestamp = (new Date()).valueOf();    
  10.             var index = url.indexOf(“?”);  
  11.             console.log(index);   
  12.             if (index > 0) {    
  13.                 url = url.substring(0, url.indexOf(“?”));    
  14.             }  
  15.             console.log(url);  
  16.             if ((url.indexOf(“&”) > 0)) {    
  17.                 url = url + “×tamp=” + timestamp;    
  18.                 console.log(url);  
  19.             } else {    
  20.                 url = url + “?timestamp=” + timestamp;  
  21.                 console.log(url);  
  22.                 }    
  23.             return url;    
  24.         }  
 // 刷新图片
function changeImg() {
var imgSrc = $("#imgObj");
var url = imgSrc.attr("src");
imgSrc.attr("src", changeUrl(url));
}
//为了使每次生成图片不一致,即不让浏览器读缓存,所以需要加上时间戳
function changeUrl(url) {
var timestamp = (new Date()).valueOf();
var index = url.indexOf("?");
console.log(index);
if (index > 0) {
url = url.substring(0, url.indexOf("?"));
}
console.log(url);
if ((url.indexOf("&") > 0)) {
url = url + "×tamp=" + timestamp;
console.log(url);
} else {
url = url + "?timestamp=" + timestamp;
console.log(url);
}
return url;
}

下面是controller层输出验证码

  1. /  
  2.   响应验证码页面  
  3.   @return  
  4.  */    
  5. @RequestMapping(value=“/validateCode”)    
  6. public String validateCode(HttpServletRequest request,HttpServletResponse response) throws Exception{    
  7.     // 设置响应的类型格式为图片格式    
  8.     response.setContentType(“image/jpeg”);    
  9.     //禁止图像缓存。    
  10.     response.setHeader(“Pragma”“no-cache”);    
  11.     response.setHeader(“Cache-Control”“no-cache”);    
  12.     response.setDateHeader(“Expires”0);    
  13.     
  14.     HttpSession session = request.getSession();    
  15.     
  16.     ValidateCode vCode = new ValidateCode(120,40,5,100);    
  17.     session.setAttribute(“code”, vCode.getCode());    
  18.     vCode.write(response.getOutputStream());    
  19.     return null;    
  20. }    
/

  • 响应验证码页面

  • @return
    */
    @RequestMapping(value=”/validateCode”)
    public String validateCode(HttpServletRequest request,HttpServletResponse response) throws Exception{
    // 设置响应的类型格式为图片格式
    response.setContentType(“image/jpeg”);
    //禁止图像缓存。
    response.setHeader(“Pragma”, “no-cache”);
    response.setHeader(“Cache-Control”, “no-cache”);
    response.setDateHeader(“Expires”, 0);

    HttpSession session = request.getSession();

    ValidateCode vCode = new ValidateCode(120,40,5,100);
    session.setAttribute(“code”, vCode.getCode());
    vCode.write(response.getOutputStream());
    return null;
    }

下面是controller层验证验证码输入是否正确

  1. String code = request.getParameter(“code”);    
  2. HttpSession session = request.getSession();    
  3. String sessionCode = (String) session.getAttribute(“code”);    
  4. if (!StringUtils.equalsIgnoreCase(code, sessionCode)) {  //忽略验证码大小写    
  5.     throw new RuntimeException(“验证码对应不上code=” + code + ”  sessionCode=” + sessionCode);    
  6. }   
String code = request.getParameter("code");
HttpSession session = request.getSession();
String sessionCode = (String) session.getAttribute("code");
if (!StringUtils.equalsIgnoreCase(code, sessionCode)) { //忽略验证码大小写
throw new RuntimeException("验证码对应不上code=" + code + " sessionCode=" + sessionCode);
}

版权声明:本文为jpfss原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/jpfss/p/8444116.html