介紹
本文透過一個簡單的例子說明如何使用wego框架來實現使用者登入功能。主要功能如下:
- 使用者訪問需要進行登入驗證的頁面時,首先會檢查session的登入賬號,若沒有登入賬號,則跳轉到登入頁面。
- 使用者提交登入頁面後,驗證是否是合法的使用者,若透過驗證,則儲存使用者賬號到session,並跳轉到index頁面。
說明:本例子採用基於cookie引擎的session
專案的結構
demo
├── controller - 控制器目錄
│ └── base.go - 控制器基礎struct
│ └── home.go - home控制器
│ └── login.go - 登入相關的處理器
├── models - 模型目錄
├── logs - 日誌檔案目錄
├── static - 靜態資源目錄
│ ├── css
│ ├── img
│ └── js
├── view - 檢視模板目錄
│ └── login.html
│ └── index.html
├── app.conf - 應用配置檔案
└── main.go - 入口檔案
配置檔案的內容
#應用名稱
app_name = demo
[server]
#http監聽埠
http_port = 8080
[session]
#session 是否開啟
session_on = true
#session型別
session_store=cookie
#客戶端的cookie的名稱
cookie_name = "wego"
#session 過期時間, 單位秒
life_time = 3600
#session資料的hash字串
hash_key = 123456
重點說明:
- http_port = 8080
<< 服務將監聽8080埠 - [session]
<< 用於設定是否開啟session,並設定session對應的快取引擎,本例子中採用基於cookie的session
main檔案
package main
import (
"demo/controller"
"github.com/haming123/wego"
log "github.com/haming123/wego/dlog"
)
func main() {
web, err := wego.InitWeb()
if err != nil{
log.Error(err)
return
}
web.GET ("/show_login", controller.HandlerShowLogin)
web.POST("/login_post", controller.HandlerLoginPost)
web.GET ("/index", (*controller.HomeController).ShowHome)
err = web.Run()
if err != nil {
log.Error(err)
}
}
登入邏輯
使用者訪問需要進行登入驗證的頁面時,首先會檢查session的登入賬號,若沒有登入賬號,則跳轉到登入頁面, 登入頁面的路由註冊程式碼為:
web.GET ("/show_login", controller.HandlerShowLogin)
controller.HandlerShowLogin為"/show_login"註冊了一個函式型處理器:controller.HandlerShowLogin
:
func HandlerShowLogin(c *wego.WebContext) {
c.WriteHTML(http.StatusOK, "./view/login.html", nil)
}
login.html的內容如下:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>登入頁面</title>
</head>
<body>
<h2>使用者登陸</h2>
<form action="/login_post" method="post">
<div>使用者賬號:</div>
<div>
<input type="text" name="account" placeholder="請輸入使用者賬號" />
</div>
<br />
<div>登入密碼:</div>
<div>
<input type="password" name="password" placeholder="請輸入登入密碼"/>
</div>
<br />
<div>
<input type="submit" value="立即登入" />
</div>
</form>
</body>
</html>
使用者點選"立即登入"後項伺服器傳送post請求:/login_post, /login_post請求的路由註冊程式碼:
web.POST("/login_post", controller.HandlerLoginPost)
controller.HandlerLoginPost為一個函式型處理器:
func HandlerLoginPost(c *wego.WebContext) {
account := c.Param.MustString("account")
password := c.Param.MustString("password")
if account == "admin" && password == "demo" {
c.Session.Set("account", account)
c.Session.Save()
c.Redirect(302, "/index")
} else {
c.Session.Set("account", "")
c.Session.Save()
c.Redirect(302, "/show_login")
}
}
重點說明:
- 透過
c.Param.MustString
函式來獲取form引數 - 驗證透過後將account儲存到session中
- 檢查"account"、"password"引數,若透過驗證,則跳轉到"/index", 否則顯示登入頁面:"/show_login"
實現/index頁面的顯示
實現BaseController
只有透過登入驗證的使用者才可以訪問/index頁面,因此在顯示/index頁面時需要檢查session資料,若存在account,則可以訪問/index頁面,否則跳轉到/show_login頁面
可以為每個需要登入的頁面都實現登入驗證邏輯, 這種做法雖然可行,但是實現起來比較繁瑣。我們可以使用wego框架的攔截器來簡化登入驗證的實現,wego提供了兩種攔截器:
- 函式型攔截器
- 介面型攔截器
本例子中我們使用介面型攔截器來實現登入驗證,首先定義一個基礎的struct:BaseController, 在BaseController中實現了攔截器介面:BeforeExec(ctx *wego.WebContext)
:
type BaseController struct {
}
func (this *BaseController) SetAccount(c *wego.WebContext, val string) {
c.Data.Set("account", val)
}
func (this *BaseController) GetAccount(c *wego.WebContext) string {
uid , _ := c.Data.GetString("account")
return uid
}
func (this *BaseController) BeforeExec(ctx *wego.WebContext) {
account, err := ctx.Session.GetString("account")
if err != nil || account == "" {
ctx.Redirect(302, "/show_login")
return
}
this.SetAccount(c, account)
}
這樣,若一個struct組合了BaseController, 便具有了BeforeExec方法,使用者在訪問處理器是首先會訪問BeforeExec方法, 這樣便可以共用登入驗證邏輯, 不必在每個處理器中重複實現,大大簡化了程式碼的編寫。
實現HomeController
為了共用登入驗證邏輯,首先需要HomeController中組合BaseController:
type HomeController struct {
BaseController
}
接下來是/index頁面的處理器程式碼:
func (this *HomeController) ShowHome(c *wego.WebContext) {
c.WriteHTML(http.StatusOK, "./view/index.html", this.Account)
}
(this *HomeController)ShowHome是一個方法型處理器, 在ShowHome中讀取index.html模板,並使用this.Account進行渲染。index.html模板的內容如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello : {{.}}
</body>
</html>