• Springboot +redis+⾕歌开源Kaptcha实现图片验证码功能 look


    Springboot +redis+⾕歌开源Kaptcha实现图片验证码功能

    • 背景
      • 注册-登录-修改密码⼀般需要发送验证码,但是容易被 攻击恶意调⽤
      • 什么是短信-邮箱轰炸机
        • 手机短信轰炸机是批、循环给⼿机⽆限发送各种⽹ 站的注册验 证码短信的⽅法。
      • 公司带来的损失
        • 短信⼀条5分钱,如果被⼤盗刷⼤家⾃⼰计算 邮箱通知不⽤钱,但被⼤盗刷,带宽、连接等都被占⽤,导致⽆法正常使⽤
    • 如何避免⾃⼰的⽹站成为”⾁鸡“或者被刷呢
      • 增加图形验证码(开发⼈员)
      • 单IP请求次数限制(开发⼈员)
      • 限制号码发送(⼀般短信提供商会做)
      • 攻防永远是有的,只过加⼤了攻击者的成本,ROI划不 过来⾃然就放弃了

    Kaptcha 框架介绍

    • ⾕歌开源的⼀个可⾼度配置的实⽤验证 码⽣成⼯具

      • 验证码的字体/⼤⼩/颜⾊

      • 验证码内容的范围(数字,字⺟,中⽂汉字!)

      • 验证码图⽚的⼤⼩,边框,边框粗细,边框颜⾊

      • 验证码的⼲扰线 验证码的样式(⻥眼样式、3D、普通 模糊)

    • 添加依赖

      <!--kaptcha依赖包-->
      <dependency>
       <groupId>com.baomidou</groupId>
       <artifactId>kaptcha-spring-bootstarter</artifactId>
       <version>1.0.0</version>
       </dependency>
      
    • 配置类

      /**
       * 图像验证码的配置文件
       * @author : look-word
       * @date : 2022-01-28 17:10
       **/
      @Configuration
      public class CaptchaConfig {
          /**
           * 验证码配置
           * Kaptcha配置类名
           *
           * @return
           */
          @Bean
          @Qualifier("captchaProducer")
          public DefaultKaptcha kaptcha() {
              DefaultKaptcha kaptcha = new DefaultKaptcha();
              Properties properties = new Properties();
              //验证码个数
              properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
              //字体间隔
              properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE,"8");
              //⼲扰线颜⾊
      
              //⼲扰实现类
              properties.setProperty(Constants.KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
              //图⽚样式
              properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL,
                      "com.google.code.kaptcha.impl.WaterRipple");
              //⽂字来源
              properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "0123456789");
      
              Config config = new Config(properties);
              kaptcha.setConfig(config);
              return kaptcha;
          }
      }
      

    实战

    我的配置类

    获取访问ip和生成MD5的工具类

    public class CommonUtil {
        /**
         * 获取ip
         * @param request
         * @return
         */
        public static String
        getIpAddr(HttpServletRequest request) {
            String ipAddress = null;
            try {
                ipAddress = request.getHeader("xforwarded-for");
                if (ipAddress == null ||
                        ipAddress.length() == 0 ||
                        "unknown".equalsIgnoreCase(ipAddress)) {
                    ipAddress =
                            request.getHeader("Proxy-Client-IP");
                }
                if (ipAddress == null ||
                        ipAddress.length() == 0 ||
                        "unknown".equalsIgnoreCase(ipAddress)) {
                    ipAddress =
                            request.getHeader("WL-Proxy-Client-IP");
                }
                if (ipAddress == null ||
                        ipAddress.length() == 0 ||
                        "unknown".equalsIgnoreCase(ipAddress)) {
                    ipAddress =
                            request.getRemoteAddr();
                    if
                    (ipAddress.equals("127.0.0.1")) {
                        // 根据⽹卡取本机配置的IP
                        InetAddress inet = null;
                        try {
                            inet =
                                    InetAddress.getLocalHost();
                        } catch (UnknownHostException e) {
                            e.printStackTrace();
                        }
                        ipAddress =
                                inet.getHostAddress();
                    }
                }
                // 对于通过多个代理的情况,第⼀个IP为客户端真实IP,多个IP按照','分割
                if (ipAddress != null &&
                        ipAddress.length() > 15) {
                    // "***.***.***.***".length()
                    // = 15
                    if (ipAddress.indexOf(",") > 0)
                    {
                        ipAddress =
                                ipAddress.substring(0, ipAddress.indexOf(","));
                    }
                }
            } catch (Exception e) {
                ipAddress="";
            }
            return ipAddress;
        }
        public static String MD5(String data) {
            try {
                java.security.MessageDigest md =
                        MessageDigest.getInstance("MD5");
                byte[] array =
                        md.digest(data.getBytes("UTF-8"));
                StringBuilder sb = new
                        StringBuilder();
                for (byte item : array) {
    
                    sb.append(Integer.toHexString((item & 0xFF) |
                            0x100).substring(1, 3));
                }
                return sb.toString().toUpperCase();
            } catch (Exception exception) {
            }
            return null;
    
        }
    }
    

    接口开发

    @RestController
    @RequestMapping("/api/v1/captcha")
    public class CaptchaController {
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        
        @Autowired
        private Producer producer;
    
        @RequestMapping("get_captcha")
        public void getCaptcha(HttpServletRequest request, HttpServletResponse response){
            String captchaText = producer.createText();
            String key = getCaptchaKey(request);
            // 十分钟过期
            stringRedisTemplate.opsForValue().set(key,captchaText,10, TimeUnit.MINUTES);
            BufferedImage image = producer.createImage(captchaText);
            ServletOutputStream outputStream=null;
            try {
                outputStream= response.getOutputStream();
                ImageIO.write(image,"jpg",outputStream);
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 生成redis验证码模块的key
         * @param request
         * @return
         */
        private String getCaptchaKey(HttpServletRequest request){
            String ipAddr = CommonUtil.getIpAddr(request);
            // 请求头
            String userAgent=request.getHeader("user-Agent");
            String key="user_service:captcha:"+CommonUtil.MD5(ipAddr+userAgent);
            return key;
        }
    
    
    }
    

    配置文件

    server:
      port: 8080
    spring:
      redis:
        host: redis锁在的ip
        password: redis的密码
        port: 端口号
        lettuce:
          pool:
            # 连接池最⼤连接数(使⽤负值表示没有限制)
            max-idle: 10
            # 连接池中的最⼤空闲连接
            max-active: 10
            # 连接池中的最⼩空闲连接
            min-idle: 0
            # 连接池最⼤阻塞等待时间(使⽤负值表示没有限制)
            max-wait: -1ms
    

    结果

    image-20220129095351726

  • 相关阅读:
    洛谷 P2486 [SDOI2011]染色 树链剖分
    js 随机打乱数组
    js 中concat()和slice()方法介绍
    encodeURIComponent() 函数的使用
    mysql中LOCATE和CASE WHEN...THEN...ELSE...END结合用法
    Java多态的理解
    JQuery UI完成自动匹配的的下拉列表步骤
    marquee 标签的使用介绍
    orcale数据恢复
    sql中replace的用法
  • 原文地址:https://www.cnblogs.com/look-word/p/15854374.html
Copyright © 2020-2023  润新知