1. 程式人生 > 其它 >谷歌Captcha圖形驗證碼實戰

谷歌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);
            }
        }
    }