基于beego+orm的管理系统
一、用户登录
1、main函数为入口,引包的时候调用router路由
import (
_ "cmdb/router" //用户管理的路由,之后由路由进入
"github.com/astaxie/beego" //引用beego的自带包
)
func main() {
beego.Run()
}
2、由main包跳转到路由,使用init初始化函数进行绑定
func init() {
beego.AutoRouter(&controller.AuthController{}) //定义网页路由,在网址输入的时候切记加上auth结构
beego.AutoRouter(&controller.HomeController{}) //绑定
beego.AutoRouter(&controller.QueryController{})
}
注意:其中controller包中含有这几个结构体,每个结构体对应相关的网页以及实现方法
3、逻辑分层
有一些结构体可以直接与beego.Controller组合,但是有一些结构体需要预设条件(比如登录就需要判断session是否存在),就需要定义两个不同的结构体来提供组合
(1)直接与beego.Controller组合
type MainController struct {
beego.Controller
}
(2)与beego.Controller组合,并且增加预设条件
type PrepareController struct {
Base.MainController
LoginUser *models.User
}
func (c *PrepareController) getNav() string {
controllerName, _ := c.GetControllerAndAction() //获取Controller的名字
return strings.ToLower(strings.TrimSuffix(controllerName, "Controller"))
}
func (c *PrepareController) Prepare() {
//设置预设条件
sessionKey := beego.AppConfig.DefaultString("auth::SessionKey", "user") //设置默认值
sessionVal := c.GetSession(sessionKey)
c.Data["loginUser"] = nil
c.Data["nav"] = c.getNav()
if sessionVal != nil {
if pk, ok := sessionVal.(int); ok {
if user := models.IdGetUser(pk); user != nil {
c.LoginUser = user
return
}
}
}
loginAction := beego.AppConfig.DefaultString("auth::LoginAction", "AuthController.Login") //设置默认值
c.Redirect(beego.URLFor(loginAction), http.StatusFound)
}
4、处理登录
(1)在AuthController结构体中定义Login方法,之后绑定模板,可以向模板传值,然后通过auth/login路径访问网址
func (c *AuthController) Login() {
c.Data["form"] = form //传递相关参数
c.Data["errors"] = e //将值传送给模板
c.TplName = "auth/login.html"
}
(2)访问之前进行方法验证,如果是get方法直接跳转,是post方法就进行数据验证
if c.Ctx.Input.IsGet() {
c.TplName = "home/Index.html"
} //如果是get方法就直接跳转页面
if c.Ctx.Input.IsPost() {
//数据验证
} //如果是post方法就进行数据验证
二、数据验证
1、validation进行数据验证
(1)使用Message方式进行验证
u := User{"", 40}
valid := validation.Validation{}
valid.Required(u.Name, "name").Key("姓名").Message("不能为空") //名字不能为空格,第一个参数为判断对象,第二个参数为报错的时候参数名称
valid.MaxSize(u.Name, 15, "nameMax") //设置name参数的最大长度为15
valid.Range(u.Age, 0, 18, "年龄").Message("长度不在范围内") //设置年龄最大长度为18
if valid.HasErrors() { //判断validation是否有错误
// 如果有错误信息,证明验证没通过
// 打印错误信息
for _, err := range valid.Errors { //遍历错误切片
fmt.Println(err.Key, err.Message)
}
}
(2) 使用tag标签来判断
package main
import (
"github.com/astaxie/beego/validation"
"log"
"strings"
)
type User struct {
Name string `valid:"Required;Match(/^Bee.*/)` //Name 不能为空并且以 Bee 开头
Age int `valid:"Range(1,140)"` //设置年龄区间
Email string `valid:"Email; MaxSize(100)"` // Email 字段需要符合邮箱格式,并且最大长度不能大于 100 个字符
Mobile string `valid:"Mobile"` // Mobile 必须为正确的手机号
IP string `valid:"IP"` // IP 必须为一个正确的 IPv4 地址
}
//实现结构自定义错误
func (u *User) Vaild(v *validation.Validation) {
if strings.Index(u.Name, "admin") != -1 {
v.SetError("Name", "名字里面不能含有admin")
}
}
func main() {
vaild := validation.Validation{} //实例化一个结构体
u := User{Name: "yangadmin", Age: 0, Email: "dev@web.me", Mobile: "的方式", IP: "123"}
b, err := vaild.Valid(&u) //将结构体传入进行判断
if err != nil {
log.Fatal("err")
}
if !b {
for _, err := range vaild.Errors {
log.Fatal(err.Key, err.Message)
}
}
}
2、Flash
处理成功后将消息储存;想要显示时从储存中取出消息并显示,设置将数据储存到flash中,实际上就是储存在cookie中(举例说明:当需要重定向,但是需要一些信息在重定向的时候进行传递的时候)
flash对象有三个级别的设置:Notice提示信息,Warning警告信息,Error错误信息
// 显示设置信息
func (c *MainController) Get() {
flash:=web.ReadFromRequest(&c.Controller)
if n,ok:=flash.Data["notice"];ok{
// 显示设置成功
c.TplName = "set_success.html"
}else if n,ok=flash.Data["error"];ok{
// 显示错误
c.TplName = "set_error.html"
}else{
// 不然默认显示设置页面
c.Data["list"]=GetInfo()
c.TplName = "setting_list.html"
}
}
// 处理设置信息
func (c *MainController) Post() {
flash:=web.NewFlash() //初始化flash对象
setting:=Settings{} //实例化setting结构体
valid := Validation{} //实例化数据验证结构体
c.ParseForm(&setting) //解析表单
if b, err := valid.Valid(setting);err!=nil { //判断数据验证是否通过
flash.Error("Settings invalid!") //赋值错误信息
flash.Store(&c.Controller)
c.Redirect("/setting",302)
return
}else if b!=nil{
flash.Error("validation err!") //赋值错误信息
flash.Store(&c.Controller)
c.Redirect("/setting",302)
return
}
saveSetting(setting)
flash.Notice("Settings saved!") //赋值提示信息
flash.Store(&c.Controller)
c.Redirect("/setting",302)
}
三、错误处理
目的:在做 Web 开发的时候,经常需要页面跳转和错误处理,beego 这方面也进行了考虑,通过 Redirect 方法来进行跳转。
1、定义Err结构体,
package controller
import "cmdb/base/Controller/Base"
type ErrorController struct {
Base.MainController
}
//设置Error开头的方法
//Error404=>处理404错误的逻辑
func (c *ErrorController) Error404() {
c.TplName = "error/404.html"
}
2、注册Err结构体
beego.ErrorController(&controller.ErrorController{}) //注册错误结构体
3、加上相关条件然后使用Abort
func (c *HomeController) Index() {
if 1==1{ //条件可以丢
c.Abort("404")
}
c.TplName = "home/index.html"
}
四、XSRF
跨站伪造请求:防止别的页面直接进行post请求进行攻击修改信息,举例:转账例子(https://blog.csdn.net/weixin_38597669/article/details/90694407)
1、配置(添加配置后必须使用xsrf标签)
#设置跨站伪造请求的配置
EnableXSRF=true //开启XSRF防护
XSRFKey=61oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o //对XRSF配置Token
XSRFExpire=3600 //设置过期时间
2、自动生成xsrf标签并且使用模板技术调用
c.Data["xsrf_input"] = template.HTML(c.XSRFFormHTML())
{{ .xsrf_input }}
3、传递token,使用自己拼写的标签页面
c.Data["xsrf_token"] = c.XSRFToken()
<input type="hidden" name="_xsrf" value="{{ .xsrf_token }}"/>
五、日志
作用:记录登录状态、错误信息等等
package main
import (
"github.com/astaxie/beego"
)
func main() {
beego.SetLogger("file", `{"filename":"test.log"}`) //设置日志记录方式,记录在内存或者文件夹中
//上述初始化日志的储存路径,可以在main函数中进行初始化
beego.SetLevel(beego.LevelError) //设置日志记录级别 调试>提醒>错误
beego.Debug("我是调试日志")
beego.Informational("我是一个提醒日志")
beego.Error("我是一个错误日志")
}
六、Layout和LayoutSection
Layout类似于模板嵌套,可以定义在Parper中,类似于固定一部分在layout模板,然后向模板嵌套html
this.Layout = "admin/layout.html"
this.TplName = "admin/add.tpl"
//在layout中使用
{{.LayoutContent}}
beego 就会首先解析 TplName 指定的文件,获取内容赋值给 LayoutContent,然后最后渲染 layout.html 文件。
LayoutSection用途在于添加额外的css
定义模板
//html_head.tpl:
<style>
h1 {
color: red;
}
</style>
//scripts.tpl:
<script type="text/javascript">
$(document).ready(function() {
// bla bla bla
});
</script>
赋值
type BlogsController struct {
web.Controller
}
func (this *BlogsController) Get() {
this.Layout = "layout_blog.tpl"
this.TplName = "blogs/index.tpl"
this.LayoutSections = make(map[string]string)
this.LayoutSections["HtmlHead"] = "blogs/html_head.tpl"
this.LayoutSections["Scripts"] = "blogs/scripts.tpl"
this.LayoutSections["Sidebar"] = ""
}
其次在模板中调用
<!DOCTYPE html>
<html>
<head>
<title>Lin Li</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap-theme.min.css">
{{.HtmlHead}}
</head>
<body>
<div class="container">
{{.LayoutContent}}
</div>
<div>
{{.SideBar}}
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
{{.Scripts}}
</body>
</html>
七、Cache缓存
目的:一般设计的微服务接口若被频繁大量调用,会导致CPU冲高,服务挂死等问题。此时可设计缓存方案,降低服务挂死风险。
1、导入beego包,并且放在内存中
"github.com/astaxie/beego/cache"
bm, err := cache.NewCache("memory", `{"interval":60}`)
这里设置的是memory这个为放入内存中,重启后就不存在内存中的东西了
package main
import (
"fmt"
"github.com/astaxie/beego/cache"
"time"
)
func main() {
bm, err := cache.NewCache("memory", `{"interval":60}`)
if err != nil {
fmt.Println(err)
}
// 然后我们就可以使用bm增删改缓存
fmt.Println("设置缓存前的值", bm.Get("name"))
bm.Put("name", "test", 10*time.Second)
fmt.Println("设置缓存后的值", bm.Get("name"))
fmt.Println("缓存是否存在", bm.IsExist("name"))
bm.Delete("name")
fmt.Println("删除缓存的后值", bm.Get("name"))
fmt.Println("缓存是否存在", bm.IsExist("name"))
}
2、将内存持久化
package main
import (
"encoding/gob"
"fmt"
"github.com/astaxie/beego/cache"
"time"
)
type User struct {
Id int
Name string
}
func main() {
gob.Register(new(User)) //持久化结构体必须注册
bm, err := cache.NewCache("file", `{"CachePath":"cache","FileSuffix":".cache","EmbedExpiry":"60","DirectoryLevel":"3"}`)
if err != nil {
fmt.Println(err)
}
if bm.IsExist("user") {
fmt.Println(bm.Get("user"))
} else {
fmt.Println("设置user缓存")
user := &User{1, "tom"}
bm.Put("user", user, time.Minute)
}
}
八、部署
1、文件目录作用
2、部署拷贝
(1)windows上编译
因为编译的时候只会编译go代码,所以需要拷贝其他的非go代码
设置好之后就可以打包发给其他人,其他人只需要修改配置mysql的文件,或者可以直接将mysql的配置文件一下打包发给他
(2)linux上编译
GOARCH是指编译成64位的程序,当为32位的。。
可以设置GOOS环境为linux环境,就可以直接编译成linux程序 然后拷贝到虚拟机中,安装相关的msql数据库
然后运行(也可以使用进程监控来开始服务器)
九、HTTPS
前两个设置为true,后面的需要到阿里购买证书或者自己自签证书(下列网址有自签证书教学)
十、cobra
1、命令行参数实现cobra的参数传递
以前使用flag包,但是需要设置与docker命令相似
cmdb包下面的root命令
将web.go中的命令加入到rootCommond
main函数中调用excute
同理设置db下的Command命令
十一、用户权限
1、rbac垂直权限
2、根据属性进行水平权限
十二、过滤器
如果看完对自己有所帮助,请点赞支持,谢谢