最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go整合captcha實(shí)現(xiàn)驗(yàn)證碼功能

 更新時(shí)間:2023年03月01日 11:41:18   作者:BarryYan  
最近在使用Go語(yǔ)言搞一個(gè)用戶登錄&注冊(cè)的功能,我們油然會(huì)產(chǎn)生一種增加驗(yàn)證碼的想法。后來(lái)在GitHub上找到了這個(gè)名叫captcha的插件,于是就利用文檔進(jìn)行了初步的學(xué)習(xí),并融入到自己的項(xiàng)目中,整個(gè)過(guò)程下來(lái)感覺(jué)這個(gè)插件的設(shè)計(jì)非常巧妙

最近在使用Go語(yǔ)言搞一個(gè)用戶登錄&注冊(cè)的功能,說(shuō)到登錄&注冊(cè)相關(guān),我們油然會(huì)產(chǎn)生一種增加驗(yàn)證碼的想法,因此著手實(shí)現(xiàn),后來(lái)在GitHub上找到了這個(gè)名叫captcha的插件,于是就利用文檔進(jìn)行了初步的學(xué)習(xí),并融入到自己的項(xiàng)目中,整個(gè)過(guò)程下來(lái)感覺(jué)這個(gè)插件的設(shè)計(jì)非常巧妙,所以就想寫(xiě)一篇文章分享一下,通過(guò)本篇文章,你會(huì)學(xué)到:

  • 利用captcha生成驗(yàn)證碼返回到前端使用
  • 將captcha生成的驗(yàn)證碼點(diǎn)擊刷新
  • 將captcha生成的驗(yàn)證碼利用Redis進(jìn)行緩存

1 captcha概述

GitHub:https://github.com/dchest/captcha

captcha的使用設(shè)計(jì)流程

2 實(shí)現(xiàn)代碼(使用內(nèi)存緩存)

2.1 后端代碼

生成驗(yàn)證碼圖片API:

//GenerateImg 生成驗(yàn)證碼圖片名稱
func GenerateImg(w http.ResponseWriter, req *http.Request) {
   w.Header().Set("Access-Control-Allow-Origin", "*")             //允許訪問(wèn)所有域
   w.Header().Add("Access-Control-Allow-Headers", "Content-Type") 
   d := struct {
      CaptchaId string
   }{
      captcha.New(),
   }
   bytes, _ := json.Marshal(map[string]interface{}{"code": 0, "msg": "", "count": 0, "data": d.CaptchaId})
   w.Write(bytes)
}

HTTP服務(wù):

func RunHttp(port string) {
   logger := log.Default()

   http.Header{}.Set("Access-Control-Allow-Origin", "*")

   http.HandleFunc("/user/login", controller.UserLogin) //登錄API
   http.HandleFunc("/img", controller.GenerateImg)  //生成驗(yàn)證碼圖片API
   http.Handle("/verify/", captcha.Server(captcha.StdWidth, captcha.StdHeight)) //刷新驗(yàn)證碼API

   logger.Println("Http Server Running port:", port, "...")
   http.ListenAndServe(":"+port, nil)
}

啟動(dòng)HTTP服務(wù):

func main() {
   web.RunHttp("8000")
}

驗(yàn)證碼驗(yàn)證:

//UserLogin 用戶登錄
func UserLogin(w http.ResponseWriter, req *http.Request) {
   w.Header().Set("Access-Control-Allow-Origin", "*")
   w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
   ......
   var m map[string]string
   body, err := ioutil.ReadAll(req.Body)
   if err != nil {
      panic(err)
   }
   json.Unmarshal(body, &m)
   var k = m["verify_key"]
   var v = m["verify_value"]
   res := captcha.VerifyString(k, v)
   if res { // 驗(yàn)證通過(guò)
     ......
   } else { // 驗(yàn)證未通過(guò)
     ......
   }
   ......
}

2.2 前端代碼

......

<form class="layui-form" id="form">
    <h3 style="font-size: 20px;text-align: center;margin-bottom: 30px;">登錄</h3>
    <div class="layui-form-item">
        <label class="layui-form-label">賬號(hào)</label>
        <div class="layui-input-inline">
            <input type="text" id="loginName" placeholder="請(qǐng)輸入賬號(hào)" autocomplete="off"
                   class="layui-input">
        </div>
    </div>
    <div class="layui-form-item">
        <label class="layui-form-label">密碼</label>
        <div class="layui-input-inline">
            <input type="password" id="loginPwd" placeholder="請(qǐng)輸入密碼" autocomplete="off"
                   class="layui-input">
        </div>
    </div>
    <div class="layui-form-item">
        <label class="layui-form-label">驗(yàn)證碼</label>
        <div class="layui-input-inline">
            <input type="text" id="loginV" placeholder="請(qǐng)輸入驗(yàn)證碼" autocomplete="off"
                   class="layui-input">
        </div>
    </div>
    <div class="layui-form-item">
        <div class="layui-input-block">
            <button class="layui-btn" type="button" onclick="login()">立即提交</button>
            <button type="button" onclick="toRegister()" class="layui-btn layui-btn-primary">注冊(cè)</button>
        </div>
    </div>
</form>
<img id="verify" onclick="reload()"></img>
......
<input type="hidden" id="verify_key">
</body>
<script src="http://unpkg.com/layui@2.6.8/dist/layui.js"></script>
<script src="http://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script>
    const base_url = 'http://localhost:8000'

    init()

    function init() {
        $.ajax({
            url: base_url + "/img",
            type: "GET",
            success: function (res) {
                var obj = JSON.parse(res)
                $("#verify").attr("src", base_url + "/verify/" + obj.data + ".png")
                $("#verify_key").attr("value", obj.data)
            }
        })
    }

    function reload() {
        var url = $("#verify").attr("src");
        $("#verify").attr("src", url + "?reload=" + (new Date()).getTime())
    }

    function login() {
        var loginName = $("#loginName").val()
        var loginPwd = $("#loginPwd").val()
        var verify_key = $("#verify_key").val()
        var loginV = $("#loginV").val()
        var data = {
            'login_name': loginName,
            'pwd': loginPwd,
            'verify_key': verify_key,
            'verify_value': loginV
        }
        $.ajax({
            url: base_url + "/user/login",
            type: "POST",
            data: JSON.stringify(data),
            success: function (res) {
               ......
            },
            ......
        })
    }

   ......
   
</script>

2.3 注意點(diǎn)

跨域問(wèn)題:可加入如下代碼

w.Header().Set("Access-Control-Allow-Origin", "*")             //允許訪問(wèn)所有域
w.Header().Add("Access-Control-Allow-Headers", "Content-Type") 

3 自定義Store(使用Redis緩存)

3.1 自定義對(duì)象并實(shí)現(xiàn)Store抽象

Redis初始化:

var (
   RDB          *redis.Client
   TokenTimeOut = time.Second * 3600
)

func init() {
   RDB = redis.NewClient(&redis.Options{
      Addr:     "127.0.0.1:6379",
      Password: "",
      DB:       0,
   })
}

自定義結(jié)構(gòu)體&實(shí)現(xiàn)Store抽象:

type StoreImpl struct {
   RDB        *redis.Client
   Expiration time.Duration
}

func (impl *StoreImpl) Set(id string, digits []byte) {
   impl.RDB.Set(context.Background(), id, string(digits), impl.Expiration)
}

func (impl *StoreImpl) Get(id string, clear bool) (digits []byte) {
   bytes, _ := impl.RDB.Get(context.Background(), id).Bytes()
   return bytes
}

3.2 配置captcha,加入自定義Store實(shí)現(xiàn)

//GenerateImg 生成驗(yàn)證碼圖片名稱
func GenerateImg(w http.ResponseWriter, req *http.Request) {
   w.Header().Set("Access-Control-Allow-Origin", "*")             //允許訪問(wèn)所有域
   w.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的類型
   //需要在New之前進(jìn)行指定
   captcha.SetCustomStore(&verify.StoreImpl{
      RDB:        dao.RDB,
      Expiration: time.Second * 1000,
   })
   d := struct {
      CaptchaId string
   }{
      captcha.New(),
   }
   bytes, _ := json.Marshal(map[string]interface{}{"code": 0, "msg": "", "count": 0, "data": d.CaptchaId})
   w.Write(bytes)
}

3.3 注意點(diǎn)

  • 需要在captcha.New()之前進(jìn)行captcha.SetCustomStore()
  • 在captcha.SetCustomStore()之后,自定義的方法實(shí)現(xiàn)Store接口時(shí)需要完整實(shí)現(xiàn),也就是能真正的實(shí)現(xiàn)存儲(chǔ)或緩存功能,否則驗(yàn)證碼無(wú)法生成

到此這篇關(guān)于Go整合captcha實(shí)現(xiàn)驗(yàn)證碼功能的文章就介紹到這了,更多相關(guān)Go captcha驗(yàn)證碼內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang操作Redis的實(shí)現(xiàn)示例

    golang操作Redis的實(shí)現(xiàn)示例

    本文主要介紹了golang操作Redis的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04
  • Golang中channel的原理解讀(推薦)

    Golang中channel的原理解讀(推薦)

    channel主要是為了實(shí)現(xiàn)go的并發(fā)特性,用于并發(fā)通信的,也就是在不同的協(xié)程單元goroutine之間同步通信。接下來(lái)通過(guò)本文給大家介紹Golang中channel的原理解讀,感興趣的朋友一起看看吧
    2021-10-10
  • golang中的io.ReadCloser與ioutil.NopCloser使用

    golang中的io.ReadCloser與ioutil.NopCloser使用

    這篇文章主要介紹了golang中的io.ReadCloser與ioutil.NopCloser使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 一文掌握go的sync.RWMutex鎖

    一文掌握go的sync.RWMutex鎖

    這篇文章主要介紹了一文掌握go的sync.RWMutex鎖,本文是為了在面試中能快速口述RW鎖,并非為了完整解答RW鎖的機(jī)制,需要的朋友可以參考下
    2023-03-03
  • 一文帶你了解Go語(yǔ)言中的單元測(cè)試

    一文帶你了解Go語(yǔ)言中的單元測(cè)試

    寫(xiě)過(guò)單元測(cè)試的開(kāi)發(fā)人員應(yīng)該理解,單元測(cè)試最核心的價(jià)值是為了證明:為什么我寫(xiě)的代碼是正確的?也就是從邏輯角度幫你檢查你的代碼。本文就來(lái)和大家詳細(xì)聊聊Go語(yǔ)言中的單元測(cè)試,需要的可以參考一下
    2022-07-07
  • 詳解Golang中日志庫(kù)glog的使用

    詳解Golang中日志庫(kù)glog的使用

    golang/glog?是?C++?版本?google/glog?的?Go?版本實(shí)現(xiàn),基本實(shí)現(xiàn)了原生?glog?的日志格式,下面大家就跟隨小編一起了解一下glog的具體使用吧
    2023-09-09
  • GO語(yǔ)言協(xié)程創(chuàng)建使用并通過(guò)channel解決資源競(jìng)爭(zhēng)

    GO語(yǔ)言協(xié)程創(chuàng)建使用并通過(guò)channel解決資源競(jìng)爭(zhēng)

    這篇文章主要為大家介紹了GO語(yǔ)言協(xié)程創(chuàng)建使用并通過(guò)channel解決資源競(jìng)爭(zhēng),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • 輕松讀懂Golang中的數(shù)組和切片

    輕松讀懂Golang中的數(shù)組和切片

    這篇文章主要給大家介紹了關(guān)于Golang中數(shù)組和切片的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者Golang具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03
  • 一站式解決方案:在Windows和Linux上快速搭建Go語(yǔ)言開(kāi)發(fā)環(huán)境

    一站式解決方案:在Windows和Linux上快速搭建Go語(yǔ)言開(kāi)發(fā)環(huán)境

    本文將介紹如何在Windows和Linux操作系統(tǒng)下搭建Go語(yǔ)言開(kāi)發(fā)環(huán)境,以幫助您更高效地進(jìn)行Go語(yǔ)言開(kāi)發(fā),需要的朋友可以參考下
    2023-10-10
  • go panic時(shí)如何讓函數(shù)返回?cái)?shù)據(jù)?

    go panic時(shí)如何讓函數(shù)返回?cái)?shù)據(jù)?

    今天小編就為大家分享一篇關(guān)于go panic時(shí)如何讓函數(shù)返回?cái)?shù)據(jù)?,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04

最新評(píng)論

万源市| 宣化县| 师宗县| 吉安县| 夏邑县| 大余县| 巴塘县| 鄯善县| 建始县| 东乌珠穆沁旗| 德钦县| 合川市| 东宁县| 田阳县| 普兰店市| 泊头市| 咸阳市| 中方县| 荥经县| 航空| 永嘉县| 湖南省| 衡南县| 灌阳县| 邮箱| 呼玛县| 甘德县| 石台县| 岳西县| 辽源市| 清远市| 鄢陵县| 盐池县| 东丽区| 乾安县| 黎城县| 甘肃省| 清远市| 无锡市| 榆林市| 六安市|