提示:当调用过 captcha.VerifyString 后需要重新生成新的 CaptchaId !
核心控制器代码
package pubcontrollers import ( "time" "bytes" "net/http" "github.com/kataras/iris/v12" "github.com/kataras/iris/v12/mvc" "github.com/dchest/captcha" ) type CaptchaController struct{ Ctx iris.Context } func (c *CaptchaController) BeforeActivation(b mvc.BeforeActivation) { b.Handle("GET", "/captcha/{captcha_id}", "CaptchaImage") } func (c *CaptchaController) CaptchaImage() { captcha_id := c.Ctx.Params().Get("captcha_id") if c.Ctx.URLParam("t") != "" { captcha.Reload(captcha_id) } c.responseCaptchaImage(captcha_id, 200, 50) } func (c *CaptchaController) responseCaptchaImage(id string, width, height int) error { w := c.Ctx.ResponseWriter() r := c.Ctx.Request() 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 ext := ".png" 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, "zh") default: return captcha.ErrNotFound } download := false if download { w.Header().Set("Content-Type", "application/octet-stream") } http.ServeContent(w, r, id+ext, time.Time{}, bytes.NewReader(content.Bytes())) return nil }
创建 captcha_id 的通用工具包文件
package utils import ( "github.com/dchest/captcha" ) type MyCaptchaModel struct { Id string Path string } // 几位数字的验证码 func Captcha(len int) *MyCaptchaModel { captchaId := captcha.NewLen(len) stru := MyCaptchaModel { Id: captchaId, Path : "/pub/captcha/"+ captchaId + "", } return &stru } func VerifyCaptcha(captchaId, postCaptcha string) bool { success := captcha.VerifyString(captchaId, postCaptcha) return success }
登录控制器调用示例
func (c *LoginController) GetLogin() mvc.Result { // 验证码 capt := utils.Captcha(4) return mvc.View{ Name: "pub/login/login.html", Data: iris.Map{ "Title": "登录 | " + utils.AppConfig.AppName, "CaptchaPath": capt.Path, "CaptchaId": capt.Id, }, } }
模板文件 html 示例
<div class="form-group"> <label for="user_password">验证码</label> <img id="captcha_img" height="50" width="100%" src="{{.CaptchaPath}}" title="看不清,点击验证码可变更" /> <input type="text" class="form-control" id="user_captcha" placeholder="验证码"> </div>
部分 js 代码
$("#captcha_img").on("click", function(){ var path = '{{.CaptchaPath}}'; path += '?t=' + new Date().getTime() $("#captcha_img").attr("src", path); }); $("#loginButton").on("click", function(){ var usercode = $("#user_login").val(); var userpass = $("#user_password").val(); var usercapt = $("#user_captcha").val(); if(usercode.length == 0){ pubmain.toast('请输入帐号'); return; } if(userpass.length == 0){ pubmain.toast('请输入密码'); return; } if(usercapt.length == 0){ pubmain.toast('请输入验证码'); return; } $.post("/pub/login", { usercode: usercode, userpass: userpass, usercapt: usercapt, captcha_id: '{{.CaptchaId}}', }, function(json){ if (json.flag){ window.location.replace("/") }else{ pubmain.toast(json.msg); } }); });
后端验证验证码代码
func (c *LoginController) PostLogin() { // ... usercapt := c.Ctx.FormValue("usercapt") captcha_id := c.Ctx.FormValue("captcha_id") if len(usercode) == 0{ c.responseToClient(false, "请输入您的帐号") return } if len(usercapt) == 0{ c.responseToClient(false, "请输入验证码") return } if len(captcha_id) == 0 { c.responseToClient(false, "非法请求") return } if !utils.VerifyCaptcha(captcha_id, usercapt) { c.responseToClient(false, "验证码错误") return } // ... }