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

项目配置基类

在面向对象设计中,被定义为包含所有实体共性的 class 类型,被称为“基类”
  1. BaseController.go

基础控制器
package admin

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

//基础控制器
type BaseController struct {

}

//公共成功函数
func (con BaseController) Success(c *gin.Context, message string, redirectUrl string) {
    c.HTML(http.StatusOK, "admin/public/success.html", gin.H{
        "message": message,
        "redirectUrl": redirectUrl,
    })
}

//公共失败函数
func (con BaseController) Error(c *gin.Context, message string, redirectUrl string) {
    c.HTML(http.StatusOK, "admin/public/error.html", gin.H{
        "message": message,
        "redirectUrl": redirectUrl,
    })
}

2.success.html

公共成功跳转页面
{{ define "admin/public/success.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta http-equiv="refresh" content="1;url={{ .redirectUrl }}">
    <title>提示信息</title>
    <link rel="stylesheet" href="/static/admin/bootstrap/css/bootstrap.css">
</head>
<body>
    <div class="container-fluid">
        <div class="container" style="width: 480px;margin-top:100px;">
            <div class="alert alert-success">
                <h2>操作成功: {{ .message }}</h2>
                <br />
                <p>如果您不做出选择,将在 1秒后跳转到上一个链接地址</p>
                <br />

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

3.error.html

公共失败跳转页面
{{ define "admin/public/error.html" }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta http-equiv="refresh" content="1;url={{ .redirectUrl }}">
    <title>提示信息</title>
    <link rel="stylesheet" href="/static/admin/bootstrap/css/bootstrap.css">
</head>
<body>
    <div class="container-fluid">
        <div class="container" style="width: 480px;margin-top:100px;">
            <div class="alert alert-dange">
                <h2>操作失败: {{ .message }}</h2>
                <br />
                <p>如果您不做出选择,将在 1秒后跳转到上一个链接地址</p>
                <br />

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

二、配置 session

1.安装 session 包

直接在项目main.go目录下运行命令: go get github.com/gin-contrib/sessions

2.基本的 session 用法

基于 cookie 的存储引擎

package main
import ( 
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/cookie"
    "github.com/gin-gonic/gin"
)

func main() { 
    初始化路由,会设置默认中间件:engine.Use(Logger(), Recovery()),可以使用gin.New()来设置路由
    r := gin.Default()
    
    // 创建基于 cookie 的存储引擎,secret11111 参数是用于加密的密钥
    store := cookie.NewStore([]byte("secret11111"))
    // 设置 session 中间件,参数 mysession,指的是 session 的名字,也是 cookie 的名字
    // store 是前面创建的存储引擎,我们可以替换成其他存储引擎
    r.Use(sessions.Sessions("mysession", store))
    
    r.GET("/", func(c *gin.Context) {
        //初始化 session 对象
        session := sessions.Default(c)
        //设置过期时间
        session.Options(sessions.Options{
            MaxAge: 3600 * 6, // 6hrs
        })
        //设置 Session
        session.Set("username", "张三") 
        session.Save() 
        c.JSON(200, gin.H{
            "msg": session.Get("username")
            })
    })

    r.GET("/user", func(c *gin.Context) {
        // 初始化 session 对象
        session := sessions.Default(c)
        // 通过 session.Get 读取 session 值
        username := session.Get("username") 
        c.JSON(200, gin.H{
            "username": username
        })
    })
    
    r.Run(":8000")
}

基于redis的存储引擎

package main

import (
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/redis"
    "github.com/gin-gonic/gin"
)

func main() {
    //初始化路由,会设置默认中间件:engine.Use(Logger(), Recovery()),可以使用gin.New()来设置路由
    r := gin.Default()

    //初始化基于redis的存储引擎: 需要启动redis服务,不然会报错
    //参数说明:
    //自第1个参数-redis最大的空闲连接数
    //第2个参数-数通信协议tcp或者udp
    //第3个参数-redis地址,格式,host:port 第4个参数-redis密码
    //第5个参数-session加密密钥
    store,_:=redis.NewStore(10,"tcp","localhost:6379","",[]byte("secret"))
    r.Use(sessions.Sessions("mysession",store))

    r.GET("/", func(c *gin.Context) {
        //初始化 session 对象
        session := sessions.Default(c)
        //设置过期时间
        session.Options(sessions.Options{
            MaxAge: 3600 * 6, // 6hrs
        })
        //设置 Session
        session.Set("username", "张三") 
        session.Save() 
        c.JSON(200, gin.H{
            "msg": session.Get("username")
            })
    })

    r.GET("/user", func(c *gin.Context) {
        // 初始化 session 对象
        session := sessions.Default(c)
        // 通过 session.Get 读取 session 值
        username := session.Get("username") 
        c.JSON(200, gin.H{
            "username": username
        })
    })
    
    r.Run(":8000")
}

三、配置 Golang Md5 加密

在models/tools.go下写一个md5加密方法
package models

import (
    "crypto/md5"
    "fmt"
    "io"
)

//md5加密
func Md5(str string) string {
    //data := []byte(str)
    //return fmt.Sprintf("%x\n", md5.Sum(data))

    h := md5.New()
    io.WriteString(h, str)
    return fmt.Sprintf("%x", h.Sum(nil))
}

四、创建数据库、实现用户登录、以及用户权限判断

1.创建数据库

-- ----------------------------
-- Table structure for manager
-- ----------------------------
DROP TABLE IF EXISTS `manager`;
CREATE TABLE `manager`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `mobile` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `status` tinyint(1) NULL DEFAULT NULL,
  `role_id` int(0) NULL DEFAULT NULL,
  `add_time` int(0) NULL DEFAULT NULL,
  `is_super` tinyint(1) NULL DEFAULT 0,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of manager
-- ----------------------------
INSERT INTO `manager` VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', '15201686411', '518864@qq.com', 1, 1, 0, 1);
INSERT INTO `manager` VALUES (2, 'zhagnsan', 'e10adc3949ba59abbe56e057f20f883e', '15201686412', '34233869@qq.com', 1, 2, 1581661532, 0);

2.创建模型

在目录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"
}

3.创建控制器

在controllers/admin下创建LoginController.go,实现用户的登录登出
package admin

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

type LoginController struct {
    BaseController
}

//进入登录页面
func (con LoginController) Index(c *gin.Context) {
    c.HTML(http.StatusOK, "admin/login/login.html", gin.H{})
}

//执行登录操作
func (con LoginController) DoIndex(c *gin.Context) {
    //获取表单中的数据
    captchaId := c.PostForm("captchaId")     // 验证码id
    verifyValue := c.PostForm("verifyValue") //验证码的值
    //获取用户名以及密码
    username := c.PostForm("username")
    password := c.PostForm("password")

    // 1.判断验证码是否验证成功
    if flag := models.VerifyCaptcha(captchaId, verifyValue); flag {
        //2.查询数据库,判断用户以及密码是否正确
        userinfo := []models.Manager{}
        password = models.Md5(password)
        models.DB.Where("username = ? and password = ? ", username, password).Find(&userinfo)
        if len(userinfo) > 0 {
            //3.执行登录,保存用户信息,执行跳转操作
            session := sessions.Default(c)
            //注意: session.Set没法保存结构体对应的切片,所以需要把结构体转换成json字符串
            userinfoSlice, _ := json.Marshal(userinfo)
            session.Set("userinfo", string(userinfoSlice))
            session.Save()
            con.Success(c, "登录成功", "/admin")
        } else {
            con.Error(c, "用户名或密码错误", "/admin/login")
        }
    } else {
        con.Error(c, "验证码验证失败", "/admin/login")
    }
}

//获取验证码,验证验证码
func (con LoginController) Captcha(c *gin.Context) {
    id, b64s, err := models.MakeCaptcha()
    if err != nil {
        fmt.Println(err)
    }
    c.JSON(http.StatusOK, gin.H{
        "captchaId":    id,
        "captchaImage": b64s,
    })
}

func (con LoginController) LoginOut(c *gin.Context) {
    //1.销毁session中用户信息
    session := sessions.Default(c)
    session.Delete("userinfo")
    session.Save()
    con.Success(c, "退出登录成功", "/admin/login")
}

4.创建adminAuth.go中间件

在middlewares文件夹下创建adminAuth.go中间件,进行权限判断
package middlewares

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

import (
    "encoding/json"
    "ginshop04/models"
    "strings"
    "github.com/gin-contrib/sessions"
    "github.com/gin-gonic/gin"
)
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 u []models.Manager
        //把获取到的用户信息转换结构体
        json.Unmarshal([]byte(userinfoStr), &u)
        if !(len(u) > 0 && u[0].Username != "") {
            if pathname != "/admin/login" && pathname != "/admin/doLogin" && pathname !="/admin/captcha" { 
                //跳转到登录页面
                c.Redirect(302, "/admin/login")
            }
        }
    } else {
        if pathname != "/admin/login" && pathname != "/admin/doLogin" && pathname != "/admin/captcha" { 
            c.Redirect(302, "/admin/login")
        }
    }
}

5.创建登录html表单页面

在templates/admin/login目录下,创建login.html页面
{{ define "admin/login/login.html" }}
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>用户登录</title>  
    <link rel="stylesheet" href="/static/admin/css/login.css">
    <script type="text/javascript" src="/static/admin/bootstrap/js/jquery-1.10.1.js"></script>
    <script type="text/javascript" src="/static/admin/js/login.js"></script>
</head>
<body>
<div class="container">
        <div id="login">
                <form action="/admin/doLogin" method="post" id="myform">
                    <input type="hidden" name="captchaId" id="captchaId">
                    <div class="l_title">小米商城后台管理系统-IT营</div>
                    <dl>
                        <dd>管理员姓名:<input class="text" type="text" name="username" id="username"></dd>
                        <dd>管理员密码:<input class="text" type="password" name="password" id="password"></dd>
                        <dd>验 证 码:<input id="verifyValue" type="text" name="verifyValue">
                            <img id="captchaImg" >
                         </dd>            
                        <dd><input type="submit" class="submit" name="dosubmit" value=""></dd>            
                    </dl>
                </form>
            </div>
</div>

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

6.增加登录相关路由

在routers/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("/login", admin.LoginController{}.Index) // 实例化控制器,并访问其中方法
        adminRouters.POST("/doLogin", admin.LoginController{}.DoIndex)
        adminRouters.GET("/loginOut", admin.LoginController{}.LoginOut)

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

7.完善main.go文件

package main

import (
    "fmt"
    "github.com/gin-contrib/sessions"
    "github.com/gin-contrib/sessions/redis"
    "github.com/gin-gonic/gin"
    "goshop/models"
    "goshop/routers"
    "html/template"
    "os"
)

func main() {
    //初始化路由,会设置默认中间件:engine.Use(Logger(), Recovery()),可以使用gin.New()来设置路由
    r := gin.Default()

    //初始化基于redis的存储引擎: 需要启动redis服务,不然会报错
    //参数说明:
    //自第1个参数-redis最大的空闲连接数
    //第2个参数-数通信协议tcp或者udp
    //第3个参数-redis地址,格式,host:port 第4个参数-redis密码
    //第5个参数-session加密密钥
    store,_:=redis.NewStore(10,"tcp","localhost:6379","",[]byte("secret"))
    r.Use(sessions.Sessions("mysession",store))

    //加载templates中所有模板文件, 使用不同目录下名称相同的模板,注意:一定要放在配置路由之前才得行
    //如果模板在多级目录里面的话需要这样配置 r.LoadHTMLGlob("templates/**/**/*") /** 表示目录
    //LoadHTMLGlob只能加载同一层级的文件
    //比如说使用router.LoadHTMLFile("/templates/**/*"),就只能加载/templates/admin/或者/templates/order/下面的文件
    //解决办法就是通过filepath.Walk来搜索/templates下的以.html结尾的文件,把这些html文件都加载一个数组中,然后用LoadHTMLFiles加载
    r.LoadHTMLGlob("templates/**/**/*")
    //var files []string
    //filepath.Walk("./templates", func(path string, info os.FileInfo, err error) error {
    //    if strings.HasSuffix(path, ".html") {
    //        files = append(files, path)
    //    }
    //    return nil
    //})
    //r.LoadHTMLFiles(files...)

    //配置静态web目录 第一个参数表示路由,第二个参数表示映射的目录
    r.Static("/static", "./static")

    //分组路由文件
    routers.AdminRoutersInit(r)
    routers.ApiRoutersInit(r)
    routers.DefaultRoutersInit(r)

    r.Run() // 启动一个web服务
}

[上一节][golang gin框架] 12.Gin 商城项目-base64Captcha生成图形验证码以及分布式架构中配置Captcha

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您提供一些关于使用 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 框架进行项目实战的流程。当然,在实际项目中,您需要根据自己的需求进行相应的修改和扩展。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值