分享

JavaWeb中登录模块验证码(springMVC)

 三十的狼 2019-08-22

最近有需求在项目的登录模块加上验证码,在网上找了一些java写的验证码,总算是找到了一个比较炫酷的,废话不多说,上代码:

1.首先是生成随机数的Randoms类:

复制代码
 1 2 
 3 import java.util.Random;
 4 
 5 public class Randoms {
 6     private static final Random RANDOM = new Random();
 7     //定义验证码字符.去除了O和I等容易混淆的字母
 8     public static final char ALPHA[]={'A','B','C','D','E','F','G','H','G','K','M','N','P','Q','R','S','T','U','V','W','X','Y','Z'
 9             ,'a','b','c','d','e','f','g','h','i','j','k','m','n','p','q','r','s','t','u','v','w','x','y','z','2','3','4','5','6','7','8','9'};
10  
11     /**
12      * 产生两个数之间的随机数
13      * @param min 小数
14      * @param max 比min大的数
15      * @return int 随机数字
16      */
17     public static int num(int min, int max)
18     {
19         return min + RANDOM.nextInt(max - min);
20     }
21  
22     /**
23      * 产生0--num的随机数,不包括num
24      * @param num 数字
25      * @return int 随机数字
26      */
27     public static int num(int num)
28     {
29         return RANDOM.nextInt(num);
30     }
31  
32     public static char alpha()
33     {
34         return ALPHA[num(0, ALPHA.length)];
35     }
36 
37 }
复制代码

2.然后是生成验证码接口Captcha(需要注意这里Randoms类是静态导包,对应我上面第1步中的Randoms包路径):

复制代码
  1  2 
  3 import java.awt.*;
  4 import java.awt.image.BufferedImage;
  5 import java.io.OutputStream;
  6  
  7 
  8 import static com.gmsz.ylpt.common.utils.Randoms.num;
  9 import static com.gmsz.ylpt.common.utils.Randoms.alpha;
 10 /**
 11  * <p>验证码抽象类,暂时不支持中文</p>
 12  *
 13  * @author: cjz
 14  * 
 15  */
 16 public abstract class Captcha
 17 {
 18     protected Font font = new Font("Verdana", Font.ITALIC|Font.BOLD, 28);   // 字体
 19     protected int len = 5;  // 验证码随机字符长度
 20     protected int width = 150;  // 验证码显示跨度
 21     protected int height = 40;  // 验证码显示高度
 22     private String chars = null;  // 随机字符串
 23  
 24     /**
 25      * 生成随机字符数组
 26      * @return 字符数组
 27      */
 28     protected char[] alphas()
 29     {
 30         char[] cs = new char[len];
 31         for(int i = 0;i<len;i++)
 32         {
 33             cs[i] = alpha();
 34         }
 35         chars = new String(cs);
 36         return cs;
 37     }
 38     public Font getFont()
 39     {
 40         return font;
 41     }
 42  
 43     public void setFont(Font font)
 44     {
 45         this.font = font;
 46     }
 47  
 48     public int getLen()
 49     {
 50         return len;
 51     }
 52  
 53     public void setLen(int len)
 54     {
 55         this.len = len;
 56     }
 57  
 58     public int getWidth()
 59     {
 60         return width;
 61     }
 62  
 63     public void setWidth(int width)
 64     {
 65         this.width = width;
 66     }
 67  
 68     public int getHeight()
 69     {
 70         return height;
 71     }
 72  
 73     public void setHeight(int height)
 74     {
 75         this.height = height;
 76     }
 77  
 78     /**
 79      * 给定范围获得随机颜色
 80      * @return Color 随机颜色
 81      */
 82     protected Color color(int fc, int bc)
 83     {
 84         if (fc > 255)
 85             fc = 255;
 86         if (bc > 255)
 87             bc = 255;
 88         int r = fc + num(bc - fc);
 89         int g = fc + num(bc - fc);
 90         int b = fc + num(bc - fc);
 91         return new Color(r, g, b);
 92     }
 93  
 94     /**
 95      * 验证码输出,抽象方法,由子类实现
 96      * @param os 输出流
 97      */
 98     public abstract BufferedImage out(OutputStream os);
 99  
100     /**
101      * 获取随机字符串
102      * @return string
103      */
104     public String text()
105     {
106         return chars;
107     }
108 }
复制代码

3.继承Captcha接口的SpecCaptcha类实现了父类的生成验证码的抽象方法:

复制代码
 1 2 
 3 import static com.gmsz.ylpt.common.utils.Randoms.num;
 4 
 5 import java.awt.AlphaComposite;
 6 import java.awt.Color;
 7 import java.awt.Font;
 8 import java.awt.Graphics2D;
 9 import java.awt.image.BufferedImage;
10 import java.io.OutputStream;
11 
12 public class SpecCaptcha  extends Captcha{
13      public SpecCaptcha()
14         {
15         }
16         public SpecCaptcha(int width, int height)
17         {
18             this.width = width;
19             this.height = height;
20         }
21         public SpecCaptcha(int width, int height, int len){
22             this(width,height);
23             this.len = len;
24         }
25         public SpecCaptcha(int width, int height, int len, Font font){
26             this(width,height,len);
27             this.font = font;
28         }
29         /**
30          * 生成验证码
31          * @throws java.io.IOException IO异常
32          */
33         @Override
34         public BufferedImage out(OutputStream out){
35             return graphicsImage(alphas(), out);
36         }
37      
38         /**
39          * 画随机码图
40          * @param strs 文本
41          * @param out 输出流
42          */
43         private BufferedImage graphicsImage(char[] strs, OutputStream out){
44                BufferedImage bi =null;
45                 bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
46                 Graphics2D g = (Graphics2D)bi.getGraphics();
47                 AlphaComposite ac3;
48                 Color color ;
49                 int len = strs.length;
50                 g.setColor(Color.WHITE);
51                 g.fillRect(0,0,width,height);
52                 // 随机画干扰的蛋蛋
53                 for(int i=0;i<15;i++){
54                     color = color(150, 250);
55                     g.setColor(color);
56                     g.drawOval(num(width), num(height), 5+num(10), 5+num(10));// 画蛋蛋,有蛋的生活才精彩
57                     color = null;
58                 }
59                 g.setFont(font);
60                 int h  = height - ((height - font.getSize()) >>1),
61                     w = width/len,
62                     size = w-font.getSize()+1;
63                 /* 画字符串 */
64                 for(int i=0;i<len;i++)
65                 {
66                     ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f);// 指定透明度
67                     g.setComposite(ac3);
68                     color = new Color(20 + num(110), 20 + num(110), 20 + num(110));// 对每个字符都用随机颜色
69                     g.setColor(color);
70                     g.drawString(strs[i]+"",(width-(len-i)*w)+size, h-4);
71                     color = null;
72                     ac3 = null;
73                 }
74             return bi;
75         }
76 
77 }
复制代码

好了,到这里,这三个类就可以生成验证码了,那么如何将生成好的验证码加到项目中呢?我用的是SpringMVC框架,用户打开登录界面,会到controller中将生成好的验证码字符串放到session中(接口Captcha中有个text()方法返回一个验证码字符串),然后将生成好的验证码图片放到servlert的输出流中,jsp页面去输出流中把图片取出来展示到前台即可。说干就干,首先上我的前台jsp代码:

1 <div class="login-content-input login-content-input-code">
2     <div>
3                 验证码<input type="code"  name="password"           id="validateCode" value="" />
4     <img  id="validateCodeImg" src="<%=actionPath%>/getCode"    onclick="login.reloadValidateCode();" />
5     </div>
6     </div>                    

这里我只贴出了我项目中的验证码模块的关键部分代码,那些引入jquery.js,  jstl之类的我就忽略了。这里的<%=actionPath%>可以根据自己的项目路径自行修改。下面是我的后台java代码,也就是controller中的代码:

复制代码
/**
     * 生成验证码
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "getCode")
    public void validateCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //禁止图像缓存
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", 0);
        
        Captcha captcha = new SpecCaptcha(150,40,5);// png格式验证码
        ServletOutputStream out = response.getOutputStream();
        BufferedImage bi = captcha.out(out);
        //获取验证码字符串放到session中,用于登录时取出来验证
        String verifyCode =   captcha.text();
        request.getSession().setAttribute("validateCode", verifyCode);
        //将图像输出到 servlet的输出流中
        ImageIO.write(bi, "png", out);
        try {
            out.flush();
        } finally {
            out.close();
        }
    
    }
复制代码

这里注释也很详细了,最终前台展示效果图:,哈哈大功告成,当然还有一点就是 刷新验证码,刷新验证码其实就是重新去后台生成一个验证码,这里,我贴出我的js文件代码:

复制代码
/**
 * 点击验证码刷新
 */
var login = login || {};

login.reloadValidateCode = function(){
    /**
     * 给url后面加一个随机数,这样,每次请求都会从后台取新生成的验证码
     * 不会再去缓存中取验证码
     */
    var randomNumber = new Date()+Math.floor(Math.random() * Math.pow(10, 8));
    $("#validateCodeImg").attr("src",commonutil.actionPath+"/getCode?random="+randomNumber);
}
复制代码

这里需要稍微注意下的就是url后面的随机数,保证不会从缓存中取验证码,说白了就是每次发送新的url请求去后台获取验证码 。

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多