爲了學習go我從0開始用beego寫了一個簡單我的博客(2)登錄管理

當主頁面成功展現以後咱們開始作一個簡單的登錄系統css

1、 登錄功能html

登錄的時候咱們須要保存用戶的登錄狀態,這個時候咱們就要用到session了mysql

beego官方支持文件、緩存、數據庫幾種保存session的方式我選擇了mysql數據庫方式git

這個時候就要用到app.conf下面的這幾個參數了github

sessionon = truesql

sessionhashkey = "asdsdfsdfsdfsfdsf"數據庫

sessionprovider = "mysql"bootstrap

sessionname = "servesession"緩存

sessionname和sessionhashkey是自定義的session

首先你須要手動在你項目相關的數據庫表中建立session這個表

官方給出的sql建立語是

CREATE TABLE `session` (
        `session_key` char(64) NOT NULL,
        `session_data` blob,
        `session_expiry` int(11) unsigned NOT NULL,
        PRIMARY KEY (`session_key`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

後續我會將它寫成自定義命令來方便部署項目

建立好數據庫表後,咱們在main.go下面註冊這個session表

func init() {
	if sessionprovider, err := beego.GetConfig("String", "sessionprovider", "--"); err == nil && sessionprovider == "mysql" {
		dbname, _ := beego.GetConfig("String", "dbname", "myblogbygo")
		sqluser, _ := beego.GetConfig("String", "sqluser", "root")
		sqlpass, _ := beego.GetConfig("String", "sqlpass", "123")
		sqlhost, _ := beego.GetConfig("String", "sqlhost", "127.0.0.1")
		sqlport, _ := beego.GetConfig("String", "sqlport", "3306")
		verification := "%s:%s@tcp(%s:%s)/%s?charset=utf8"
		verificationStr := fmt.Sprintf(verification, sqluser, sqlpass, sqlhost, sqlport, dbname)
		beego.BConfig.WebConfig.Session.SessionProviderConfig = verificationStr
	}
}

接下來你就能夠嘗試在contorllers函數下面嘗試

c.SetSession("isLogin", bool(true))和c.GetSession("isLogin")來嘗試是否能夠寫入和或許相對應的session

c.SetSession("isLogin", bool(true))
islogin := c.GetSession("isLogin")
fmt.Println("sessionValue", islogin)

成功後接下來開始寫登錄功能

首先自定義一個初始化用戶的自定義命令,由於beego自己是支持命令模式的,只須要在main.go中的main函數執行以下代碼

orm.RunCommand()

既然如此咱們拓展下這個命令模式,咱們建立一個tools文件夾用來放自定義的拓展功能,在下面建立一個叫commands.go的文件

/tools/commands.go代碼以下

package tools

import (
	"crypto/sha512"
	"encoding/base64"
	"fmt"
	"os"

	"github.com/astaxie/beego/orm"

	"MyblogByGo/models"
)

// 將其設計爲map便於拓展功能
var commandMaps = map[string]func(){
	"initUser":    initUser,
    "initSession": initSessionTable,
}

// initUser 初始化管理員
func initUser() {
	user := new(models.User)
	user.Name = "你的用戶名"
	userpass := "你的密碼"
	myHs := sha512.New() //使用sha512加密方式
	myHs.Write([]byte(userpass))
	myHasPas := myHs.Sum(nil) //這個時候將密碼變爲亂碼,返回的是byte類型
	encodedPss := base64.StdEncoding.EncodeToString([]byte(myHasPas)) //將byte類型轉爲字符串便於存儲
	user.PassWord = encodedPss
	o := orm.NewOrm()
	o.Using("default")
	if id, err := o.Insert(user); err == nil {
		fmt.Println("用戶已經建立:", user.Name, id)
	} else {
		fmt.Println("error:", err)
	}
}

//順便將以前的建立session表也自定義爲命令
func initSessionTable() {
	o := orm.NewOrm()
	o.Using("default")
	sqlstr := "CREATE TABLE `session` " +
		"(`session_key` char(64) NOT NULL,`session_data` blob, `session_expiry` int(11) unsigned NOT NULL,PRIMARY KEY (`session_key`)) " +
		"ENGINE=MyISAM DEFAULT CHARSET=utf8;"
	r := o.Raw(sqlstr)
	_, cerr := r.Exec()
	if cerr == nil {
		fmt.Println("session table create success")
	} else {
		fmt.Println("session table create err:", cerr)
	}
}

// Mycommands 自定義命令
func cMycommands(com func()) {
	if len(os.Args) < 2 {
		return
	} else if mcom, ok := commandMaps[os.Args[1]]; ok {
		mcom()
		os.Exit(0)
	} else {
		com()
	}
}

頁面一樣咱們直接搬bootstrap4的模版第一部分有提到

將這個頁面放到views/blog下面取名叫signin.html並導入相應的依賴腳本。

接下來在controllers下面新建文件叫account.go用來放置和登錄驗證相關的代碼

/controllers/account.go

package controllers

import (
	"crypto/sha512"
	"encoding/base64"
	"fmt"
	"html/template"

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

	"MyblogByGo/models"
)

// AccountController 登錄入口
type AccountController struct {
	beego.Controller
}

// Get Signin blog展現登錄頁面
func (c *AccountController) Get() {
	c.Data["xsrfdata"] = template.HTML(c.XSRFFormHTML())
	c.TplName = "blog/signin.html"
}

// 用於獲取form表單的struct
type userFrom struct {
	Username string `form:"username"`
	Pass     string `form:"pass"`
}

// Post post signin
func (c *AccountController) Post() {
	uf := userFrom{}
    將數據解析到userForm struct中
	if err := c.ParseForm(&uf); err != nil {
		fmt.Println("數據提交出錯:", err)
	} else {
		user := models.User{
			Name: uf.Username,
		}
		o := orm.NewOrm()
		o.Using("default")
		err := o.Read(&user, "Name")
		if err == orm.ErrNoRows {
			fmt.Println("查詢不到用戶:", user.Name)
			c.Data["errmsg"] = "找不到用戶"
			c.Data["xsrfdata"] = template.HTML(c.XSRFFormHTML())
			c.TplName = "blog/signin.html"
		} else if err == orm.ErrMissPK {
			fmt.Println("找不到主鍵")
			c.Data["xsrfdata"] = template.HTML(c.XSRFFormHTML())
			c.TplName = "blog/signin.html"
		} else {
			ufpass := uf.Pass
			myHs := sha512.New()
			myHs.Write([]byte(ufpass))
			myHasPas := myHs.Sum(nil)
			encodedPss := base64.StdEncoding.EncodeToString([]byte(myHasPas))
			if user.PassWord == encodedPss {
				c.SetSession("isLogin", bool(true))
				c.SetSession("userId", int(user.Id))
				// c.SetSession("userid", user.Id)
				c.Redirect("/", 302)
			} else {
				c.Data["errmsg"] = "密碼錯誤"
				c.TplName = "blog/signin.html"
			}
		}

	}
}

// SignOutController 退出登陸
type SignOutController struct {
	beego.Controller
}

// Get 退出登陸
func (c *SignOutController) Get() {
	c.DestroySession()
	url := beego.URLFor("AccountController.Get")
	c.Redirect(url, 302)
}

在views/blog 下面建立signin.html代碼以下

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="/static/img/blog/favicon.ico">

    <title>Signin</title>

    <!-- Bootstrap core CSS -->
    <link href="/static/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href="/static/css/blog/signin.css" rel="stylesheet">
  </head>

  <body class="text-center">
    <form class="form-signin" method="POST" action="/signin" id="user">
      {{ .xsrfdata }}
      <img class="mb-4" src="/static/img/blog/UNADJUSTEDNONRAW_thumb_19a.jpg" alt="" width="72" height="72">
      <h1 class="h3 mb-3 font-weight-normal">請登陸</h1>
      <label for="username" class="sr-only">Username</label>
      <input name="username" type="text" id="username" class="form-control" placeholder="username" required autofocus>
      <label for="pass" class="sr-only">Password</label>
      <input name="pass" type="password" id="pass" class="form-control" placeholder="password" required>
      {{if .errmsg}}
         <!-- 展現錯誤信息 -->
        <p style="color: red">{{.errmsg}}</p>
      {{end}}
      <!-- <div class="checkbox mb-3">
        <label>
          <input type="checkbox" value="remember-me"> Remember me
        </label>
      </div> -->
      <button class="btn btn-lg btn-primary btn-block" type="submit">登陸</button>
      <p class="mt-5 mb-3 text-muted">&copy; 2019-2020 by Space Cowboy</p>
    </form>
  </body>
</html>

注意由於在配置文件中啓用了xsrf防禦,在訪問登錄頁面的時候將生成的xsfr from傳入了模版,並用模版渲染了,詳細看官方文檔

這個時候登錄準備好了,接下來將以前建立的全部表所有在數據庫中生成

在mian.go中導入models文件

import (

    ...

    ...

    _ "MyblogByGo/models"

)

注意在導入的包前面加了一個 _ 是爲了執行包中的init函數,這是一個特殊語法,由於我將註冊數據庫一系列操做放到了init函數裏面了。

先啓動數據庫,這個時候執行go run main.go orm syncdb 就會建立好表,注意數據庫登錄配置不要出錯了。

成功後命令行就會顯示已經建立表

create table your table name

...

...

當這些都準備好了,就能夠執行咱們以前的自定義命令 go run main.go initUser來初始化一個用戶了

註冊好登錄頁面路由

beego.Router("/signin", &controllers.AccountController{})

這個時候就能夠進入你的登錄頁嘗試你註冊的用戶能不能登錄了,注意以前的代碼登錄成功後將跳轉到主頁

登錄頁面展現:

那個頭像是自定義的

相關文章
相關標籤/搜索