Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
家好!我是黑客之家小編,黑客之家頭條號
分享黑客技術,GO、Python、Kotlin、Android、Java編程知識,科技資訊等
喜歡的朋友可以關注我的頭條號!
圖形驗證碼是我們經常會用到的,例如在app或者網站注冊的時候,登錄的時候等等。圖形驗證碼屬于驗證碼的一種。
圖形驗證碼
驗證碼(CAPTCHA)是 “Completely Automated Public Turing test to tell Computers and Humans Apart”(全自動區分計算機和人類的圖靈測試)的縮寫,是一種區分用戶是計算機還是人的公共全自動程序。
采用圖形驗證碼是為了數據的安全,防止某些破解軟件,進行無限嘗試破解,圖形的話,軟件無法識別,或識別的慢,這樣更加安全。
理論上圖形驗證碼是比較安全的,但是隨著技術的發展,特別是機器學習和人工智能技術的發展,圖形驗證碼也變得不安全了,今天我們將要生成的數字字母組合的驗證碼,其實已經不夠安全了,生成效果如下:
這種驗證碼還是容易被機器識別的,后續的文章中會介紹如何采用程序識別這類圖形驗證碼。
接著說圖形驗證碼的生成,今天我們采用的是kaptcha。kaptcha是一個可配置驗證碼生成工具包,我們按照kaptcha的配置表配置就可以了。
在使用kaptcha之前,要導入kaptcha的包,依賴如下:
<dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
在Spring Boot項目中新建一個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的樣式和顏色字體等就設置好了,接著就是生成圖形上的字符,同時通過二進制流的形式把生成的圖片返回給前端。
代碼如下:
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方式獲取到生成的圖形驗證碼了。
為了能在瀏覽器里顯示我們這里采用thymeleaf模板。
在pom.xml文件中引入thymeleaf依賴如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
之后在templates文件夾下新建一個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="點擊更換" title="點擊更換" onclick="refresh()" src="/api/getVerifyCode"/> </div> </body> </html>
這樣一個簡單前端顯示圖形驗證碼就做好了,之后我們輸入http://localhost:8090/,就可以訪問了,8090換成自己對應的端口。
圖形驗證碼
點擊圖片可以切換圖形驗證碼。至此,圖形驗證碼功能結束!
如果覺得文章對你有幫助,歡迎關注,點贊,轉發,評論!后續文章會介紹如何通過程序識別今天生成的圖形驗證碼,感興趣的同學,可以持續關注!
相關閱讀:
基于spring boot快速搭建Java服務器
Spring Boot項目部署簡單方便的Shell腳本
推薦一款Spring Boot中非常好用的插件
網頁設計中,尤其表單填寫提交過程中,為防止機器自動登錄,很多網頁都采用驗證碼技術,允許用戶輸入而盡量避免自動登錄。驗證碼實現的方法有很多,PHP繪圖技術可以在服務端生成驗證碼并發送客戶端,HTML5技術下可以使用canvas與JS腳本實現在客戶端瀏覽器自動生成驗證碼。本文給出JS+Canvas驗證碼的解決措施,所制作驗證碼實現效果如下圖所示:
驗證碼實現效果動態圖
本例驗證碼的實現主要包括驗證碼字符串的生成、背景干擾點實現及干擾直線的生成三部分。最終通過canvas繪圖技術將生成的驗證碼字符串、背景及干擾直線顯示到畫布上。主要涉及技術或知識點包括canvas繪圖技術、數組、鼠標點擊事件、隨機函數等。以下從驗證字符串、背景干擾點及干擾直線三方面對實現過程進行說明。
驗證字符串部分主要借助數組存儲驗證碼所有字符,通過調用Math對象的隨機函數獲取數組下標,并通過數組下表讀取數組元素,將讀取的數組元素組裝成完整字符串。其實現核心代碼如下:
驗證字符串獲取核心代碼
如上圖所示,本例驗證碼字符包括數字與大寫字母,getCode函數返回值即為4位驗證碼字符串。
背景干擾點可以直接使用canvas對應的繪圖方法進行繪制,本例為簡化開發過程,降低難度直接使用drawImage繪圖方式加載背景圖片,實現干擾點效果。背景圖片如下:
背景干擾點圖片
通過調用drawImage方法,指定截取的坐標位置參數,可實現背景干擾點的動態變化效果,背景干擾點實現核心代碼如下:
背景干擾點實現代碼
其中getXsize與getYsize為獲取繪圖截取背景圖片的坐標位置,通過使用隨機函數實現從背景圖片不同位置截取進行繪圖輸出。
干擾直線實現較為簡單,直接通過JS提供的moveTo與lineTo方法完成直線的繪制,本例繪制了兩條直線,一條為黑色干擾線,一條為白色干擾線。在繪制過程兩端點需要使用Math隨機函數生成符合條件隨機坐標。干擾直線相關實現代碼如下:
干擾直線實現核心代碼
干擾直線實現核心代碼如上圖,其中getLsize方法主要用于獲取隨機端點Y軸坐標值。strokeStyle主要用于設置繪圖直線的顏色。
驗證碼的顯示輸出主要使用fillText()方法在canvas指定位置進行文字輸出,本例使用第三方ttf字體,因此在HTML頁面中對字體進行了加載。驗證碼顯示輸出實現代碼如下:
驗證碼繪制
驗證碼顯示輸出核心代碼如上圖所示,其中myfont為加載的第三方字體。
繪圖基礎部分主要包括前端canvas元素的布局等。包括屬性的設置,js部分元素的獲取及屬性設置等。
我們一般接觸的驗證碼,都可以點擊圖片實現驗證碼的刷新,因此本例為canvas標記添加了onclick事件,將所有驗證碼生成的代碼封裝到showCode()函數中,通過調用showCode函數實現驗證碼的刷新。本例完整JS腳本部分代碼如下:
JS實現腳本代碼
本頭條號長期關注編程資訊分享;編程課程、素材、代碼分享及編程培訓。如果您對以上方面有興趣或代碼錯誤、建議與意見,可以聯系作者,共同探討。期待大家關注!如需案例完整代碼請關注并私信,往期前端設計文章鏈接如下:
近有同事在調研微信小程序,準備把我們的 landing page(LP)頁面,遷移到小程序里,提高用戶體驗,提升轉化率。
在LP里,遇到個很常見的問題,用戶通過手機號注冊,發送短信驗證碼需要防刷,目前在 h5 上使用的是 圖形驗證碼+極驗。一上來,就遇到了圖形驗證碼的問題。小程序和 web 開發不同,不會 自動處理 http 請求的 cookie。
通常在 web 上,我們會把圖形驗證碼存儲到用戶 session 里,然后在發送短信的接口,判斷用戶提交的圖形驗證碼和 session 里的值是否相等,這里依賴瀏覽器自動會處理 cookie 的讀寫來實現的。但是小程序里,需要開發者主動來管理 cookie 等,并且在圖片請求中,也 不能 主動設置cookie,導致之前 web 上的圖形驗證碼完全失效。
在網上發現提到小程序里的圖形驗證碼實現的文章很少,就有一篇這個 wechat-captcha ,但是作者這是純前端用 canvas 來繪制的圖形驗證碼,顯然,圖形驗證碼的生成,只能放在 server 端,這種方案,就需要有一種很好的方式,來講server端生成的圖形驗證碼的值,傳遞到前端來。沒想到有什么方案,能從server端比較穩妥的傳遞圖形驗證碼的值到小程序里,只能看看其他大廠是怎么做的了。
server 返回圖片base64編碼
同事發現餓了么的小程序里,是有圖形驗證碼的,那就先來看看餓了么的同學是怎么實現的呢。經過抓包,很明顯能看到餓了么的圖片驗證碼請求,是通過 js 來發起的,server 端返回的圖形驗證碼的 base64 編碼,沒有繼續看后續是怎么把 base64 編碼渲染到出來的,但肯定是有辦法將 base64 的圖形驗證碼繪制到 canvas 上的。
其實這里是有個疑問的,在抓包的時候,發現在請求圖形驗證碼的時(POST),并沒有帶上 cookie,也就是說,餓了么并沒有用 cookie-session 來存儲某個手機號對應的圖形驗證碼;并且用戶的手機號,拼在了請求的 url 里,似乎在server端是通過其他方式,來存儲的手機號和圖形驗證碼的關聯。
我不太理解的是,既然用戶手機號已經放在請求的 path 里了,為什么要使用 POST 來單獨請求圖驗的 base64 編碼,再渲染到 canvas 上,為什么不直接拼一個 GET 的 url,同樣把手機號放進去,然后接口直接輸出二進制的圖片數據,這樣就可以直接把 url 賦值給小程序的 image 組件了。
餓了么抓包如下(響應中的 captcha_image 字段就是 png 圖片的 base64編碼):
使用 WebView
然后又看了下美團的小程序,直接沒用圖形驗證碼,而是用的類似極驗的滑塊。猜想也是使用了 canvas 之類的技術來實現的,抓包才發現,原來是用的 web-view組件來引用的 html 頁面。剛重新抓包過程中,雖然后端響應接口確實返回了一個 h5 的滑塊頁面URL,但是沒看到有加載這個頁面,看來美團也 沒有 用 web-view 來加載 h5。
美團抓包如下:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。