GO實(shí)戰(zhàn)——Gin+dchest/captcha實(shí)現(xiàn)圖片驗(yàn)證碼

最近研究了下開源的驗(yàn)證碼框架dchest/captcha github地址,可以實(shí)現(xiàn)圖片驗(yàn)證碼(數(shù)字+運(yùn)算公式),聲音驗(yàn)證碼。今天就以圖片驗(yàn)證碼為例子,做個(gè)簡單demo

分析思路

驗(yàn)證碼流程圖.jpg

根據(jù)框架源碼介紹,大概可以分為三塊內(nèi)容

  1. 創(chuàng)建驗(yàn)證碼
  2. 校驗(yàn)驗(yàn)證碼
  3. 驗(yàn)證碼圖片獲取

1.創(chuàng)建驗(yàn)證碼

創(chuàng)建驗(yàn)證碼函數(shù)變量代碼

type CaptchaResponse struct {
    CaptchaId string `json:"captchaId"`

    ImageUrl string `json:"imageUrl"`
}

var GetCaptcha = func(context *gin.Context) {
    baseResponse := model.NewBaseResponse()
    d := struct {
        CaptchaId string
    }{
        captcha.New(),
    }
    if d.CaptchaId != "" {
        baseResponse.GetSuccessResponse()
        var captcha model.CaptchaResponse
        captcha.CaptchaId = d.CaptchaId
        captcha.ImageUrl = "/show/" + d.CaptchaId + ".png"
        baseResponse.Data = captcha
    } else {
        baseResponse.GetFailureResponse(model.SYSTEM_ERROE)
    }
    context.JSON(http.StatusOK, baseResponse)
}

2.校驗(yàn)驗(yàn)證碼

校驗(yàn)驗(yàn)證碼函數(shù)變量代碼

var VerifyCaptcha = func(context *gin.Context) {
    baseResponse := model.NewBaseResponse()
    captchaId := context.Request.FormValue("captchaId")
    value := context.Request.FormValue("value")
    if captchaId == "" || value == "" {
        baseResponse.GetFailureResponse(model.QUERY_PARAM_ERROR)
    } else {
        if captcha.VerifyString(captchaId, value) {
            baseResponse.GetSuccessResponse()
            baseResponse.Message = "驗(yàn)證成功"
        } else {
            baseResponse.GetFailureResponse(model.CAPTCHA_ERROR)
        }
    }
    context.JSON(http.StatusOK, baseResponse)
}

3.驗(yàn)證碼圖片獲取

dchest/captcha框架中圖片獲取是用的非Gin方式實(shí)現(xiàn),并且Gin對文件下載支持的并不友好。想要使用Gin方式實(shí)現(xiàn),得將框架源碼中圖片查找response代碼copy一份自己實(shí)現(xiàn)。

func Serve(w http.ResponseWriter, r *http.Request, id, ext, lang string, download bool, width, height int) error {
    w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
    w.Header().Set("Pragma", "no-cache")
    w.Header().Set("Expires", "0")

    var content bytes.Buffer
    switch ext {
    case ".png":
        w.Header().Set("Content-Type", "image/png")
        captcha.WriteImage(&content, id, width, height)
    case ".wav":
        w.Header().Set("Content-Type", "audio/x-wav")
        captcha.WriteAudio(&content, id, lang)
    default:
        return captcha.ErrNotFound
    }

    if download {
        w.Header().Set("Content-Type", "application/octet-stream")
    }
    http.ServeContent(w, r, id+ext, time.Time{}, bytes.NewReader(content.Bytes()))
    return nil
}

func ServeHTTP(w http.ResponseWriter, r *http.Request) {
    dir, file := path.Split(r.URL.Path)
    ext := path.Ext(file)
    id := file[:len(file)-len(ext)]
    fmt.Println("file : " + file)
    fmt.Println("ext : " + ext)
    fmt.Println("id : " + id)
    if ext == "" || id == "" {
        http.NotFound(w, r)
        return
    }
    fmt.Println("reload : " + r.FormValue("reload"))
    if r.FormValue("reload") != "" {
        captcha.Reload(id)
    }
    lang := strings.ToLower(r.FormValue("lang"))
    download := path.Base(dir) == "download"
    if Serve(w, r, id, ext, lang, download, captcha.StdWidth, captcha.StdHeight) == captcha.ErrNotFound {
        http.NotFound(w, r)
    }

從這里可以看出,加載音頻驗(yàn)證碼文件也是從這里實(shí)現(xiàn)的。
接下來,實(shí)現(xiàn)圖片加載函數(shù)變量

var GetCaptchaPng = func(context *gin.Context) {
    source := context.Param("source")
    logrus.Info("GetCaptchaPng : " + source)
    recaptcha.ServeHTTP(context.Writer, context.Request)
}

Gin部分

驗(yàn)證碼邏輯已寫完,接下來用Gin將代碼跑起來

func main() {
    ginRouter := gin.New()
    ginRouter.GET("/getCaptcha", controller.GetCaptcha)
    ginRouter.GET("/verifyCaptcha", controller.VerifyCaptcha)
    ginRouter.GET("/show/:source", controller.GetCaptchaPng)
    ginRouter.Run(":8080")
}

測試效果

  1. 使用postman調(diào)用獲取驗(yàn)證碼
    得到返回結(jié)果
{
    "code": 1000,
    "message": "success",
    "data": {
        "captchaId": "VaK1byBtI8TUh8KP6ZrO",
        "imageUrl": "/show/VaK1byBtI8TUh8KP6ZrO.png"
    }
}

其中 captchaId就是驗(yàn)證碼的Id(非value)
imageUrl就是生成的驗(yàn)證碼圖片路徑,保存在服務(wù)器本地

  1. 獲取驗(yàn)證碼圖片
    加上Host,訪問圖片地址http://192.168.1.2:8080/show/VaK1byBtI8TUh8KP6ZrO.png
    得到圖片效果如下
    驗(yàn)證碼圖片.jpg

如想要刷新圖片驗(yàn)證碼,則只需要將url參數(shù)加上&reload=true
http://192.168.1.2:8080/show/VaK1byBtI8TUh8KP6ZrO.png&reload=true
這樣會將新生成的驗(yàn)證碼value替換覆蓋原來的。

  1. 使用postman調(diào)用驗(yàn)證驗(yàn)證碼
    傳入captchaId和圖片中驗(yàn)證碼的值
    得到結(jié)果如下
{
    "code": 1000,
    "message": "驗(yàn)證成功"
}

注意: 驗(yàn)證碼驗(yàn)證成功后,緩存圖片即被清除

最后

附上完整代碼 github地址
如加星,萬分感激.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容