使用Go語言web框架wego實現使用者登入功能

haming 發表於 2022-11-24
框架 Go

介紹

本文透過一個簡單的例子說明如何使用wego框架來實現使用者登入功能。主要功能如下:

  1. 使用者訪問需要進行登入驗證的頁面時,首先會檢查session的登入賬號,若沒有登入賬號,則跳轉到登入頁面。
  2. 使用者提交登入頁面後,驗證是否是合法的使用者,若透過驗證,則儲存使用者賬號到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提供了兩種攔截器:

  1. 函式型攔截器
  2. 介面型攔截器

本例子中我們使用介面型攔截器來實現登入驗證,首先定義一個基礎的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>