谷歌Captcha图形验证码实战

谷歌Captcha图形验证码实战

1.为什么要进行图形验证码开发?

  • 验证码开发是为了防止 短信-邮箱轰炸机

    手机短信轰炸机是批量、循环给手机无限发送各种网站的注册验证码短信的方法。
    
    原理:
    很多人都用手机注册一些网站的验证了,比如手机验证码。先填手机号,然后发一条验证码过去,输入验证码,完成验证,注册成功。
    
    * 寻找大量肉鸡网站,寻找发送验证码的请求接口
    
    * 如果找不到接口,也可以使用自动化UI工具触发
    
    * 编写程序和调度任务,相关脚本录入数据库
    
    * 输入目标手机号或者邮箱,触发攻击
    
    公司带来的损失:
    1. 短信一条5分钱,如果被大量盗刷大家自己计算
    2. 邮箱通知不用钱,但被大量盗刷,带宽、连接等都被占用,导致无法正常使用
    
  • 图形验证码 开发 防止 批量注册账号

  • 如何避免自己的网站成为”肉鸡“或者被刷呢

    • 增加图形验证码(开发人员)
    • 单IP请求次数限制(开发人员)
    • 限制号码发送(一般短信提供商会做)

2.图形验证码开发之谷歌kaptcha引入

  • Kaptcha 框架 是谷歌开源的一个生成验证码的工具

    • 验证码的字体/大小/颜色
    • 验证码内容的范围(数字,字母,中文汉字!)
    • 验证码图片的大小,边框,边框粗细,边框颜色
    • 验证码的干扰线
    • 验证码的样式(鱼眼样式、3D、普通模糊)
  • 添加依赖(使用国内baomidou二次封装的springboot整合starter)

    <!--kaptcha依赖包-->
                <dependency>
                    <groupId>com.baomidou</groupId>
                    <artifactId>kaptcha-spring-boot-starter</artifactId>
                    <version>1.1.0</version>
                </dependency>
    
  • 开发配置

    • 任何框架和springboot整合基本都是 @Configuration + @Bean 把配置放入Spring容器中
    @Configuration
    public class CaptchaConfig {
    
        /**
         * 验证码配置
         * Kaptcha配置类名
         * 
         * @return
         */
        @Bean
        @Qualifier("captchaProducer")
        public DefaultKaptcha kaptcha() {
            DefaultKaptcha kaptcha = new DefaultKaptcha();
            Properties properties = new Properties();
    //		properties.setProperty(Constants.KAPTCHA_BORDER, "yes");
    //		properties.setProperty(Constants.KAPTCHA_BORDER_COLOR, "220,220,220");
    //		//properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "38,29,12");
    //		properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "147");
    //		properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "34");
    //		properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "25");
    //		//properties.setProperty(Constants.KAPTCHA_SESSION_KEY, "code");
            //验证码个数
            properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
    //		properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Courier");
            //字体间隔
            properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE,"8");
            //干扰线颜色
    //		properties.setProperty(Constants.KAPTCHA_NOISE_COLOR, "white");
            //干扰实现类
            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;
        }
    }
    
  • 测试

    /**
     * @Author:fan
     * @Description:
     * @Date:2022-09-17 22:09
     */
    @Api(tags = "通知模块")
    @RequestMapping("/api/v1/notify")
    @RestController
    @Slf4j
    public class NotifyController {
        @Autowired
        private Producer captcha;
    
        @ApiOperation("获取图形验证码")
        @GetMapping("/getCaptcha")
        public void getCaptcha(HttpServletRequest request, HttpServletResponse response){
    
            //通过Captcha获取验证码数据
            String text = captcha.createText();
            //把 验证码生成图片
            BufferedImage image = captcha.createImage(text);
            ServletOutputStream outputStream = null;
            try {
                //获取输出流
                outputStream = response.getOutputStream();
                //把验证码的图片,以jpg格式,转换为 ServletOutputStream
                ImageIO.write(image,"jpg",outputStream);
                //刷新
                outputStream.flush();
                //关闭流
                outputStream.close();
            } catch (IOException e) {
               log.error("获取图形验证码失败"+e);
            }
        }
    }
    
    
posted @ 2022-12-10 15:00  snail05  阅读(1466)  评论(0)    收藏  举报