为了学习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{})

这个时候就能够进入你的登录页尝试你注册的用户能不能登录了,注意以前的代码登录成功后将跳转到主页

登录页面展现:

那个头像是自定义的

相关文章
相关标签/搜索