iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
0
Modern Web

BeeGo系列 第 16

Middleware / Filter(2)

  • 分享至 

  • xImage
  •  

上篇介紹了 Filter 的使用以及 Django 的作法,這篇我們就來試著簡化 Django 的作法,然後參考官方文件,來實作一個在驗證失敗後會導向到 /login 的 Filter。

建立資料表格

先回頭複習一下 migration,先建立 model

bee generate model Member -fields="username:string,password:string" -driver="mysql"

然後再建立 migration

bee generate migration user -fields="name:string,gender:string,birthday:datetime"
bee migrate

用 MySQL CLI 新增一筆資料,密碼部份先暫時使用明碼。

mysql
mysql> use hellodb;
mysql> insert into member (username, password) values ('johndoe', 'his_password');

登入頁面

接著實作登入頁面

bee generate controller login

編輯 controllers/login.go

package controllers

import (
    "html/template"
    "my/hello/models"

    "github.com/astaxie/beego"
    "github.com/astaxie/beego/orm"
)

// LoginController operations for Login
type LoginController struct {
    beego.Controller
}

// Post ...
// 處理登入
func (c *LoginController) Post() {
    c.TplName = "login/index.tpl"
    c.Data["has_error"] = false
    // Check XSRF first.
    if !c.CheckXSRFCookie() {
        c.Data["error"] = "XSRF token missing or incorrect."
        c.Data["has_error"] = true
        return
    }

    // parse form parameters
    username := c.GetString("username")
    password := c.GetString("password")

    // 以 username 去找使用者
    o := orm.NewOrm()
    v := &models.Member{Username: username}
        // 沒有找到,顯示錯誤
        c.Data["error"] = "No such member."
        c.Data["has_error"] = true
        return
    }
    // 找到使用者,檢查密碼
    if password == v.Password {
        // 在 session 留下 user_id,作為檢查依據
        // 這是簡便作法,實務上要嚴謹
        c.SetSession("user_id", int(v.Id))
    } else {
        c.Data["error"] = "Authentication fail."
        c.Data["has_error"] = true
        return
    }
    c.Ctx.Redirect(302, "/myuser/")
}

// Get ...
// 顯示登入表單
func (c *LoginController) Get() {
    c.Data["has_error"] = false
    c.Data["xsrfdata"] = template.HTML(c.XSRFFormHTML())
    c.TplName = "login/index.tpl"
}

在 router 裡加入登入頁面的路由

beego.Router("/login", &controllers.LoginController{}, "get:Get")
beego.Router("/login", &controllers.LoginController{}, "post:Post")

登出

跟登入一樣,先產生登出的 controller

bee generate controller logout

然後編輯 controllers/logout.go

package controllers

import (
    "github.com/astaxie/beego"
)

// LogoutController operations for Logout
type LogoutController struct {
    beego.Controller
}

// Get
func (c *LogoutController) Get() {
    c.DelSession("user_id")
    c.Data["has_error"] = false
    c.TplName = "logout/index.tpl"
}

同樣也在 routers/router.go 裡加入登出頁面的路由

beego.Router("/logout", &controllers.LogoutController{}, "get:Get")

Filter

終於到 Filter 的部份了,Filter 裡就只是簡單的檢查 user_id,如果沒有,就導向到登入頁。

var FilterMember = func(ctx *context.Context) {
    if strings.HasPrefix(ctx.Input.URL(), "/login") {
        return
    }

    _, ok := ctx.Input.Session("user_id").(int)
    if !ok {
        ctx.Redirect(302, "/login")
    }
}

這邊要照 Django 的方法走的話,還需要埋入 user,這樣後續的 Controller 就可以直接判斷或使用。

好,Filter 寫好,接著就來安插進去使用

beego.InsertFilter("/myuser/*", beego.BeforeRouter, FilterMember)

小結

好,到這裡,也差不多完工了。對了,模版的程式碼我省略囉,完整的程式請到 github 上看。


上一篇
Middleware / Filter(1)
下一篇
訊息顯示
系列文
BeeGo30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言