Go整合captcha實(shí)現(xiàn)驗(yàn)證碼功能
最近在使用Go語言搞一個(gè)用戶登錄&注冊的功能,說到登錄&注冊相關(guān),我們油然會產(chǎn)生一種增加驗(yàn)證碼的想法,因此著手實(shí)現(xiàn),后來在GitHub上找到了這個(gè)名叫captcha的插件,于是就利用文檔進(jìn)行了初步的學(xué)習(xí),并融入到自己的項(xiàng)目中,整個(gè)過程下來感覺這個(gè)插件的設(shè)計(jì)非常巧妙,所以就想寫一篇文章分享一下,通過本篇文章,你會學(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.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)
}啟動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)證通過
......
} else { // 驗(yàn)證未通過
......
}
......
}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">賬號</label>
<div class="layui-input-inline">
<input type="text" id="loginName" placeholder="請輸入賬號" 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="請輸入密碼" 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="請輸入驗(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">注冊</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.Header().Set("Access-Control-Allow-Origin", "*") //允許訪問所有域
w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
3 自定義Store(使用Redis緩存)
3.1 自定義對象并實(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.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)存儲或緩存功能,否則驗(yàn)證碼無法生成
到此這篇關(guān)于Go整合captcha實(shí)現(xiàn)驗(yàn)證碼功能的文章就介紹到這了,更多相關(guān)Go captcha驗(yàn)證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang中的io.ReadCloser與ioutil.NopCloser使用
這篇文章主要介紹了golang中的io.ReadCloser與ioutil.NopCloser使用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
GO語言協(xié)程創(chuàng)建使用并通過channel解決資源競爭
這篇文章主要為大家介紹了GO語言協(xié)程創(chuàng)建使用并通過channel解決資源競爭,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04
一站式解決方案:在Windows和Linux上快速搭建Go語言開發(fā)環(huán)境
本文將介紹如何在Windows和Linux操作系統(tǒng)下搭建Go語言開發(fā)環(huán)境,以幫助您更高效地進(jìn)行Go語言開發(fā),需要的朋友可以參考下2023-10-10
go panic時(shí)如何讓函數(shù)返回?cái)?shù)據(jù)?
今天小編就為大家分享一篇關(guān)于go panic時(shí)如何讓函數(shù)返回?cái)?shù)據(jù)?,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-04-04

