beego框架(golang)學習驗證碼
登錄頁面使用驗證碼
路由設置
/beego_admin_template/routers/router.go
get請求頁面, post驗證用戶名密碼和驗證碼
beego.Router("/login", &admin.CommonController{},
"get:LoginPage;post:Login")
當url輸入 http://localhost:8080/login 時跳轉到登錄頁面,顯示驗證碼
控制器目錄
/beego_admin_template/controllers/admin/common.go
package admin
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/cache"
captcha2 "github.com/astaxie/beego/utils/captcha"
)
// 全局驗證碼結構體
var captcha *captcha2.Captcha
// init函數初始化captcha
func init() {
// 驗證碼功能
// 使用Beego緩存存儲驗證碼數據
store := cache.NewMemoryCache()
// 創建驗證碼
captcha = captcha2.NewWithFilter("/captcha", store)
// 設置驗證碼長度
captcha.ChallengeNums = 4
// 設置驗證碼模板高度
captcha.StdHeight = 50
// 設置驗證碼模板寬度
captcha.StdWidth = 120
}
// 登錄頁面
func (c *CommonController)LoginPage() {
// 設置模板目錄
c.TplName = "admin/common/login.html"
}
登錄頁面
/beego_admin_template/views/admin/common/login.html
<div style="margin-left: 10px;">
{{create_captcha}}
</div>
驗證驗證碼
// 登錄
func (c *CommonController)Login() {
// 驗證碼驗證
if !captcha.VerifyReq(c.Ctx.Request) {
c.Data["Error"] = "驗證碼錯誤"
return
}
// 其他代碼
……
c.Redirect("/", 302)
}
captcha.go
// VerifyReq verify from a request
func (c *Captcha) VerifyReq(req *http.Request) bool {
// 解析請求體
req.ParseForm()
// 讀取請求參數調用Verify方法
return c.Verify(req.Form.Get(c.FieldIDName), req.Form.Get(c.FieldCaptchaName))
}
// 驗證驗證碼id和字符串
func (c *Captcha) Verify(id string, challenge string) (success bool) {
if len(challenge) == 0 || len(id) == 0 {
return
}
var chars []byte
key := c.key(id)
if v, ok := c.store.Get(key).([]byte); ok {
chars = v
} else {
return
}
defer func() {
// finally remove it
c.store.Delete(key)
}()
if len(chars) != len(challenge) {
return
}
// verify challenge
for i, c := range chars {
if c != challenge[i]-48 {
return
}
}
return true
}
注意點
在調試驗證碼的時候,會發現驗證碼老是錯誤,是因為默認驗證碼是存儲在內存中,每次重啟會刪除內存
源碼查看
文件:common.go
調用緩存包中的NewMemoryCache()函數,返回一個新的內存緩存指針地址
store := cache.NewMemoryCache()
文件:memory.go
MemoryCache是一個內存緩存適配器,它包含一個map帶有讀寫鎖的map存儲
// MemoryCache is Memory cache adapter.
// it contains a RW locker for safe map storage.
type MemoryCache struct {
sync.RWMutex
dur time.Duration
items map[string]*MemoryItem
Every int // run an expiration check Every clock time
}
// NewMemoryCache returns a new MemoryCache.
func NewMemoryCache() Cache {
cache := MemoryCache{items: make(map[string]*MemoryItem)}
return &cache
}
文件:common.go
NewWithFilter()方法創建一個新的驗證碼,並返回該驗證碼的指針
captcha = captcha2.NewWithFilter("/captcha", store)
文件 captcha.go
// 該方法創建了一個驗證碼在指定緩存中
// 增加了一個服務於驗證碼圖片的過濾器
// 並且添加了一個用於輸出html的模板函數
func NewWithFilter(urlPrefix string, store cache.Cache) *Captcha {
// 生成驗證碼結構體
cpt := NewCaptcha(urlPrefix, store)
// 創建過濾器
beego.InsertFilter(cpt.URLPrefix+"*", beego.BeforeRouter, cpt.Handler)
// add to template func map
beego.AddFuncMap("create_captcha", cpt.CreateCaptchaHTML)
return cpt
}
其實 cpt.Handler需要好好看一下,里面包含了beego過濾器的使用