Go 項(xiàng)目實(shí)戰(zhàn):Golang HTTP 驗(yàn)證碼
驗(yàn)證碼(CAPTCHA)是“Completely Automated Public Turing test to tell Computers and Humans Apart”(全自動(dòng)區(qū)分計(jì)算機(jī)[1]和人類的圖靈測(cè)試[2])的縮寫,是一種區(qū)分用戶是計(jì)算機(jī)還是人的公共全自動(dòng)程序[3]。可以防止:惡意破解密碼、刷票[4]、論壇灌水,有效防止某個(gè)黑客對(duì)某一個(gè)特定注冊(cè)用戶用特定程序暴力破解方式進(jìn)行不斷的登陸嘗試,實(shí)際上用驗(yàn)證碼是現(xiàn)在很多網(wǎng)站通行的方式,我們利用比較簡(jiǎn)易的方式實(shí)現(xiàn)了這個(gè)功能。這個(gè)問題可以由計(jì)算機(jī)生成并評(píng)判,但是必須只有人類才能解答。由于計(jì)算機(jī)無法解答CAPTCHA的問題,所以回答出問題的用戶就可以被認(rèn)為是人類。
傳統(tǒng)網(wǎng)站驗(yàn)證碼工作機(jī)制
客戶端請(qǐng)求服務(wù)器獲取驗(yàn)證碼圖片 服務(wù)器生成隨機(jī)串(驗(yàn)證碼值)寫入Session,并將驗(yàn)證碼值寫入到圖片中返回給客戶端 客戶端輸入圖片上的字符串提交給服務(wù)器驗(yàn)證 服務(wù)器比對(duì)客戶端提交的字符串值和 Session 中是否匹配,如果匹配則通過驗(yàn)證
由于服務(wù)器生成的驗(yàn)證碼值從始至終均未返回給客戶端,因此,客戶端只能從圖片中識(shí)別驗(yàn)證碼字符串,從而保證人機(jī)校驗(yàn)邏輯。
Go的HTTP驗(yàn)證碼
思路
Go 語言的 HTTP 服務(wù)器默認(rèn)不支持 Session,因此驗(yàn)證碼值需要換個(gè)思路存儲(chǔ),以下是不使用 Session 的邏輯
客戶端請(qǐng)求服務(wù)器獲取驗(yàn)證碼ID 服務(wù)器生成驗(yàn)證碼 ID,并生成驗(yàn)證碼值,將 ID 和值的映射關(guān)系記錄到內(nèi)存或緩存,并將 ID 返回給客戶端 客戶端根據(jù)返回的 ID 請(qǐng)求服務(wù)器獲取驗(yàn)證碼圖片 服務(wù)器獲取到驗(yàn)證碼 ID,從內(nèi)存或緩存中取出驗(yàn)證碼值,將該值寫入圖片并將圖片返回給客戶端 客戶端提交驗(yàn)證碼 ID(第1步獲得)和驗(yàn)證碼值給服務(wù)器驗(yàn)證 服務(wù)器獲取驗(yàn)證碼 ID,從內(nèi)存或緩存中取出驗(yàn)證碼值與客戶端提交的驗(yàn)證碼值比對(duì)
示例
安裝驗(yàn)證碼依賴
go?get?-u?github.com/dchest/captcha
代碼實(shí)現(xiàn)
package?main
???
???import?(
???????"fmt"
???????"github.com/dchest/captcha"
???????"log"
???????"net/http"
???)
???
???func?main()?{
???????//?獲取驗(yàn)證碼?ID
???????http.HandleFunc("/captcha/generate",?func(w?http.ResponseWriter,?r?*http.Request)?{
???????????id?:=?captcha.NewLen(6)
???????????if?_,?err?:=?fmt.Fprint(w,?id);?err?!=?nil?{
???????????????log.Println("generate?captcha?error",?err)
???????????}
???????})
???????//?獲取驗(yàn)證碼圖片
???????http.HandleFunc("/captcha/image",?func(w?http.ResponseWriter,?r?*http.Request)?{
???????????id?:=?r.URL.Query().Get("id")
???????????if?id?==?""?{
???????????????http.Error(w,?"Bad?Request",?http.StatusBadRequest)
???????????????return
???????????}
???????????w.Header().Set("Content-Type",?"image/png")
???????????if?err?:=?captcha.WriteImage(w,?id,?120,?80);?err?!=?nil?{
???????????????log.Println("show?captcha?error",?err)
???????????}
???????})
???????//?業(yè)務(wù)處理
???????http.HandleFunc("/login",?func(w?http.ResponseWriter,?r?*http.Request)?{
???????????if?err?:=?r.ParseForm();?err?!=?nil?{
???????????????log.Println("parseForm?error",?err)
???????????????http.Error(w,?"Internal?Error",?http.StatusInternalServerError)
???????????????return
???????????}
???????????//?獲取驗(yàn)證碼?ID?和驗(yàn)證碼值
???????????id?:=?r.FormValue("id")
???????????value?:=?r.FormValue("value")
???????????//?比對(duì)提交的驗(yàn)證碼值和內(nèi)存中的驗(yàn)證碼值
???????????if?captcha.VerifyString(id,?value)?{
???????????????fmt.Fprint(w,?"ok")
???????????}?else?{
???????????????fmt.Fprint(w,?"mismatch")
???????????}
???????})
???????log.Fatal(http.ListenAndServe(":8080",?nil))
???}
運(yùn)行 訪問/captcha/generate獲得驗(yàn)證碼 ID 訪問/captcha/image?id=驗(yàn)證碼 ID 訪問/login,并輸入第一步的驗(yàn)證碼 ID 和第二步的驗(yàn)證碼值即可查看驗(yàn)證結(jié)果
項(xiàng)目地址
完整代碼 https://github.com/xialeistudio/go-http-captcha-example。
本文作者:xialeistudio
原文鏈接:https://segmentfault.com/a/1190000023703468
參考資料
計(jì)算機(jī): https://baike.baidu.com/item/計(jì)算機(jī)
[2]圖靈測(cè)試: https://baike.baidu.com/item/圖靈測(cè)試
[3]程序: https://baike.baidu.com/item/程序/71525
[4]刷票: https://baike.baidu.com/item/刷票/6540942
推薦閱讀
站長(zhǎng) polarisxu
自己的原創(chuàng)文章
不限于 Go 技術(shù)
職場(chǎng)和創(chuàng)業(yè)經(jīng)驗(yàn)
Go語言中文網(wǎng)
每天為你
分享 Go 知識(shí)
Go愛好者值得關(guān)注
