整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          如何在Spring Boot項(xiàng)目中生成圖形驗(yàn)證碼

          家好!我是黑客之家小編,黑客之家頭條號(hào)

          分享黑客技術(shù),GO、Python、Kotlin、Android、Java編程知識(shí),科技資訊等

          喜歡的朋友可以關(guān)注我的頭條號(hào)!

          圖形驗(yàn)證碼是我們經(jīng)常會(huì)用到的,例如在app或者網(wǎng)站注冊(cè)的時(shí)候,登錄的時(shí)候等等。圖形驗(yàn)證碼屬于驗(yàn)證碼的一種。

          圖形驗(yàn)證碼

          驗(yàn)證碼(CAPTCHA)是 “Completely Automated Public Turing test to tell Computers and Humans Apart”(全自動(dòng)區(qū)分計(jì)算機(jī)和人類的圖靈測(cè)試)的縮寫,是一種區(qū)分用戶是計(jì)算機(jī)還是人的公共全自動(dòng)程序。

          采用圖形驗(yàn)證碼是為了數(shù)據(jù)的安全,防止某些破解軟件,進(jìn)行無限嘗試破解,圖形的話,軟件無法識(shí)別,或識(shí)別的慢,這樣更加安全。

          理論上圖形驗(yàn)證碼是比較安全的,但是隨著技術(shù)的發(fā)展,特別是機(jī)器學(xué)習(xí)和人工智能技術(shù)的發(fā)展,圖形驗(yàn)證碼也變得不安全了,今天我們將要生成的數(shù)字字母組合的驗(yàn)證碼,其實(shí)已經(jīng)不夠安全了,生成效果如下:

          這種驗(yàn)證碼還是容易被機(jī)器識(shí)別的,后續(xù)的文章中會(huì)介紹如何采用程序識(shí)別這類圖形驗(yàn)證碼。

          接著說圖形驗(yàn)證碼的生成,今天我們采用的是kaptcha。kaptcha是一個(gè)可配置驗(yàn)證碼生成工具包,我們按照kaptcha的配置表配置就可以了。

          在使用kaptcha之前,要導(dǎo)入kaptcha的包,依賴如下:

          <dependency>
           <groupId>com.github.penggle</groupId>
           <artifactId>kaptcha</artifactId>
           <version>2.3.2</version>
          </dependency>
          

          在Spring Boot項(xiàng)目中新建一個(gè)KaptchaConfig.java文件,具體代碼如下:

          package com.example.demo.config;
          /**
           * Created by hacker on 2019-07-16.
           */
          import com.google.code.kaptcha.impl.DefaultKaptcha;
          import com.google.code.kaptcha.util.Config;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          import java.util.Properties;
          /**
           * @author hacker
           */
          @Configuration
          public class KaptchaConfig {
           @Bean
           public DefaultKaptcha getDefaultKaptcha() {
           DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
           Properties properties = new Properties();
           properties.setProperty("kaptcha.border", "yes");
           properties.setProperty("kaptcha.border.color", "105,179,90");
           properties.setProperty("kaptcha.textproducer.font.color", "blue");
           properties.setProperty("kaptcha.image.width", "110");
           properties.setProperty("kaptcha.image.height", "40");
           properties.setProperty("kaptcha.textproducer.font.size", "30");
           properties.setProperty("kaptcha.session.key", "code");
           properties.setProperty("kaptcha.textproducer.char.length", "4");
           properties.setProperty("kaptcha.textproducer.font.names", "宋體,楷體,微軟雅黑");
           Config config = new Config(properties);
           defaultKaptcha.setConfig(config);
           return defaultKaptcha;
           }
          }
          

          這樣kaptcha的樣式和顏色字體等就設(shè)置好了,接著就是生成圖形上的字符,同時(shí)通過二進(jìn)制流的形式把生成的圖片返回給前端。

          代碼如下:

          package com.example.demo.controller;
          import com.google.code.kaptcha.impl.DefaultKaptcha;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.web.bind.annotation.GetMapping;
          import org.springframework.web.bind.annotation.RequestMapping;
          import org.springframework.web.bind.annotation.RestController;
          import javax.imageio.ImageIO;
          import javax.servlet.ServletOutputStream;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.awt.image.BufferedImage;
          /**
           * <p>
           * 用戶信息表 前端控制器
           * </p>
           *
           * @author hacker
           */
          @RestController
          @RequestMapping("/api/")
          public class UserInfoController {
           @Autowired
           private DefaultKaptcha captchaProducer;
           @GetMapping("/getVerifyCode")
           public void getVerifyCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
           String createText = captchaProducer.createText();
           request.getSession().setAttribute("verifyCode", createText);
           response.setHeader("Cache-Control", "no-store");
           response.setHeader("Pragma", "no-cache");
           response.setDateHeader("Expires", 0);
           response.setContentType("image/jpeg");
           BufferedImage challenge = captchaProducer.createImage(createText);
           ServletOutputStream outputStream = response.getOutputStream();
           ImageIO.write(challenge, "jpg", outputStream);
           try {
           outputStream.flush();
           } finally {
           outputStream.close();
           }
           }
          }
          

          這樣我們就可以用GET方式獲取到生成的圖形驗(yàn)證碼了。

          為了能在瀏覽器里顯示我們這里采用thymeleaf模板。

          在pom.xml文件中引入thymeleaf依賴如下:

          <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-thymeleaf</artifactId>
          </dependency>
          

          之后在templates文件夾下新建一個(gè)index.html文件,代碼如下:

          <!DOCTYPE html>
          <html lang="en">
          <head>
           <meta charset="UTF-8">
           <title>CAPTCHA</title>
           <script type="text/javascript">
           function refresh() {
           document.getElementById('captcha_img').src = "/api/getVerifyCode?" + Math.random();
           }
           </script>
          </head>
          <body>
          <div>
           <img id="captcha_img" alt="點(diǎn)擊更換" title="點(diǎn)擊更換"
           onclick="refresh()" src="/api/getVerifyCode"/>
          </div>
          </body>
          </html>
          

          這樣一個(gè)簡(jiǎn)單前端顯示圖形驗(yàn)證碼就做好了,之后我們輸入http://localhost:8090/,就可以訪問了,8090換成自己對(duì)應(yīng)的端口。

          圖形驗(yàn)證碼

          點(diǎn)擊圖片可以切換圖形驗(yàn)證碼。至此,圖形驗(yàn)證碼功能結(jié)束!

          如果覺得文章對(duì)你有幫助,歡迎關(guān)注,點(diǎn)贊,轉(zhuǎn)發(fā),評(píng)論!后續(xù)文章會(huì)介紹如何通過程序識(shí)別今天生成的圖形驗(yàn)證碼,感興趣的同學(xué),可以持續(xù)關(guān)注!

          相關(guān)閱讀:

          基于spring boot快速搭建Java服務(wù)器

          Spring Boot項(xiàng)目部署簡(jiǎn)單方便的Shell腳本

          推薦一款Spring Boot中非常好用的插件

          網(wǎng)頁設(shè)計(jì)中,尤其表單填寫提交過程中,為防止機(jī)器自動(dòng)登錄,很多網(wǎng)頁都采用驗(yàn)證碼技術(shù),允許用戶輸入而盡量避免自動(dòng)登錄。驗(yàn)證碼實(shí)現(xiàn)的方法有很多,PHP繪圖技術(shù)可以在服務(wù)端生成驗(yàn)證碼并發(fā)送客戶端,HTML5技術(shù)下可以使用canvas與JS腳本實(shí)現(xiàn)在客戶端瀏覽器自動(dòng)生成驗(yàn)證碼。本文給出JS+Canvas驗(yàn)證碼的解決措施,所制作驗(yàn)證碼實(shí)現(xiàn)效果如下圖所示:

          驗(yàn)證碼實(shí)現(xiàn)效果動(dòng)態(tài)圖


          實(shí)現(xiàn)原理

          本例驗(yàn)證碼的實(shí)現(xiàn)主要包括驗(yàn)證碼字符串的生成、背景干擾點(diǎn)實(shí)現(xiàn)及干擾直線的生成三部分。最終通過canvas繪圖技術(shù)將生成的驗(yàn)證碼字符串、背景及干擾直線顯示到畫布上。主要涉及技術(shù)或知識(shí)點(diǎn)包括canvas繪圖技術(shù)、數(shù)組、鼠標(biāo)點(diǎn)擊事件、隨機(jī)函數(shù)等。以下從驗(yàn)證字符串、背景干擾點(diǎn)及干擾直線三方面對(duì)實(shí)現(xiàn)過程進(jìn)行說明。

          驗(yàn)證字符串

          驗(yàn)證字符串部分主要借助數(shù)組存儲(chǔ)驗(yàn)證碼所有字符,通過調(diào)用Math對(duì)象的隨機(jī)函數(shù)獲取數(shù)組下標(biāo),并通過數(shù)組下表讀取數(shù)組元素,將讀取的數(shù)組元素組裝成完整字符串。其實(shí)現(xiàn)核心代碼如下:

          驗(yàn)證字符串獲取核心代碼

          如上圖所示,本例驗(yàn)證碼字符包括數(shù)字與大寫字母,getCode函數(shù)返回值即為4位驗(yàn)證碼字符串。

          背景干擾點(diǎn)

          背景干擾點(diǎn)可以直接使用canvas對(duì)應(yīng)的繪圖方法進(jìn)行繪制,本例為簡(jiǎn)化開發(fā)過程,降低難度直接使用drawImage繪圖方式加載背景圖片,實(shí)現(xiàn)干擾點(diǎn)效果。背景圖片如下:

          背景干擾點(diǎn)圖片

          通過調(diào)用drawImage方法,指定截取的坐標(biāo)位置參數(shù),可實(shí)現(xiàn)背景干擾點(diǎn)的動(dòng)態(tài)變化效果,背景干擾點(diǎn)實(shí)現(xiàn)核心代碼如下:

          背景干擾點(diǎn)實(shí)現(xiàn)代碼

          其中g(shù)etXsize與getYsize為獲取繪圖截取背景圖片的坐標(biāo)位置,通過使用隨機(jī)函數(shù)實(shí)現(xiàn)從背景圖片不同位置截取進(jìn)行繪圖輸出。

          干擾直線

          干擾直線實(shí)現(xiàn)較為簡(jiǎn)單,直接通過JS提供的moveTo與lineTo方法完成直線的繪制,本例繪制了兩條直線,一條為黑色干擾線,一條為白色干擾線。在繪制過程兩端點(diǎn)需要使用Math隨機(jī)函數(shù)生成符合條件隨機(jī)坐標(biāo)。干擾直線相關(guān)實(shí)現(xiàn)代碼如下:

          干擾直線實(shí)現(xiàn)核心代碼

          干擾直線實(shí)現(xiàn)核心代碼如上圖,其中g(shù)etLsize方法主要用于獲取隨機(jī)端點(diǎn)Y軸坐標(biāo)值。strokeStyle主要用于設(shè)置繪圖直線的顏色。

          驗(yàn)證碼顯示輸出

          驗(yàn)證碼的顯示輸出主要使用fillText()方法在canvas指定位置進(jìn)行文字輸出,本例使用第三方ttf字體,因此在HTML頁面中對(duì)字體進(jìn)行了加載。驗(yàn)證碼顯示輸出實(shí)現(xiàn)代碼如下:

          驗(yàn)證碼繪制

          驗(yàn)證碼顯示輸出核心代碼如上圖所示,其中myfont為加載的第三方字體。

          繪圖基礎(chǔ)部分

          繪圖基礎(chǔ)部分主要包括前端canvas元素的布局等。包括屬性的設(shè)置,js部分元素的獲取及屬性設(shè)置等。

          其他工作

          我們一般接觸的驗(yàn)證碼,都可以點(diǎn)擊圖片實(shí)現(xiàn)驗(yàn)證碼的刷新,因此本例為canvas標(biāo)記添加了onclick事件,將所有驗(yàn)證碼生成的代碼封裝到showCode()函數(shù)中,通過調(diào)用showCode函數(shù)實(shí)現(xiàn)驗(yàn)證碼的刷新。本例完整JS腳本部分代碼如下:

          JS實(shí)現(xiàn)腳本代碼


          本頭條號(hào)長(zhǎng)期關(guān)注編程資訊分享;編程課程、素材、代碼分享及編程培訓(xùn)。如果您對(duì)以上方面有興趣或代碼錯(cuò)誤、建議與意見,可以聯(lián)系作者,共同探討。期待大家關(guān)注!如需案例完整代碼請(qǐng)關(guān)注并私信,往期前端設(shè)計(jì)文章鏈接如下:

          1. 前端設(shè)計(jì)-Ajax技術(shù)及實(shí)例展示
          2. 前端設(shè)計(jì)-響應(yīng)式頁面開發(fā)基礎(chǔ)
          3. Web開發(fā)前端、后端與全棧的區(qū)別是什么?

          近有同事在調(diào)研微信小程序,準(zhǔn)備把我們的 landing page(LP)頁面,遷移到小程序里,提高用戶體驗(yàn),提升轉(zhuǎn)化率。

          在LP里,遇到個(gè)很常見的問題,用戶通過手機(jī)號(hào)注冊(cè),發(fā)送短信驗(yàn)證碼需要防刷,目前在 h5 上使用的是 圖形驗(yàn)證碼+極驗(yàn)。一上來,就遇到了圖形驗(yàn)證碼的問題。小程序和 web 開發(fā)不同,不會(huì) 自動(dòng)處理 http 請(qǐng)求的 cookie。

          通常在 web 上,我們會(huì)把圖形驗(yàn)證碼存儲(chǔ)到用戶 session 里,然后在發(fā)送短信的接口,判斷用戶提交的圖形驗(yàn)證碼和 session 里的值是否相等,這里依賴瀏覽器自動(dòng)會(huì)處理 cookie 的讀寫來實(shí)現(xiàn)的。但是小程序里,需要開發(fā)者主動(dòng)來管理 cookie 等,并且在圖片請(qǐng)求中,也 不能 主動(dòng)設(shè)置cookie,導(dǎo)致之前 web 上的圖形驗(yàn)證碼完全失效。

          在網(wǎng)上發(fā)現(xiàn)提到小程序里的圖形驗(yàn)證碼實(shí)現(xiàn)的文章很少,就有一篇這個(gè) wechat-captcha ,但是作者這是純前端用 canvas 來繪制的圖形驗(yàn)證碼,顯然,圖形驗(yàn)證碼的生成,只能放在 server 端,這種方案,就需要有一種很好的方式,來講server端生成的圖形驗(yàn)證碼的值,傳遞到前端來。沒想到有什么方案,能從server端比較穩(wěn)妥的傳遞圖形驗(yàn)證碼的值到小程序里,只能看看其他大廠是怎么做的了。

          server 返回圖片base64編碼

          同事發(fā)現(xiàn)餓了么的小程序里,是有圖形驗(yàn)證碼的,那就先來看看餓了么的同學(xué)是怎么實(shí)現(xiàn)的呢。經(jīng)過抓包,很明顯能看到餓了么的圖片驗(yàn)證碼請(qǐng)求,是通過 js 來發(fā)起的,server 端返回的圖形驗(yàn)證碼的 base64 編碼,沒有繼續(xù)看后續(xù)是怎么把 base64 編碼渲染到出來的,但肯定是有辦法將 base64 的圖形驗(yàn)證碼繪制到 canvas 上的。

          其實(shí)這里是有個(gè)疑問的,在抓包的時(shí)候,發(fā)現(xiàn)在請(qǐng)求圖形驗(yàn)證碼的時(shí)(POST),并沒有帶上 cookie,也就是說,餓了么并沒有用 cookie-session 來存儲(chǔ)某個(gè)手機(jī)號(hào)對(duì)應(yīng)的圖形驗(yàn)證碼;并且用戶的手機(jī)號(hào),拼在了請(qǐng)求的 url 里,似乎在server端是通過其他方式,來存儲(chǔ)的手機(jī)號(hào)和圖形驗(yàn)證碼的關(guān)聯(lián)。

          我不太理解的是,既然用戶手機(jī)號(hào)已經(jīng)放在請(qǐng)求的 path 里了,為什么要使用 POST 來單獨(dú)請(qǐng)求圖驗(yàn)的 base64 編碼,再渲染到 canvas 上,為什么不直接拼一個(gè) GET 的 url,同樣把手機(jī)號(hào)放進(jìn)去,然后接口直接輸出二進(jìn)制的圖片數(shù)據(jù),這樣就可以直接把 url 賦值給小程序的 image 組件了。

          餓了么抓包如下(響應(yīng)中的 captcha_image 字段就是 png 圖片的 base64編碼):

          使用 WebView

          然后又看了下美團(tuán)的小程序,直接沒用圖形驗(yàn)證碼,而是用的類似極驗(yàn)的滑塊。猜想也是使用了 canvas 之類的技術(shù)來實(shí)現(xiàn)的,抓包才發(fā)現(xiàn),原來是用的 web-view組件來引用的 html 頁面。剛重新抓包過程中,雖然后端響應(yīng)接口確實(shí)返回了一個(gè) h5 的滑塊頁面URL,但是沒看到有加載這個(gè)頁面,看來美團(tuán)也 沒有 用 web-view 來加載 h5。

          美團(tuán)抓包如下:


          主站蜘蛛池模板: 日韩精品一区二区三区色欲AV | 蜜臀Av午夜一区二区三区| 精品一区二区三区在线观看| 日韩精品无码Av一区二区 | 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 麻豆AV无码精品一区二区 | 中字幕一区二区三区乱码| 中字幕一区二区三区乱码| 精品一区二区三区无码视频| 亚洲性日韩精品国产一区二区| 午夜视频久久久久一区 | 一区二区免费在线观看| 中文字幕精品无码一区二区三区| 日韩人妻无码一区二区三区99| 中字幕一区二区三区乱码| 精品无码一区二区三区水蜜桃 | 中文字幕精品一区二区精品| 中文字幕乱码人妻一区二区三区| 内射白浆一区二区在线观看| 久久一区二区精品综合| 国产精品99精品一区二区三区| 国产精品主播一区二区| 国产精品一区视频| 国产免费播放一区二区| 亚洲电影唐人社一区二区| 无码精品人妻一区二区三区免费 | 久久伊人精品一区二区三区| 国产成人精品无码一区二区老年人| 黑人大战亚洲人精品一区| 成人一区专区在线观看| 精品国产免费一区二区三区香蕉 | 国产成人精品a视频一区| 亚洲高清一区二区三区 | 一区二区高清视频在线观看| 国产免费一区二区三区| 国产一区二区三区不卡观| 无码av不卡一区二区三区| 日韩一区二区三区射精| 亚洲无删减国产精品一区| 中文字幕无码免费久久9一区9| 色屁屁一区二区三区视频国产|