课程表

Spring Boot课程

工具箱
速查手册

Boot 验证码功能

当前位置:免费教程 » Java相关 » Spring Boot

在我们编写Web程序的时候,为了防止恶意的刷新和攻击,往往会用到验证码功能。那么,Spring Boot里面如何实现验证码功能呢?

验证码的基本原理是,产生一个随机的seesion值,让客户端和服务器端展开会话,然后根据这个随机的值,生成一张图片,再通过前端展示这张图片,用户根据图片上的内容,填写相关信息,然后提交给服务器端,服务器端会把用户输入的值和产生的随机值进行比对,相同则验证通过。

验证码最主要的功能是面向机器的,因此,必须为恶意的程序设置更多的障碍,但障碍也不能验证影响正常用户对于程序的使用。还要注意一点,验证码的明文是不能直接传送到前端的。前端内容都是透明的,不安全。验证码是用来防机器人并不是单单防人。如果把验证码明文传到前端很容易就会被破解。

下面,我们就一步步实现验证码的功能。


一、图片生成的工具类

我们在utils文件夹,建立一个图片生成工具类RandomValidateCodeUtil类,完整代码如下:

  1. package com.w3xue.jiaocheng.utils;
  2.  
  3. import javax.imageio.ImageIO;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. import javax.servlet.http.HttpSession;
  7. import java.awt.*;
  8. import java.awt.image.BufferedImage;
  9. import java.util.Random;
  10.  
  11. public class RandomValidateCodeUtil {
  12.  
  13.     public static final String RANDOMCODEKEY = "RANDOMVALIDATECODEKEY";//放到session中的key
  14.     private String randString = "0123456789";//随机产生只有数字的字符串 private String
  15.     //private String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串
  16.     //private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生数字与字母组合的字符串
  17.     private int width = 95;// 图片宽
  18.     private int height = 25;// 图片高
  19.     private int lineSize = 40;// 干扰线数量
  20.     private int stringNum = 4;// 随机产生字符数量
  21.  
  22.     private Random random = new Random();
  23.  
  24.     /**
  25.      * 获得字体
  26.      */
  27.     private Font getFont() {
  28.         return new Font("Fixedsys", Font.CENTER_BASELINE, 18);
  29.     }
  30.  
  31.     /**
  32.      * 获得颜色
  33.      */
  34.     private Color getRandColor(int fc, int bc) {
  35.         if (fc > 255)
  36.             fc = 255;
  37.         if (bc > 255)
  38.             bc = 255;
  39.         int r = fc + random.nextInt(bc - fc - 16);
  40.         int g = fc + random.nextInt(bc - fc - 14);
  41.         int b = fc + random.nextInt(bc - fc - 18);
  42.         return new Color(r, g, b);
  43.     }
  44.  
  45.     /**
  46.      * 生成随机图片
  47.      */
  48.     public void getRandcode(HttpServletRequest request, HttpServletResponse response) {
  49.         HttpSession session = request.getSession();
  50.         // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类
  51.         BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
  52.         Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作
  53.         g.fillRect(0, 0, width, height);//图片大小
  54.         g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18));//字体大小
  55.         g.setColor(getRandColor(110, 133));//字体颜色
  56.         // 绘制干扰线
  57.         for (int i = 0; i <= lineSize; i++) {
  58.             drowLine(g);
  59.         }
  60.         // 绘制随机字符
  61.         String randomString = "";
  62.         for (int i = 1; i <= stringNum; i++) {
  63.             randomString = drowString(g, randomString, i);
  64.         }
  65.         System.out.println(randomString);
  66.         //将生成的随机字符串保存到session中
  67.         session.removeAttribute(RANDOMCODEKEY);
  68.         session.setAttribute(RANDOMCODEKEY, randomString);
  69.         g.dispose();
  70.         try {
  71.             // 将内存中的图片通过流动形式输出到客户端
  72.             ImageIO.write(image, "JPEG", response.getOutputStream());
  73.         } catch (Exception e) {
  74.             e.printStackTrace();
  75.         }
  76.  
  77.     }
  78.  
  79.     /**
  80.      * 绘制字符串
  81.      */
  82.     private String drowString(Graphics g, String randomString, int i) {
  83.         g.setFont(getFont());
  84.         g.setColor(new Color(random.nextInt(101), random.nextInt(111), random
  85.                 .nextInt(121)));
  86.         String rand = String.valueOf(getRandomString(random.nextInt(randString
  87.                 .length())));
  88.         randomString += rand;
  89.         g.translate(random.nextInt(3), random.nextInt(3));
  90.         g.drawString(rand, 13 * i, 16);
  91.         return randomString;
  92.     }
  93.  
  94.     /**
  95.      * 绘制干扰线
  96.      */
  97.     private void drowLine(Graphics g) {
  98.         int x = random.nextInt(width);
  99.         int y = random.nextInt(height);
  100.         int xl = random.nextInt(13);
  101.         int yl = random.nextInt(15);
  102.         g.drawLine(x, y, x + xl, y + yl);
  103.     }
  104.  
  105.     /**
  106.      * 获取随机的字符
  107.      */
  108.     public String getRandomString(int num) {
  109.         return String.valueOf(randString.charAt(num));
  110.     }
  111. }

这里的图片类,作用是生成图片,还可以设置相关参数。

二、Controller层引用

第二步,就是将验证码图片传给前端页面。在MainRestController类中,加入如下路由和方法:

  1. //生成验证码
  2. @RequestMapping(value = "/getVerify")
  3. public void getVerify(HttpServletRequest request, HttpServletResponse response) {
  4.     try {
  5.         response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片
  6.         response.setHeader("Pragma", "No-cache");//设置响应头信息,告诉浏览器不要缓存此内容
  7.         response.setHeader("Cache-Control", "no-cache");
  8.         response.setDateHeader("Expire", 0);
  9.         RandomValidateCodeUtil randomValidateCode = new RandomValidateCodeUtil();
  10.         randomValidateCode.getRandcode(request, response);//输出验证码图片方法
  11.     } catch (Exception e) {
  12.         e.printStackTrace();
  13.     }
  14. }

三、前端页面显示

第三步,就是在前端页面中,把验证码显示出来。在Resouces/templates模板文件夹中,新建一个HTML页面verify.html,代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>验证码实验</title>
  6. </head>
  7. <body>
  8.  
  9.  
  10. <div class="row">
  11.     <div class="col-xs-6 pull_left">
  12.         <form action="checkVerify">
  13.             <div class="form-group">
  14.                 <input class="form-control" type="tel" id="verify_input" name="code" placeholder="请输入验证码" maxlength="4">
  15.             </div>
  16.             <div class="form-group">
  17.                 <button type="submit">提交</button>
  18.             </div>
  19.         </form>
  20.     </div>
  21.     <div class="col-xs-6 pull_left">
  22.         <a href="javascript:void(0);" title="点击更换验证码">
  23.             <img id="imgVerify" src="getVerify" alt="更换验证码" height="36" width="100px" onclick="getVerify(this);">
  24.         </a>
  25.     </div>
  26.     <script>
  27.         function getVerify(obj) {
  28.             obj.src = "getVerify?" + Math.random();
  29.         }
  30.     </script>
  31. </div>
  32.  
  33. </body>
  34. </html>

同时,在MainController类中,加上一个路由方法,绑定该前端页面:

  1. @RequestMapping(value = "/verify")
  2. public String verify(){
  3.     return "verify"; //使用lucky模板并返回
  4. }

四、后端验证

可以看到,刚才前端页面中,页面是返回给checkVerify这个路由进行处理的。下面,我们就来定义这个路由。在MainRestController类中加入如下路由,这样,在用户输入验证码后,交给这个路由验证。验证成功,则返回“ture”字样,否则,返回“false”字样。在实际使用的过程中,你把这个验证整合到总的提交路由中即可。

  1. //对验证码进行验证
  2. @RequestMapping(value = "/checkVerify")
  3. public boolean checkVerify(String code, HttpSession session) {
  4.     try {
  5.         //从session中获取随机数
  6.         String random = (String) session.getAttribute("RANDOMVALIDATECODEKEY");
  7.         if (random == null) {
  8.             return false;
  9.         }
  10.         if (random.equals(code)) {
  11.             System.out.println("正确的验证码");
  12.             return true;
  13.         } else {
  14.             System.out.println("错误的验证码");
  15.             return false;
  16.         }
  17.     } catch (Exception e) {
  18.         e.printStackTrace();
  19.         return false;
  20.     }
  21. }

最后,我们访问“localhost:8080/jiaocheng/verify”,即可使用该功能。

0.jpg

参考自:https://blog.csdn.net/Colton_Null/article/details/78744240

转载本站内容时,请务必注明来自W3xue,违者必究。
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号