单一功能学习----简单的验证码

时间:2022-08-31 16:33:30

一、验证码的作用

  1、防止大量重复请求。一般在登录的时候需要验证码,验证码的作用就是拖延时间,让每次登录的操作时间间隔变长,这样可以防止有人暴力破解密码登录。

 

二、设计思路

  1、最简单的验证码,就是一串数字了。小时候看到的就是这个样子的,4个数字。

  2、这串数字应该是随机的。

  3、这串数字是可以更换的(以前看到的换一张按钮)。

  4、要有一个输入框,输入验证码。

  5、每登录一次,若失败应该更换验证码。

  6、稍微高级一点,验证码可以变成一张图片,防止恶意软件直接从前端代码获取验证码值。

  7、更高级的验证码,可以改变验证的内容:比如验证中文,验证计算结果等;可以改变验证的方式,比如12306看名称选图,比如拖拽图片验证;可以改变验证码的获取方式,比如把验证码通过短信或电话发到用户的手机,通过邮件发到用户的邮箱等。(难度略大,在这里忽略掉这一条)

 

三、代码实现

  1、最简单的验证码

    ①前端

1     <div class="yanzhengma">
2         <span>验证码:</span>
3         <input type="text" name="yanzhengma" placeholder="请输入验证码">
4         <span id="yanzhengmaInfo">1234</span>
5         <span onclick="changeYanzhengmaInfo();">换一张</span>
6     </div>

 

// 改变验证码的值
function changeYanzhengmaInfo() {
    var url = contextPath + '/changeYanzhengmaInfo.html?' + new Date().getTime();
    $.post(url,function(data) {
        $("#yanzhengmaInfo").text(data);
    });
}

 

    ②后端

 1     // 生成验证码
 2     @Action("/changeYanzhengmaInfo")
 3     public void changeYanzhengmaInfo() {
 4         // 生成随机数,四位数,不足四位数(小于1000)的,给设一个值,大于9999的给设一个值
 5         Random random = new Random();
 6         int r = random.nextInt(10000);
 7         if (r < 1000) {
 8             r = 2018;
 9         } else if (r > 9999) {
10             r = 9999;
11         }
12         final String yanzhengma = random.nextInt(10000) + "";
13         // 把值保存到session
14         final HttpSession session = ServletActionContext.getRequest().getSession();
15         session.setAttribute("captcha", yanzhengma);
16         // 把值返回到前端
17         this.sendResponseMsg(yanzhengma);
18     }
19 
20     /**
21      * 验证验证码.
22      *
23      * @throws UnsupportedEncodingException
24      * @author 
25      */
26     @Action("/checkCaptcha")
27     public void checkCaptcha() throws UnsupportedEncodingException {
28         this.request.setCharacterEncoding(ENCODE_UTF_8);
29         this.response.setContentType(CONTENT_TYPE);
30         final String yanzhengma = this.request.getParameter("yanzhengma");
31 
32         String captcha = this.session.get("captcha");
33         if (captcha == null) {
34             sendFailMsg("", "验证码不存在,请刷新!");
35             return;
36         }
37         if (captcha.equals(yanzhengma)) {
38             this.sendSuccessMsg();
39         } else {
40             this.sendFailMsg(null, "验证码错误!");
41         }
42     }

 

 

  2、图片形式的验证码

    ①前端

      与上边的不同,这里获取的验证码是一张图片,所以这里要从后台获取到的数据应该是验证码图片的链接。通过换链接的方式来达到换验证码的效果。

    <li>
        <label class="u_label">验证码:</label>
        <input id="captcha" class="text-input captcha" name="captcha" type="text" placeholder="请输入验证码">
        <a href="javascript:;" style="margin-left:20px;"><img id="captcha-img" width="80" height="36" src="${contextPath}/captchaImage.html" /></a>
        <span><a href="javascript:changeCaptchaImg();" style="height: 40px; line-height: 40px; margin-left: 10px;">换一张</a></span>
    </li>
    <span id="captchadwrong" style="margin-left:84px;color:red;display: none">请输入正确的验证码</span>

 

 1 // 改获取图片的链接
 2 function changeCaptchaImg() {
 3     var imgUrl = contextPath + '/captchaImage.html?' + new Date().getTime();
 4     $('#captcha-img').attr('src', imgUrl);
 5 }
 6 
 7 // 验证验证码
 8 function checkCaptcha() {
 9     var captchaValue = $("input[name='captcha']").val();
10     var captcha = false;
11     var captchadwrong = $('#captchadwrong');
12     $.ajax({
13         url: contextPath + '/checkCaptcha.html',
14         type: 'post',
15         dataType: 'json',
16         async: false,
17         data: { captcha: captchaValue },
18         success: function(text) {
19             captcha = text.success;
20         }
21     });
22     if (captcha == false) { //失败
23         captchadwrong.css('display', "inline-block");
24         captchadwrong.text("请输入正确的验证码");
25         return false;
26     } else { //成功
27         captchadwrong.css('display', "none");
28         return true;
29     }
30 }

 

    ②后端

      首先,需要引入一个jar包:simplecaptcha-1.2.1.jar

 1     @Action("/captchaImage")
 2     public void createCaptchaImage() {
 3         // 自定义设置字体颜色和大小 最简单的效果 多种字体随机显示
 4         final List<java.awt.Color> textColors = Arrays.asList(this.getRandColor(50, 200), this.getRandColor(50, 200));
 5         final List<Font> fontList = Lists.newArrayList();
 6         fontList.add(new Font("Viner Hand ITC", Font.TYPE1_FONT, 52));// 可以设置斜体之类的
 7          fontList.add(new Font("Kristen ITC", Font.ITALIC, 45));
 8         fontList.add(new Font("Bradley Hand ITC", Font.HANGING_BASELINE, 52));
 9         fontList.add(new Font("Comic Sans ms", Font.PLAIN, 45));
10         // 图片的背景(渐变,从 white 色到 white 色)
11         final GradiatedBackgroundProducer gbp = new GradiatedBackgroundProducer(Color.white, Color.white);
12         // 生成验证码对象:包括值Answer,时间Timestamp,图片Image,图片里包括颜色,宽高等信息
13         final Captcha captcha = new Captcha.Builder(CAPTCHA_WIDTH, CAPTCHA_HEIGHT).addNoise().addNoise()
14                 // .gimp(new ShearGimpyRenderer
15                 // (this.getRandColor(50, 200)))
16                 .addText(new DefaultTextProducer(RANDOM_NUMBER, MY_CHARS),
17                         new DefaultWordRenderer(textColors, fontList))
18                 .addBackground(gbp).build();
19         // // 在session中存储生成的验证码
20         final HttpSession session = ServletActionContext.getRequest().getSession();
21         OutputStream out = null;
22         try {
23             out = this.response.getOutputStream();
24             this.response.reset();
25             this.response.setContentType("image/jpeg");
26             this.response.setHeader("Pragma", "No-cache");
27             this.response.setHeader("Cache-Control", "no-cache");
28             this.response.setDateHeader("Expires", 0);
29             ImageIO.write(captcha.getImage(), "JPG", out);
30             session.setAttribute(CAPTCHA, captcha);
31             out.flush();
32             out.close();
33             this.response.flushBuffer();
34         } catch (final IOException e) {
35             CaptchaImageAction.LOGGER.error("发送验证码IO异常", e);
36         } finally {
37             if (out != null) {
38                 try {
39                     out.close();
40                 } catch (final IOException e) {
41                     CaptchaImageAction.LOGGER.error("发送验证码IO异常", e);
42                 }
43             }
44         }
45     }
46 
47 
48     /*
49      * 给定范围获得随机颜色
50      */
51     private Color getRandColor(final int fc, final int bc) {
52         int tmpFc = fc;
53         int tmpBc = bc;
54         final Random random = new Random();
55         if (tmpFc > MAX_RANDOM_NUMBER) {
56             tmpFc = MAX_RANDOM_NUMBER;
57         }
58         if (tmpBc > MAX_RANDOM_NUMBER) {
59             tmpBc = MAX_RANDOM_NUMBER;
60         }
61         final int r = tmpFc + random.nextInt(tmpBc - tmpFc);
62         final int g = tmpFc + random.nextInt(tmpBc - tmpFc);
63         final int b = tmpFc + random.nextInt(tmpBc - tmpFc);
64         return new Color(r, g, b);
65     }
66 
67 
68     /**
69      * 验证验证码.
70      *
71      * @throws UnsupportedEncodingException
72      * @author
73      */
74     @Action("/checkCaptcha")
75     public void checkCaptcha() throws UnsupportedEncodingException {
76         this.request.setCharacterEncoding(ENCODE_UTF_8);
77         this.response.setContentType(CONTENT_TYPE);
78         final String captcha = this.request.getParameter(CaptchaImageAction.CAPTCHA);
79 
80         Object object = this.session.get(CaptchaImageAction.CAPTCHA);
81         if (object == null) {
82             sendFailMsg("", "验证码不存在,请刷新!");
83             return;
84         }
85         final Captcha captchaInSession = (Captcha) object;
86         final String answer = captchaInSession.getAnswer();
87         // 忽略大小写比较
88         if (answer.equalsIgnoreCase(captcha)) {
89             this.sendSuccessMsg();
90         } else {
91             this.sendFailMsg(null, "验证码错误!");
92         }
93     }

 

    ③效果图

    单一功能学习----简单的验证码单一功能学习----简单的验证码

    单一功能学习----简单的验证码