[golang gin框架] 14.Gin 商城项目-RBAC管理

一.权限介绍

RBAC 是基于角色的权限访问控制(Role-Based Access Control)。在 RBAC 中,权限与角色相
关联,用户通过成为适当角色的成员而得到这些角色的权限

二.用户 RBAC 权限管理树形图

三.RBAC 实现流程

1、实现角色的增加修改删除

2、实现用户的增加修改删除,增加修改用户的时候需要选择角色

3、实现权限的增加修改删除 (页面菜单)

4、实现角色授权功能

5、判断当前登录的用户是否有访问菜单的权限

6、根据当前登录账户的角色信息动态显示左侧菜单

四.权限控制相关的数据库表

五. 角色的增、删、改、查

1.创建角色模型

在models目录下创建role.go角色模型
package models

//角色模型

type Role struct { // 结构体首字母大写, 和数据库表名对应, 默认访问数据表users, 可以设置访问数据表的方法
    Id  int
    Title string
    Description string
    Status int
    AddTime int
}

//配置数据库操作的表名称
func (Role) TableName() string {
    return "role"
}

2.创建角色控制器

在controllers/admin下创建RoleController.go角色控制器
package admin

import (
    "github.com/gin-gonic/gin"
    "goshop/models"
    "net/http"
    "strings"
)

type RoleController struct {
    BaseController
}

//角色列表
func (con RoleController) Index(c *gin.Context) {
    //定义一个角色切片
    roleList := []models.Role{}
    //获取角色
    models.DB.Find(&roleList)
    c.HTML(http.StatusOK, "admin/role/index.html", gin.H{
        "roleList": roleList,
    })
}

//新增角色
func (con RoleController) Add(c *gin.Context) {
    c.HTML(http.StatusOK, "admin/role/add.html", gin.H{})
}

//新增角色:提交
func (con RoleController) DoAdd(c *gin.Context) {
    //获取表单的提交数据
    //strings.Trim(str, cutset), 去除字符串两边的cutset字符
    title := strings.Trim(c.PostForm("title"), " ") // 去除字符串两边的空格
    description := strings.Trim(c.PostForm("description"), " ")

    //判断角色名称是否为空
    if title == "" {
        con.Error(c, "角色名称不能为空", "/admin/role/add")
        return
    }
    //给角色模型赋值,并保存数据到数据库
    role := models.Role{}
    role.Title = title
    role.Description = description
    role.Status = 1
    role.AddTime = int(models.GetUnix())
    err := models.DB.Create(&role).Error
    if err != nil {
        con.Error(c, "增加角色失败,请重试", "/admin/role/add")
        return
    }
    con.Success(c, "增加角色成功", "/admin/role")
}

//编辑角色
func (con RoleController) Edit(c *gin.Context) {
    //获取角色id
    id, err := models.Int(c.Query("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/role")
    } else {
        role := models.Role{Id: id}
        models.DB.Find(&role)
        c.HTML(http.StatusOK, "admin/role/edit.html", gin.H{
            "role": role,
        })
    }
}

//编辑角色:提交
func (con RoleController) DoEdit(c *gin.Context) {
    //获取提交的表单数据
    id, err := models.Int(c.PostForm("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/role")
        return
    }
    //获取表单的提交数据
    //strings.Trim(str, cutset), 去除字符串两边的cutset字符
    title := strings.Trim(c.PostForm("title"), " ") // 去除字符串两边的空格
    description := strings.Trim(c.PostForm("description"), " ")
    //判断角色名称是否为空
    if title == "" {
        con.Error(c, "角色名称不能为空", "/admin/role/add")
        return
    }
    //查询角色是否存在
    role := models.Role{Id: id}
    models.DB.Find(&role)

    //修改角色属性
    role.Title = title
    role.Description = description
    err = models.DB.Save(&role).Error
    if err != nil {
        con.Error(c, "修改数据失败", "/admin/role/edit?id="+models.String(id))
        return
    }
    con.Success(c, "修改数据成功", "/admin/role")
}

//删除角色
func (con RoleController) Delete(c *gin.Context) {
    //获取提交的表单数据
    id, err := models.Int(c.Query("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/role")
        return
    }

    //查询角色是否存在
    role := models.Role{Id: id}
    err = models.DB.Delete(&role).Error
    if err != nil {
        con.Error(c, "删除数据失败", "/admin/role")
        return
    }
    con.Success(c, "删除数据成功", "/admin/role")
}

3.创建角色html以及js

在templates/admin/role下创建角色相关html

index.html

{{ define "admin/role/index.html" }}
    {{ template "admin/public/page_header.html" .}}
    <!--
        列表展示
    -->
    <div class="table-responsive">
        <table class="table table-bordered">
            <thead>
            <tr class="th">
                <th>编号</th>
                <th>角色名称</th>
                <th>角色说明</th>
                <th>角色状态</th>
                <th class="text-center">操作</th>
            </tr>
            </thead>
            <tbody>
            {{ range $key,$value := .roleList}}
                <tr>
                    <td>{{$value.Id}}</td>
                    <td>{{$value.Title}}</td>
                    <td>{{$value.Description}}</td>
                    <td align="center">
                        {{if eq $value.Status 1}}
                            <img class="chStatus" data-id="{{$value.Id}}" data-table="role" data-field="status" src="/static/admin/images/yes.gif" />
                        {{else}}
                            <img class="chStatus" data-id="{{$value.Id}}" data-table="role" data-field="status" src="/static/admin/images/no.gif" />
                        {{end}}
                    </td>
                    <td class="text-center">
                        <a href="/admin/role/edit?id={{$value.Id}}">修改</a>
                        <a class="delete" href="/admin/role/delete?id={{$value.Id}}">删除</a>
                    </td>
                </tr>
            {{end}}
            </tbody>
        </table>
    </div>

    </body>
    </html>
{{ end }}

add.html

{{ define "admin/role/add.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="panel panel-default">
    <div class="panel-heading">
        添加角色
    </div>
    <div class="panel-body">
        <div class="table-responsive input-form">
            <form action="/admin/role/doAdd" method="post">
                <ul>
                    <li>  角色名称: <input type="text" name="title"/></li>
                    <li>
                        角色描述:
                        <textarea name="description" id="" cols="60" rows="8"></textarea>
                    </li>
                    <li>
                        <br/>
                        <button type="submit" class="btn btn-default">提交</button>
                    </li>
                </ul>
            </form>
        </div>
    </div>
</div>
</body>
</html>
{{ end }}

edit.html

{{ define "admin/role/edit.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="panel panel-default">
    <div class="panel-heading">
        编辑角色
    </div>
    <div class="panel-body">
        <div class="table-responsive input-form">
            <form action="/admin/role/doEdit" method="post">
                <input type="hidden" name="id" value="{{.role.Id}}">
                <ul>
                    <li>角色名称: <input type="text" name="title" value="{{.role.Title}}"/></li>
                    <li>
                        角色描述:
                        <textarea name="description" id="" cols="60" rows="8" >{{.role.Description}}</textarea>
                    </li>
                    <li>
                        <br/>
                        <button type="submit" class="btn btn-default">提交</button>
                    </li>
                </ul>
            </form>
        </div>
    </div>
</div>
</body>
</html>
{{ end }}

删除角色js提示

在static/admin/js/base.js下增加删除提示
$(function () {
    baseApp.init();
    //当窗口重置时,重新计算窗口高度
    $(window).resize(function () {
        baseApp.resizeIframe();
    })
})

var baseApp = {
    init: function () {
        this.initAside()
        this.confirmDelete()
        this.resizeIframe()
    },
    initAside: function () { //左侧菜单栏隐藏显示子栏
        $(".aside h4").click(function () {
            $(this).sibling("ul").slideToggle();
        })
    },
    resizeIframe: function() {  // 设置iframe高度
        $("rightMain").height($(window).height()-80)
    },
    confirmDelete: function () { // 删除提示
        $(".delete").click(function () {
            var flag = confirm("确定要删除该项?")
            return flag
        })
    }
}

4.配置路由

在routes/adminRouters.go下配置角色路由
package routers

import (
    "goshop/controllers/admin"
    "goshop/middlewares"
    "github.com/gin-gonic/gin"
)

//设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
    //路由分组: 配置全局中间件:middlewares.InitMiddleware
    adminRouters := r.Group("/admin", middlewares.InitAdminAuthMiddleware)
    {
        //后台首页
        adminRouters.GET("/", admin.MainController{}.Index)
        adminRouters.GET("/welcome", admin.MainController{}.Welcome)

        //登录页面
        adminRouters.GET("/login", admin.LoginController{}.Index) // 实例化控制器,并访问其中方法
        adminRouters.POST("/doLogin", admin.LoginController{}.DoIndex)
        adminRouters.GET("/loginOut", admin.LoginController{}.LoginOut)

        //验证码
        adminRouters.GET("/captcha", admin.LoginController{}.Captcha)

        //角色路由
        adminRouters.GET("/role", admin.RoleController{}.Index)
        adminRouters.GET("/role/add", admin.RoleController{}.Add)
        adminRouters.POST("/role/doAdd", admin.RoleController{}.DoAdd)
        adminRouters.GET("/role/edit", admin.RoleController{}.Edit)
        adminRouters.POST("/role/doEdit", admin.RoleController{}.DoEdit)
        adminRouters.GET("/role/delete", admin.RoleController{}.Delete)
    }
}

5.界面展示如下

列表

增加

编辑

删除

六. 管理员的增、删、改、查以及管理员和角色关联

  1. 创建管理员模型

在models目录下创建manager.go角色模型
package models

//管理员表

type Manager struct { // 结构体首字母大写, 和数据库表名对应, 默认访问数据表users, 可以设置访问数据表的方法
    Id  int
    Username string
    Password string
    Mobile string
    Email string
    Status int
    RoleId int
    AddTime int
    IsSuper int
    Role Role `gorm:"foreignKey:RoleId;references:Id"`  // 配置关联关系
}

//配置数据库操作的表名称
func (Manager) TableName() string {
    return "manager"
}
  1. 创建管理员控制器

在controllers/admin下创建anagerController.go角色控制器
package admin

import (
    "github.com/gin-gonic/gin"
    "goshop/models"
    "net/http"
    "strings"
)

type ManagerController struct {
    BaseController
}

func (con ManagerController) Index(c *gin.Context) {
    //获取管理员列表,以及关联对应的角色
    managerList := []models.Manager{}
    models.DB.Preload("Role").Find(&managerList)

    c.HTML(http.StatusOK, "admin/manager/index.html", gin.H{
        "managerList": managerList,
    })
}

//添加管理员
func (con ManagerController) Add(c *gin.Context) {
    //获取角色
    roleList := []models.Role{}
    models.DB.Find(&roleList)
    c.HTML(http.StatusOK, "admin/manager/add.html", gin.H{
        "roleList": roleList,
    })
}

//添加管理员:提交
func (con ManagerController) DoAdd(c *gin.Context) {
    //获取角色id,判断是否合法
    roleId, err := models.Int(c.PostForm("role_id"))
    if err != nil {
        con.Error(c, "角色不合法", "/admin/manager/add")
        return
    }
    //获取提交的表单信息
    username := strings.Trim(c.PostForm("username"), " ")
    password := strings.Trim(c.PostForm("password"), " ")
    email := strings.Trim(c.PostForm("email"), " ")
    mobile := strings.Trim(c.PostForm("mobile"), " ")

    //判断用户名和密码是否符合要求
    if len(username) < 2 || len(password) < 6 {
        con.Error(c, "用户名或密码长度不合法", "/admin/manager/add")
        return
    }

    //判断管理员是否存在
    managerList := []models.Manager{}
    models.DB.Where("username = ?", username).Find(&managerList)
    if len(managerList) > 0 {
        con.Error(c, "管理员已存在", "/admin/manager/add")
        return
    }

    //实例化Manager,执行增加管理员
    manager := models.Manager{
        Username: username,
        Password: models.Md5(password),
        Email:    email,
        Mobile:   mobile,
        AddTime:  int(models.GetUnix()),
        RoleId:   roleId,
        Status:   1,
    }
    err = models.DB.Create(&manager).Error
    if err != nil {
        con.Error(c, "添加管理员失败", "/admin/manager/add")
        return
    }
    con.Success(c, "添加管理员成功", "/admin/manager")
}

//编辑管理员
func (con ManagerController) Edit(c *gin.Context) {
    //获取管理员
    id, err := models.Int(c.Query("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/manager")
        return
    }
    manager := models.Manager{Id: id}
    models.DB.Find(&manager)

    if manager.Username == "" {
        con.Error(c, "管理员#" + models.String(id) + "不存在", "/admin/manager")
        return
    }
    //获取所有角色
    roleList := []models.Role{}
    models.DB.Find(&roleList)

    c.HTML(http.StatusOK, "admin/manager/edit.html", gin.H{
        "manager":  manager,
        "roleList": roleList,
    })
}

//编辑管理员提交
func (con ManagerController) DoEdit(c *gin.Context) {
    //获取管理员id,并判断
    id, err := models.Int(c.PostForm("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/manager")
        return
    }
    //获取角色id,并判断
    roleId, err2 := models.Int(c.PostForm("role_id"))
    if err2 != nil {
        con.Error(c, "传入数据错误", "/admin/manager")
        return
    }

    //获取提交的表单信息
    username := strings.Trim(c.PostForm("username"), " ")
    password := strings.Trim(c.PostForm("password"), " ")
    email := strings.Trim(c.PostForm("email"), " ")
    mobile := strings.Trim(c.PostForm("mobile"), " ")
    //执行修改
    manager := models.Manager{Id: id}
    models.DB.Find(&manager)
    manager.Username = username
    manager.Email = email
    manager.RoleId = roleId
    manager.Mobile = mobile
    //判断密码, 为空 表示不修改密码
    if password != "" {
        //判断密码长度
        if len(password) < 6 {
            con.Error(c, "密码长度不合法", "/admin/manager/edit?id" + models.String(id))
            return
        }
        manager.Password = models.Md5(password)
    }
    //保存
    err = models.DB.Save(&manager).Error
    if err != nil {
        con.Error(c, "修改数据失败", "/admin/manager/edit?id="+models.String(id))
        return
    }
    con.Success(c, "修改数据成功", "/admin/manager")
}

//删除
func (con ManagerController) Delete(c *gin.Context) {
    //获取提交的表单数据
    id, err := models.Int(c.Query("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/manager")
        return
    }

    //查询管理员是否存在
    manager := models.Manager{Id: id}
    err = models.DB.Delete(&manager).Error
    if err != nil {
        con.Error(c, "删除数据失败", "/admin/manager")
        return
    }
    con.Success(c, "删除数据成功", "/admin/manager")
}
  1. 创建管理员html

在templates/admin/manager下创建相关html

index.html

{{ define "admin/manager/index.html" }}
    {{ template "admin/public/page_header.html" .}}
    <!--
        列表展示
    -->
    <div class="table-responsive">
        <table class="table table-bordered">
            <thead>
            <tr class="th">
                <th>管理员名称</th>
                <th>管理员电话</th>
                <th>管理员邮箱</th>
                <th>管理员角色</th>
                <th>创建时间</th>
                <th class="text-center">操作</th>
            </tr>
            </thead>
            <tbody>
            {{range $key,$value := .managerList}}
                <tr>
                    <td>{{$value.Username}}</td>
                    <td>{{$value.Mobile}}</td>
                    <td>{{$value.Email}}</td>
                    <td>{{$value.Role.Title}}</td>
                    <td>{{UnixToTime $value.AddTime}}</td>

                    <td class="text-center">
                        <a href="/admin/manager/edit?id={{$value.Id}}">修改</a>
                        <a class="delete" href="/admin/manager/delete?id={{$value.Id}}">删除</a>
                    </td>
                </tr>
            {{end}}
            </tbody>
        </table>
    </body>
    </html>
{{end}}

add.html

{{ define "admin/manager/add.html" }}
{{ template "admin/public/page_header.html" .}}
<div class="panel panel-default">
    <div class="panel-heading">
        增加管理员
    </div>
    <div class="panel-body">
        <div class="table-responsive input-form">
            <form action="/admin/manager/doAdd" method="post">
                <ul>
                    <li> 管理员名称: <input type="text" name="username" /></li>
                    <li> 管理员密码: <input type="password" name="password" /></li>
                    <li> 管理员电话: <input type="text" name="mobile" /></li>
                    <li> 管理员邮箱: <input type="text" name="email" /></li>
                    <li> 管理员角色:
                        <select name="role_id" id="role_id">    
                            {{range $key,$value := .roleList}}                           
                                <option value="{{$value.Id}}">{{$value.Title}}</option>   
                            {{end}}
                        </select>
    
                    </li>
                    <li>
                        <br/>
                        <button type="submit" class="btn btn-default">提交</button>
                    </li>
    
                </ul>
            </form>
        </div>
    </div>
</div>
</body>
</html>
{{end}}

edit.html

{{ define "admin/manager/edit.html" }}
    {{ template "admin/public/page_header.html" .}}
    <div class="panel panel-default">
        <div class="panel-heading">
            修改管理员
        </div>
        <div class="panel-body">
            <div class="table-responsive input-form">
                <form action="/admin/manager/doEdit" method="post">
                    <input type="hidden" name="id" value="{{.manager.Id}}">
                    <ul>
                        <li> 管理员名称: <input type="text" name="username" readonly value="{{.manager.Username}}"/></li>
                        <li> 管理员密码: <input type="password" name="password" placeholder="为空表示不修改密码"/></li>
                        <li> 管理员电话: <input type="text" name="mobile" value="{{.manager.Mobile}}"/></li>
                        <li> 管理员邮箱: <input type="text" name="email" value="{{.manager.Email}}"/></li>
                        <li> 管理员角色:
                            <select name="role_id" id="role_id">
                                {{$roleId := .manager.RoleId}}
                                {{range $key,$value := .roleList}}
                                    {{if eq $value.Id $roleId }}
                                        <option selected value="{{$value.Id}}">{{$value.Title}}</option>
                                    {{else}}
                                        <option value="{{$value.Id}}">{{$value.Title}}</option>
                                    {{end}}
                                {{end}}
                            </select>
                        </li>
                        <li>
                            <br/>
                            <button type="submit" class="btn btn-default">提交</button>
                        </li>

                    </ul>
                </form>
            </div>
        </div>
    </div>
    </body>
    </html>
{{end}}

4.配置路由

在routes/adminRouters.go下配置角色路由
package routers

import (
    "goshop/controllers/admin"
    "goshop/middlewares"
    "github.com/gin-gonic/gin"
)

//设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
    //路由分组: 配置全局中间件:middlewares.InitMiddleware
    adminRouters := r.Group("/admin", middlewares.InitAdminAuthMiddleware)
    {
        //后台首页
        adminRouters.GET("/", admin.MainController{}.Index)
        adminRouters.GET("/welcome", admin.MainController{}.Welcome)

        //登录页面
        adminRouters.GET("/login", admin.LoginController{}.Index) // 实例化控制器,并访问其中方法
        adminRouters.POST("/doLogin", admin.LoginController{}.DoIndex)
        adminRouters.GET("/loginOut", admin.LoginController{}.LoginOut)

        //验证码
        adminRouters.GET("/captcha", admin.LoginController{}.Captcha)

        //管理员路由
        adminRouters.GET("/manager", admin.ManagerController{}.Index)
        adminRouters.GET("/manager/add", admin.ManagerController{}.Add)
        adminRouters.POST("/manager/doAdd", admin.ManagerController{}.DoAdd)
        adminRouters.GET("/manager/edit", admin.ManagerController{}.Edit)
        adminRouters.POST("/manager/doEdit", admin.ManagerController{}.DoEdit)
        adminRouters.GET("/manager/delete", admin.ManagerController{}.Delete)


        //角色路由
        adminRouters.GET("/role", admin.RoleController{}.Index)
        adminRouters.GET("/role/add", admin.RoleController{}.Add)
        adminRouters.POST("/role/doAdd", admin.RoleController{}.DoAdd)
        adminRouters.GET("/role/edit", admin.RoleController{}.Edit)
        adminRouters.POST("/role/doEdit", admin.RoleController{}.DoEdit)  
    }
}

5.界面展示如下

列表

增加

编辑

删除

七. 权限的增、删、改、查以及权限的自关联

  1. 创建权限模型

在models目录下创建.go角色模型
package models

//权限模型

type Access struct {
    Id          int
    ModuleName  string //模块名称
    ActionName  string //操作名称
    Type        int    //节点类型 :  1、表示模块    2、表示菜单     3、操作
    Url         string //路由跳转地址
    ModuleId    int    //此module_id和当前模型的id关联       module_id= 0 表示模块
    Sort        int
    Description string
    Status      int
    AddTime     int
    AccessItem  []Access `gorm:"foreignKey:ModuleId;references:Id"`  // 表的自关联,获取该数据的子分类

    Checked     bool     `gorm:"-"` // 用户是否有该权, 忽略本字段,给struct加一个自定义属性,和数据库没有关系
}

func (Access) TableName() string {
    return "access"
}
  1. 创建权限控制器

在controllers/admin下创建AccessController.go角色控制器
package admin

import (
    "github.com/gin-gonic/gin"
    "goshop/models"
    "net/http"
    "strings"
)

type AccessController struct {
    BaseController
}

func (con AccessController) Index(c *gin.Context) {
    //获取权限列表
    accessList := []models.Access{}
    models.DB.Where("module_id = ?", 0).Preload("AccessItem").Find(&accessList)
    c.HTML(http.StatusOK, "admin/access/index.html", gin.H{
        "accessList": accessList,
    })
}

func (con AccessController) Add(c *gin.Context) {
    //获取顶级模块
    accessList := []models.Access{}
    models.DB.Where("module_id = ?", 0).Find(&accessList)

    c.HTML(http.StatusOK, "admin/access/add.html", gin.H{
        "accessList": accessList,
    })
}

func (con AccessController) DoAdd(c *gin.Context) {
    //获取表单数据
    moduleName := strings.Trim(c.PostForm("module_name"), " ")
    actionName := strings.Trim(c.PostForm("action_name"), " ")
    accessType, err1 := models.Int(c.PostForm("type"))
    url := c.PostForm("url")
    moduleId, err2 := models.Int(c.PostForm("module_id"))
    sort, err3 := models.Int(c.PostForm("sort"))
    status, err4 := models.Int(c.PostForm("status"))
    description := strings.Trim(c.PostForm("description"), " ")
    //判断err
    if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
        con.Error(c, "传入参数错误", "/admin/access/add")
        return
    }
    //判断moduleName
    if moduleName == "" {
        con.Error(c, "模块名称不能为空", "/admin/access/add")
        return
    }
    //实例化access
    access := models.Access{
        ModuleName:  moduleName,
        ActionName:  actionName,
        Type:        accessType,
        Url:         url,
        ModuleId:    moduleId,
        Sort:        sort,
        Status:      status,
        Description: description,
    }
    err5 := models.DB.Create(&access).Error
    if err5 != nil {
        con.Error(c, "添加权限失败", "/admin/access/add")
        return
    }
    con.Success(c, "添加权限成功", "/admin/access")
}

//编辑
func (con AccessController) Edit(c *gin.Context) {
    //获取id
    id, err := models.Int(c.Query("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/access")
        return
    }
    access := models.Access{Id: id}
    models.DB.Find(&access)

    //获取顶级模块
    accessList := []models.Access{}
    models.DB.Where("module_id = ?", 0).Find(&accessList)

    c.HTML(http.StatusOK, "admin/access/edit.html", gin.H{
        "access":     access,
        "accessList": accessList,
    })
}

//编辑:提交
func (con AccessController) DoEdit(c *gin.Context) {
    //获取提交的表单数据
    id, err := models.Int(c.PostForm("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/access/edit?id"+models.String(id))
        return
    }
    //获取表单数据
    moduleName := strings.Trim(c.PostForm("module_name"), " ")
    actionName := strings.Trim(c.PostForm("action_name"), " ")
    accessType, err1 := models.Int(c.PostForm("type"))
    url := c.PostForm("url")
    moduleId, err2 := models.Int(c.PostForm("module_id"))
    sort, err3 := models.Int(c.PostForm("sort"))
    status, err4 := models.Int(c.PostForm("status"))
    description := strings.Trim(c.PostForm("description"), " ")
    //判断err
    if err1 != nil || err2 != nil || err3 != nil || err4 != nil {
        con.Error(c, "传入数据错误", "/admin/access/edit?id"+models.String(id))
        return
    }
    //判断moduleName
    if moduleName == "" {
        con.Error(c, "模块名称不能为空", "/admin/access/edit?id"+models.String(id))
        return
    }

    //获取要修改的数据
    access := models.Access{Id: id}
    models.DB.Find(&access)
    access.ModuleName = moduleName
    access.ActionName = actionName
    access.Type = accessType
    access.Url = url
    access.ModuleId = moduleId
    access.Sort = sort
    access.Status = status
    access.Description = description
    //保存
    err5 := models.DB.Save(&access).Error
    if err5 != nil {
        con.Error(c, "编辑权限失败", "/admin/access/edit?id"+models.String(id))
        return
    }
    con.Success(c, "编辑权限成功", "/admin/access")
}

//删除
func (con AccessController) Delete(c *gin.Context) {
    //获取提交的表单数据
    id, err := models.Int(c.Query("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/access")
        return
    }

    //获取要删除的数据
    access := models.Access{Id: id}
    models.DB.Find(&access)
    if access.ModuleId == 0 { // 顶级模块
        accessList := []models.Access{}
        models.DB.Where("module_id = ? ", access.Id).Find(&accessList)
        if len(accessList) > 0 {
            con.Error(c, "当前模块下子菜单,请先删除子菜单后再来删除这个数据", "/admin/access")
            return
        }
    }
    // 操作 或者 菜单, 或者顶级模块下面没有子菜单, 可以直接删除
    err = models.DB.Delete(&access).Error
    if err != nil {
        con.Error(c, "删除数据失败", "/admin/access")
        return
    }
    con.Success(c, "删除数据成功", "/admin/access")
}
  1. 创建权限html

在templates/admin/access下创建权限相关html

index.html


{{ define "admin/access/index.html" }}
{{ template "admin/public/page_header.html" .}}
               
    <!--
        列表展示
    -->
    <div class="table-responsive">
        <table class="table table-bordered">
            <thead>
                <tr>
                    <th>模块名称</th>
                    <th>节点类型</th>
                    <th>操作名称</th>
                    <th>操作地址</th>
                    <th>排序</th>
                    <th>描述</th>

                    <th class="text-center">操作</th>
                </tr>
            </thead>
            <tbody>

             {{range $key,$value := .accessList}}   
                <tr>
                    <td>{{$value.ModuleName}}</td>               
                    <td>
                        {{if eq $value.Type 1}}
                        模块
                        {{else if eq $value.Type 2}}
                        菜单
                        {{else}}
                        操作
                        {{end}}

                    </td>
                    <td>{{$value.ActionName}}</td>        
                    <td>{{$value.Url}}</td>    
                    <td>
                        <span class="chSpanNum"  data-id="{{$value.Id}}" data-table="access" data-field="sort">{{$value.Sort}}</span>
                    </td>
                    <td>{{$value.Description}}</td>    
                    <td class="text-center">
                        <a href="/admin/access/edit?id={{$value.Id}}">修改</a>
                        <a class="delete" href="/admin/access/delete?id={{$value.Id}}">删除</a>
                    </td>
                </tr>            
                
                    {{range $k,$v := $value.AccessItem}}
                    <tr>
                        <td> --{{$v.ModuleName}}</td>               
                        <td>

                            {{if eq $v.Type 1}}
                            模块
                            {{else if eq $v.Type 2}}
                            菜单
                            {{else}}
                            操作
                            {{end}}
                        </td>
                        <td>{{$v.ActionName}}</td>        
                        <td>{{$v.Url}}</td>    
                        <td>
                            <span class="chSpanNum"  data-id="{{$v.Id}}" data-table="access" data-field="sort">{{$v.Sort}}</span>
                        </td>
                        <td>{{$v.Description}}</td>    
                        <td class="text-center">
                            <a href="/admin/access/edit?id={{$v.Id}}">修改</a>
                            <a class="delete" href="/admin/access/delete?id={{$v.Id}}">删除</a>
                        </td>
                    </tr>  
                    {{end}}   
                {{end}}   
            </tbody>
        </table>
    </div>
</body>
</html>
{{end}}

add.html

{{ define "admin/access/add.html" }}
{{ template "admin/public/page_header.html" .}}

<div class="panel panel-default">
    <div class="panel-heading">
      增加权限
    </div>
    <div class="panel-body">
        <div class="table-responsive input-form">
            <form action="/admin/access/doAdd" method="post">
                <ul>

                    <li> 模块名称: <input type="text" name="module_name" /></li>
                    <li>
                        节点类型:                        
                        <select name="type" id="type">
                            <option value="1">模块</option>
                            <option value="2">菜单</option>
                            <option value="3">操作</option>
                        </select>
                    </li>

                    <li> 操作名称: <input type="text" name="action_name" /></li>

                    <li> 操作地址: <input type="text" name="url" /></li>

                    <li> 所属模块:
                        <select name="module_id" id="module_id">
                            <option value="0">---顶级模块--</option>  
                            {{range $key,$value := .accessList}}
                                <option value="{{$value.Id}}">{{$value.ModuleName}}</option>  
                            {{end}}
                         </select>
                    </li>

                    <li>  排  序: <input type="text" name="sort" value="100"/></li>

                    <li>   描  述 :    

                        <textarea name="description" id="description" cols="60" rows="5"></textarea>
                    </li>


                    <li>  状  态:
                        <input type="radio" name="status" checked value="1" id="a"/> <label for="a">显示</label>  
                        
                        <input type="radio" name="status" value="0" id="b"/><label for="b">隐藏</label>  
                    </li>
                   
                    <li>
                        <br/>
                        <button type="submit" class="btn btn-default">提交</button>
                    </li>

                </ul>
            </form>
        </div>
    </div>
</div>
</body>
</html>
{{end}}

edit.html

{{ define "admin/access/edit.html" }}
{{ template "admin/public/page_header.html" .}}

<div class="panel panel-default">
    <div class="panel-heading">
      修改权限
    </div>
    <div class="panel-body">
        <div class="table-responsive input-form">
            <form action="/admin/access/doEdit" method="post">
                <input type="hidden" name="id" value="{{.access.Id}}">
                <ul>
                    <li> 模块名称: <input type="text" name="module_name" value="{{.access.ModuleName}}" /></li>
                    <li>
                        节点类型:                        
                        <select name="type" id="type">
                            <option {{if eq .access.Type 1}} selected {{end}} value="1">模块</option>
                            <option {{if eq .access.Type 2}} selected {{end}} value="2">菜单</option>
                            <option {{if eq .access.Type 3}} selected {{end}} value="3">操作</option>
                        </select>
                    </li>

                    <li> 操作名称: <input type="text" name="action_name" value="{{.access.ActionName}}" /></li>

                    <li> 操作地址: <input type="text" name="url"  value="{{.access.Url}}" /></li>

                    <li> 所属模块:
                        <select name="module_id" id="module_id">
                            <option value="0">---顶级模块--</option>
                            {{$moduleId := .access.ModuleId}}
                            {{range $key,$value := .accessList}}
                                <option {{if eq $value.Id $moduleId}} selected {{end}} value="{{$value.Id}}">{{$value.ModuleName}}</option>
                            {{end}}
                         </select>
                    </li>

                    <li>  排  序: <input type="text" name="sort" value="{{.access.Sort}}" /></li>

                    <li>   描  述 :    

                        <textarea name="description" id="description" cols="60" rows="5">{{.access.Description}}</textarea>
                    </li>


                    <li>  状  态:
                        <input type="radio" name="status"  {{if eq .access.Status 1}} checked {{end}}  value="1" id="a"/> <label for="a">显示</label>
                        
                        <input type="radio" name="status"  {{if eq .access.Status 0}} checked {{end}} value="0" id="b"/><label for="b">隐藏</label>  
                    </li>
                   
                    <li>
                        <br/>
                        <button type="submit" class="btn btn-default">提交</button>
                    </li>

                </ul>
            </form>
        </div>
    </div>
</div>
</body>
</html>
{{end}}
  1. 配置路由

在routes/adminRouters.go下配置权限路由
package routers

import (
    "goshop/controllers/admin"
    "goshop/middlewares"
    "github.com/gin-gonic/gin"
)

//设置admin后台路由
func AdminRoutersInit(r *gin.Engine) {
    //路由分组: 配置全局中间件:middlewares.InitMiddleware
    adminRouters := r.Group("/admin", middlewares.InitAdminAuthMiddleware)
    {
        //后台首页
        adminRouters.GET("/", admin.MainController{}.Index)
        adminRouters.GET("/welcome", admin.MainController{}.Welcome)

        //登录页面
        adminRouters.GET("/login", admin.LoginController{}.Index) // 实例化控制器,并访问其中方法
        adminRouters.POST("/doLogin", admin.LoginController{}.DoIndex)
        adminRouters.GET("/loginOut", admin.LoginController{}.LoginOut)

        //验证码
        adminRouters.GET("/captcha", admin.LoginController{}.Captcha)

        //管理员路由
        adminRouters.GET("/manager", admin.ManagerController{}.Index)
        adminRouters.GET("/manager/add", admin.ManagerController{}.Add)
        adminRouters.POST("/manager/doAdd", admin.ManagerController{}.DoAdd)
        adminRouters.GET("/manager/edit", admin.ManagerController{}.Edit)
        adminRouters.POST("/manager/doEdit", admin.ManagerController{}.DoEdit)
        adminRouters.GET("/manager/delete", admin.ManagerController{}.Delete)

        //角色路由
        adminRouters.GET("/role", admin.RoleController{}.Index)
        adminRouters.GET("/role/add", admin.RoleController{}.Add)
        adminRouters.POST("/role/doAdd", admin.RoleController{}.DoAdd)
        adminRouters.GET("/role/edit", admin.RoleController{}.Edit)
        adminRouters.POST("/role/doEdit", admin.RoleController{}.DoEdit)
        adminRouters.GET("/role/delete", admin.RoleController{}.Delete)

        //权限路由
        adminRouters.GET("/access", admin.AccessController{}.Index)
        adminRouters.GET("/access/add", admin.AccessController{}.Add)
        adminRouters.POST("/access/doAdd", admin.AccessController{}.DoAdd)
        adminRouters.GET("/access/edit", admin.AccessController{}.Edit)
        adminRouters.POST("/access/doEdit", admin.AccessController{}.DoEdit)
        adminRouters.GET("/access/delete", admin.AccessController{}.Delete
    }
}
  1. 界面展示

列表

增加

编辑

删除

八.角色和权限关联,角色授权,已授权的权限选中

1.在角色列表中增加'授权'操作

在角色index.html中增加授权连接代码,代码如下:
 <td class="text-center">
     <a href="/admin/role/auth?id={{$value.Id}}">授权</a>
     <a href="/admin/role/edit?id={{$value.Id}}">修改</a>
     <a class="delete" href="/admin/role/delete?id={{$value.Id}}">删除</a>
</td>

2.授权操作,以及已授权的权限选中

在角色html模板文件下创建auth.html页面
{{ define "admin/role/auth.html" }}
    {{ template "admin/public/page_header.html" .}}
    <div class="panel panel-default">
        <div class="panel-heading">
            角色授权
        </div>
        <div class="panel-body">
            <form action="/admin/role/doAuth" method="post">
                <input type="hidden" name="role_id" value="{{.roleId}}">
                <table class="table table-bordered">
                    {{range $key, $value := .accessList}}
                        <tr>
                            <td align="right" style="background: #D8E2FA; padding-right: 10px; width: 150px;">
                                <label>
                                    <input type="checkbox" {{if eq $value.Checked true}} checked {{end}}class="module_cbo" value="{{$value.Id}}"
                                           name="access_node[]">&nbsp;&nbsp;
                                    {{$value.ModuleName}}
                                </label>
                            </td>
                            <td>
                                {{range $k,$v := $value.AccessItem}}
                                    &nbsp;&nbsp;
                                    <label>
                                        <input type="checkbox"  {{if eq $v.Checked true}} checked {{end}} class="action_cbo" value="{{$v.Id}}"
                                               name="access_node[]">
                                        &nbsp;&nbsp;{{$v.ActionName}} </label>&nbsp;&nbsp;
                                {{end}}
                            </td>
                        </tr>
                    {{end}}
                </table>
                <button type="submit" class="btn btn-primary">提交</button>
            </form>
        </div>
    </div>
    </body>
    </html>
{{ end }}

3.增加授权方法

在角色控制器中增加授权方法

//授权
func (con RoleController) Auth(c *gin.Context) {
    //获取id
    id, err := models.Int(c.Query("id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/role")
        return
    }
    role := models.Role{Id: id}
    models.DB.Find(&role)

    //获取所有权限列表
    accessList := []models.Access{}
    models.DB.Where("module_id = ?", 0).Preload("AccessItem").Find(&accessList)

    //获取当前角色拥有的权限,并把权限id放在一个map对象中
    roleAccess := []models.RoleAccess{}
    models.DB.Where("role_id = ?", id).Find(&roleAccess)
    roleAccessMap := make(map[int]int)
    for _, v := range roleAccess {
        roleAccessMap[v.AccessId] = v.AccessId
    }

    //循环遍历所有权限数据,判断当前权限的id是否在角色权限的map对象中,如果是的话给当前数据加入checked属性
    for i := 0; i < len(accessList); i++ { //循环权限列表
        if _, ok := roleAccessMap[accessList[i].Id]; ok { // 判断当前权限是否在角色权限的map对象中
            accessList[i].Checked = true
        }
        for j := 0; j < len(accessList[i].AccessItem); j++ { // 判断当前权限的子栏位是否在角色权限的map中
            if _, ok := roleAccessMap[accessList[i].AccessItem[j].Id]; ok { // 判断当前权限是否在角色权限的map对象中
                accessList[i].AccessItem[j].Checked = true
            }
        }
    }
    c.HTML(http.StatusOK, "admin/role/auth.html", gin.H{
        "roleId":     id,
        "accessList": accessList,
    })
}

//授权提交
func (con RoleController) DoAuth(c *gin.Context) {
    //获取提交的表单数据
    roleId, err := models.Int(c.PostForm("role_id"))
    if err != nil {
        con.Error(c, "传入数据错误", "/admin/role")
        return
    }
    //获取表单提交的权限id切片
    accessIds := c.PostFormArray("access_node[]")
    //先删除当前角色对应的权限
    roleAccess := models.RoleAccess{}
    models.DB.Where("role_id = ?", roleId).Delete(&roleAccess)

    //循环遍历accessIds,增加当前角色对应的权限
    for _, v := range accessIds {
        roleAccess.RoleId = roleId
        accessId, _ := models.Int(v)
        roleAccess.AccessId = accessId
        models.DB.Create(&roleAccess)
    }

    con.Success(c, "角色授权成功", "/admin/role")
}

4.配置路由

在routes/adminRouters.go下配置授权路由
adminRouters.GET("/role/auth", admin.RoleController{}.Auth)
adminRouters.POST("/role/doAuth", admin.RoleController{}.DoAuth)

九.用户权限判断

登录后显示用户名称、根据用户的权限动态显示左侧菜单
判断当前登录用户的权限 、没有权限访问则拒绝

1.后台首页MainControllers.go修改

package admin

// 进入后台系统首页

import (
    "encoding/json"
    "github.com/gin-contrib/sessions"
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
    "goshop/models"
    "net/http"
)

type MainController struct {
}

func (con MainController) Index(c *gin.Context) {
    //获取Session里面保存的用户信息
    session := sessions.Default(c)
    userinfo := session.Get("userinfo")
    //判断Session中的用户信息是否存在,如果不存在跳转到登录页面(注意需要判断) 如果存在继续向下执行
    //session.Get获取返回的结果是一个空接口类型,所以需要进行类型断言: 判断userinfo是不是一个string
    userinfoStr, ok := userinfo.(string)
    if ok { // 说明是一个string
        //1.获取用户信息
        var userinfoStruct []models.Manager
        //把获取到的用户信息转换结构体
        json.Unmarshal([]byte(userinfoStr), &userinfoStruct)

        //获取所有权限列表
        accessList := []models.Access{}
        models.DB.Where("module_id = ?", 0).Preload("AccessItem", func(db *gorm.DB) *gorm.DB {
            return db.Order("access.sort DESC")
        }).Order("sort DESC").Find(&accessList)

        //获取当前角色拥有的权限,并把权限id放在一个map对象中
        roleAccess := []models.RoleAccess{}
        models.DB.Where("role_id = ?", userinfoStruct[0].RoleId).Find(&roleAccess)
        roleAccessMap := make(map[int]int)
        for _, v := range roleAccess {
            roleAccessMap[v.AccessId] = v.AccessId
        }

        //循环遍历所有权限数据,判断当前权限的id是否在角色权限的map对象中,如果是的话给当前数据加入checked属性
        for i := 0; i < len(accessList); i++ { //循环权限列表
            if _, ok := roleAccessMap[accessList[i].Id]; ok { // 判断当前权限是否在角色权限的map对象中
                accessList[i].Checked = true
            }
            for j := 0; j < len(accessList[i].AccessItem); j++ { // 判断当前权限的子栏位是否在角色权限的map中
                if _, ok := roleAccessMap[accessList[i].AccessItem[j].Id]; ok { // 判断当前权限是否在角色权限的map对象中
                    accessList[i].AccessItem[j].Checked = true
                }
            }
        }

        c.HTML(http.StatusOK, "admin/main/index.html", gin.H{
            "username": userinfoStruct[0].Username,
            "isSuper": userinfoStruct[0].IsSuper,  // 是否超级管理员, 超级管理员显示全部
            "accessList": accessList,
        })
    } else {
        c.Redirect(http.StatusFound, "/admin/login")
    }
}

func (con MainController) Welcome(c *gin.Context) {
    c.HTML(http.StatusOK, "admin/main/welcome.html", gin.H{})
}

2.后台首页templates/main.index.html展示

{{ define "admin/main/index.html" }}
{{ template "admin/public/page_header.html" .}}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<!--The content below is only a placeholder and can be replaced.-->

<link rel="stylesheet" href="/static/admin/bootstrap/css/bootstrap.css">

<link rel="stylesheet" href="/static/admin/css/basic.css">
<script type="text/javascript" src="/static/admin/bootstrap/js/jquery-1.10.1.js"></script>

<script type="text/javascript" src="/static/admin/js/base.js"></script>

<nav class="navbar navbar-inverse" role="navigation">
    <div class="container-fluid">
        <div class="navbar-header">
            <img src="/static/admin/images/node.jpg" class="logo" />
        </div>
        <div class="collapse navbar-collapse" id="example-navbar-collapse">
            <ul class="nav navbar-nav navbar-right">
                <li><a>欢迎您,{{.username}}</a>
                </li>
                <li><a href="/admin/loginOut">安全退出</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

<div class="container-fluid">
    <div class="row">
        <div class="col-sm-2">
            {{ template "admin/public/page_aside.html" .}}
        </div>
        <div class="col-sm-10">
            <iframe width="100%" height="500px" name="rightMain" src="/admin/welcome"></iframe>
        </div>
    </div>
</div>
</body>
</html>
{{ end }}

3.admin/public/page_header.html

<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "admin/public/page_header.html" }}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <!--The content below is only a placeholder and can be replaced.-->

    <link rel="stylesheet" href="/static/admin/bootstrap/css/bootstrap.css">

    <link rel="stylesheet" href="/static/admin/css/basic.css">
    <script type="text/javascript" src="/static/admin/bootstrap/js/jquery-1.10.1.js"></script>
    <script type="text/javascript" src="/static/admin/bootstrap/js/bootstrap.js"></script>

    <script type="text/javascript" src="/static/admin/js/base.js"></script>
{{end}}

4.左侧菜单栏admin/public/page_aside.html

<!-- 相当于给模板定义一个名字, define end 必须成对出现 -->
{{ define "admin/public/page_aside.html" }}
    <ul class="aside">
        <!--  判断当前用户权限,并显示对应目录 -->
        {{$isSuper := .isSuper}}
        {{range $key, $value := .accessList}}
            <!-- 是否超级管理员, 超级管理员显示全部 -->
            {{if eq $isSuper 1}}
                <li>
                    <h4>{{$value.ModuleName}}</h4>
                    <ul>
                        {{range $k,$v := $value.AccessItem}}
                            <!-- 判断权限类型: 2 菜单, 3 操作; 当Type=2时,才会显示菜单-->
                            {{if eq $v.Type 2}}
                                <li class="list-group-item">
                                    <a href="/admin/{{$v.Url}}" target="rightMain">
                                        {{$v.ActionName}}
                                    </a>
                                </li>
                            {{end}}
                        {{end}}
                    </ul>
                </li>
            {{else}}
                <!-- 判断用户是否有该权限 -->
                {{if eq $value.Checked true}}
                    <li>
                        <h4>{{$value.ModuleName}}</h4>
                        <ul>
                            {{range $k,$v := $value.AccessItem}}
                                {{if eq $v.Checked true}}
                                    <!-- 判断权限类型: 2 菜单, 3 操作-->
                                    {{if eq $v.Type 2}}
                                        <li class="list-group-item">
                                            <a href="/admin/{{$v.Url}}" target="rightMain">
                                                {{$v.ActionName}}
                                            </a>
                                        </li>
                                    {{end}}
                                {{end}}
                            {{end}}
                        </ul>
                    </li>
                {{end}}
            {{end}}
        {{end}}
    </ul>
{{end}}

5.权限模型代码修改

package models

//权限模型

type Access struct {
    Id          int
    ModuleName  string //模块名称
    ActionName  string //操作名称
    Type        int    //节点类型 :  1、表示模块    2、表示菜单     3、操作
    Url         string //路由跳转地址
    ModuleId    int    //此module_id和当前模型的id关联       module_id= 0 表示模块
    Sort        int
    Description string
    Status      int
    AddTime     int
    AccessItem  []Access `gorm:"foreignKey:ModuleId;references:Id"`  // 表的自关联,获取该数据的子分类

    Checked     bool     `gorm:"-"` // 用户是否有该权, 忽略本字段,给struct加一个自定义属性,和数据库没有关系
}

func (Access) TableName() string {
    return "access"
}

6.中间件middlewares/adminAuth.go修改

package middlewares

//中间件: 作用: 在执行路由之前或者之后进行相关逻辑判断

import (
    "encoding/json"
    "fmt"
    "github.com/gin-contrib/sessions"
    "github.com/gin-gonic/gin"
    "gopkg.in/ini.v1"
    "goshop/models"
    "net/http"
    "os"
    "strings"
)

func InitAdminAuthMiddleware(c *gin.Context) {
    //权限判断: 没有登录的用户不能进入后台管理中心

    //1、获取Url访问的地址
    //当地址后面带参数时:,如: admin/captcha?t=0.8706946438889653,需要处理
    //strings.Split(c.Request.URL.String(), "?"): 把c.Request.URL.String()请求地址按照?分割成切片
    pathname := strings.Split(c.Request.URL.String(), "?")[0]

    //2、获取Session里面保存的用户信息
    session := sessions.Default(c)
    userinfo := session.Get("userinfo")
    //3、判断Session中的用户信息是否存在,如果不存在跳转到登录页面(注意需要判断) 如果存在继续向下执行
    //session.Get获取返回的结果是一个空接口类型,所以需要进行类型断言: 判断userinfo是不是一个string
    userinfoStr, ok := userinfo.(string)
    if ok { // 说明是一个string
        var userinfoStruct []models.Manager
        //把获取到的用户信息转换结构体
        err := json.Unmarshal([]byte(userinfoStr), &userinfoStruct)
        if err != nil || !(len(userinfoStruct) > 0 && userinfoStruct[0].Username != "") {
            if pathname != "/admin/login" && pathname != "/admin/dologin" && pathname != "/admin/captcha" {
                //跳转到登录页面
                c.Redirect(http.StatusFound, "/admin/login")
            }
        } else { //表示用户登录成功
            //获取当前访问的URL对应的权限id,判断权限id是否在角色对应的权限中
            // strings.Replace 字符串替换
            urlPath := strings.Replace(pathname, "/admin/", "", 1)
            //排除权限判断:不是超级管理员并且不在相关权限内
            if userinfoStruct[0].IsSuper == 0 && !excludeAuthPath("/" + urlPath){
                //判断用户权限:当前用户权限是否可以访问url地址
                //获取当前角色拥有的权限,并把权限id放在一个map对象中
                roleAccess := []models.RoleAccess{}
                models.DB.Where("role_id = ?", userinfoStruct[0].RoleId).Find(&roleAccess)
                roleAccessMap := make(map[int]int)
                for _, v := range roleAccess {
                    roleAccessMap[v.AccessId] = v.AccessId
                }
                //实例化access
                access := models.Access{}
                //查询权限id
                models.DB.Where("url = ? ", urlPath).Find(&access)
                //判断权限id是否在角色对应的权限中
                if _, ok := roleAccessMap[access.Id]; !ok {
                    c.String(http.StatusOK, "没有权限")
                    c.Abort() // 终止程序
                }
            }
        }
    } else {
        //4、如果Session不存在,判断当前访问的URl是否是login doLogin captcha,如果不是跳转到登录页面,如果是不行任何操作
        //说明用户没有登录
        //需要排除到不需要做权限判断的路由
        if pathname != "/admin/login" && pathname != "/admin/dologin" && pathname != "/admin/captcha" {
            //跳转到登录页面
            c.Redirect(http.StatusFound, "/admin/login")
        }
    }
}

//排除权限判断的方法
func excludeAuthPath(urlPath string) bool {
    //加载配置文件
    cfg, err := ini.Load("./conf/app.ini")
    if err != nil {
        fmt.Printf("Fail to read file: %v", err)
        os.Exit(1)
    }
    //获取需要排除的地址
    excludeAuthPath := cfg.Section("").Key("excludeAuthPath").String()
    //拆分字符串成为一个切片
    excludeAuthPathSlice := strings.Split(excludeAuthPath, ",")
    //判断传入的地址是否在排除地址内
    for _, v := range excludeAuthPathSlice {
        if v == urlPath {
            return true
        }
    }
    return false
}

[上一节][golang gin框架] 13.Gin 商城项目-配置公共基类实现公共的成功,失败提示页面 用户登录、退出登录、以及权限判断

[下一节][golang gin框架] 15.Gin 商城项目-封装上传图片方法,轮播图的增删改查以及异步修改状态,数量

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,我可以为您提供一些关于使用 Golang Gin 框架进行项目实战的建议。 首先,您需要安装 GolangGin 框架。安装过程可以参考官方文档进行操作。然后,您可以按照以下步骤进行项目实战: 1. 创建项目结构 在您的 GOPATH 目录下创建一个新的项目文件夹。通常情况下,您需要为项目创建以下子文件夹: ``` . ├── main.go ├── config │ ├── config.go │ └── ... ├── controller │ ├── home_controller.go │ └── ... ├── middleware │ ├── auth.go │ └── ... ├── model │ ├── user.go │ └── ... ├── router │ ├── router.go │ └── ... └── service ├── user_service.go └── ... ``` 2. 创建路由 在 router 文件夹中创建一个 router.go 文件,并编写以下代码: ```go package router import ( "github.com/gin-gonic/gin" "your-project/controller" "your-project/middleware" ) func SetupRouter() *gin.Engine { r := gin.Default() // 中间件 r.Use(middleware.AuthMiddleware()) // 路由 r.GET("/", controller.HomePageHandler) return r } ``` 在上面的代码中,我们使用了 gin 框架中的 gin.Default() 函数来创建一个默认的 gin.Engine 实例,并使用中间件来进行身份验证。然后我们定义了一个路由,将根路径映射到 HomePageHandler 方法。 3. 创建控制器 在 controller 文件夹中创建 home_controller.go 文件,并编写以下代码: ```go package controller import ( "github.com/gin-gonic/gin" "your-project/service" ) func HomePageHandler(c *gin.Context) { users := service.GetAllUsers() c.JSON(200, users) } ``` 在上面的代码中,我们定义了一个 HomePageHandler 方法,它接收一个 gin.Context 对象作为参数,并使用 service 层中的 GetAllUsers 函数获取所有用户的数据。然后我们使用 JSON 方法将数据以 JSON 格式返回给客户端。 4. 创建服务层 在 service 文件夹中创建 user_service.go 文件,并编写以下代码: ```go package service import "your-project/model" func GetAllUsers() []*model.User { // TODO: 查询数据库获取所有用户数据 return []*model.User{} } ``` 在上面的代码中,我们定义了一个 GetAllUsers 函数,它返回一个包含所有用户数据的切片。在实际项目中,我们需要查询数据库来获取这些数据。 5. 创建模型 在 model 文件夹中创建 user.go 文件,并编写以下代码: ```go package model type User struct { ID int `json:"id"` Name string `json:"name"` Age int `json:"age"` } ``` 在上面的代码中,我们定义了一个 User 结构体,它包含三个字段:ID、Name 和 Age。这些字段将用于存储每个用户的信息。 6. 创建配置文件 在 config 文件夹中创建 config.go 文件,并编写以下代码: ```go package config const ( DB_HOST = "localhost" DB_PORT = "3306" DB_USERNAME = "root" DB_PASSWORD = "password" DB_NAME = "your-database-name" ) ``` 在上面的代码中,我们定义了一些常量,用于存储数据库配置信息。这些常量将在连接数据库时使用。 7. 连接数据库 在 service 层中的 GetAllUsers 函数中,我们需要连接数据库来获取所有用户数据。可以使用以下代码来连接 MySQL 数据库: ```go package service import ( "database/sql" "fmt" "your-project/config" "your-project/model" ) func GetAllUsers() []*model.User { // 连接数据库 db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", config.DB_USERNAME, config.DB_PASSWORD, config.DB_HOST, config.DB_PORT, config.DB_NAME, )) if err != nil { panic(err) } defer db.Close() // 查询所有用户数据 rows, err := db.Query("SELECT * FROM users") if err != nil { panic(err) } // 解析查询结果 users := []*model.User{} for rows.Next() { user := &model.User{} err := rows.Scan(&user.ID, &user.Name, &user.Age) if err != nil { panic(err) } users = append(users, user) } return users } ``` 在上面的代码中,我们使用 sql.Open 函数来打开 MySQL 数据库连接。然后我们使用 db.Query 函数来查询所有用户数据,并使用 rows.Scan 函数将查询结果解析为 User 结构体的切片。 以上就是使用 Golang Gin 框架进行项目实战的流程。当然,在实际项目中,您需要根据自己的需求进行相应的修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值