当主页面成功展示之后我们开始做一个简单的登陆系统
一、 登陆功能
登陆的时候我们需要保存用户的登陆状态,这个时候我们就要用到session了
beego官方支持文件、缓存、数据库几种保存session的方式我选择了mysql数据库方式
这个时候就要用到app.conf下面的这几个参数了
sessionon = true
sessionhashkey = "asdsdfsdfsdfsfdsf"
sessionprovider = "mysql"
sessionname = "servesession"
sessionname和sessionhashkey是自定义的
首先你需要手动在你项目相关的数据库表中创建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">© 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{})
这个时候就可以进入你的登陆页尝试你注册的用户能不能登陆了,注意之前的代码登陆成功后将跳转到主页
登陆页面展示:
那个头像是自定义的