GoFrame登錄實戰之session實現

GoFrame登錄實戰之session實現

一、概念介紹

GF框架提供了完善的Session管理能力,由gsession模塊實現。由於Session機制在HTTP服務中最常用,因此後續章節中將着重以HTTP服務爲示例介紹Session的使用。

二、存儲實現方式

gsession實現併爲開發者提供了常見的三種Session存儲實現方式:

  1. 基於文件存儲(默認):單節點部署方式下比較高效的持久化存儲方式;
  2. 基於純內存存儲:性能最高效,但是無法持久化保存,重啓即丟失;
  3. 基於Redis存儲:遠程Redis節點存儲Session數據,支持應用多節點部署;

代碼:

s := g.Server()
// 設置文件
s.SetConfigWithMap(g.Map{
	"SessionStorage": gsession.NewStorageFile("/tmp"),
})
// 設置內存
s.SetConfigWithMap(g.Map{
	"SessionStorage": gsession.NewStorageMemory(),
})
// 設置redis
s.SetConfigWithMap(g.Map{
	"SessionStorage": gsession.NewStorageRedis(g.Redis()),
})

三、示例

目錄

:.
│  go.mod
│  go.sum
│  main.go
│
├─config
│      config.toml
│
├─gession
│  └─default
│          C1YHTZWK7PS0AEN9VA
│
├─template
│      index.html
│      user_index.html
│
└─test
        test.http

main.go

package main

import (
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/gsession"
)

const SessionUser = "SessionUser"

func main() {
	s := g.Server()

	// 設置存儲方式
	sessionStorage := g.Config().GetString("SessionStorage")
	if sessionStorage == "redis" {
		s.SetConfigWithMap(g.Map{
			"SessionIdName":  g.Config().GetString("server.SessionIdName"),
			"SessionStorage": gsession.NewStorageRedis(g.Redis()),
		})
	} else if sessionStorage == "memory" {
		s.SetConfigWithMap(g.Map{
			"SessionStorage": gsession.NewStorageMemory(),
		})
	}

	// 常規註冊
	group := s.Group("/")
	group.GET("/", func(r *ghttp.Request) {
		r.Response.WriteTpl("index.html", g.Map{
			"title": "登錄頁面",
		})
	})
	group.POST("/login", func(r *ghttp.Request) {
		username := r.GetString("username")
		password := r.GetString("password")

		//dbUsername := "admin"
		//dbPassword := "123456"
		dbUsername := g.Config().GetString("username")
		dbPassword := g.Config().GetString("password")
		if username == dbUsername && password == dbPassword {
			// 添加session
			r.Session.Set(SessionUser, g.Map{
				"username": dbUsername,
				"name":     "管理員",
			})
			r.Response.WriteJson(g.Map{
				"code": 0,
				"msg":  "登錄成功",
			})
			r.Exit()
		}

		r.Response.WriteJson(g.Map{
			"code": -1,
			"msg":  "登錄失敗",
		})
	})

	// 用戶組
	userGroup := s.Group("/user")
	userGroup.Middleware(MiddlewareAuth)
	// 列表頁面
	userGroup.GET("/index", func(r *ghttp.Request) {
		r.Response.WriteTpl("user_index.html", g.Map{
			"title": "列表頁面",
			"dataList": g.List{
				g.Map{
					"date":    "2020-04-01",
					"name":    "朱元璋",
					"address": "江蘇110號",
				},
				g.Map{
					"date":    "2020-04-02",
					"name":    "徐達",
					"address": "江蘇111號",
				},
				g.Map{
					"date":    "2020-04-03",
					"name":    "李善長",
					"address": "江蘇112號",
				},
			}})
	})
	userGroup.POST("/logout", func(r *ghttp.Request) {
		// 刪除session
		r.Session.Remove(SessionUser)

		r.Response.WriteJson(g.Map{
			"code": 0,
			"msg":  "登出成功",
		})
	})

	s.Run()
}

// 認證中間件
func MiddlewareAuth(r *ghttp.Request) {
	if r.Session.Contains(SessionUser) {
		r.Middleware.Next()
	} else {
		// 獲取用錯誤碼
		r.Response.WriteJson(g.Map{
			"code": 403,
			"msg":  "您訪問超時或已登出",
		})
	}
}


config.toml

# 賬號
username = "admin"
# 密碼
password = "123456"

# session存儲方式file,memory,redis
# SessionStorage = "file"

[server]
    Address          = ":8199"
    SessionIdName    = "gSessionId"
    SessionPath      = "./gession"
    SessionMaxAge    = "1m"
    DumpRouterMap    = true

# 模板引擎配置
[viewer]
    Path        = "template"
    DefaultFile = "index.html"
    Delimiters  =  ["${", "}"]

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <style>
        .el-row {
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
<div id="app">
    <el-row>
        <el-col :span="6" :offset="6" style="text-align: center">
            <span>${ .title }</span>
        </el-col>
    </el-row>
    <el-row>
        <el-col :span="6" :offset="6">
            <el-input v-model="username" placeholder="請輸入內容"></el-input>
        </el-col>
    </el-row>
    <el-row>
        <el-col :span="6" :offset="6">
            <el-input placeholder="請輸入密碼" v-model="password" show-password></el-input>
        </el-col>
    </el-row>
    <el-row>
        <el-col :span="6" :offset="6" style="text-align: center">
            <el-button @click="login">登錄</el-button>
        </el-col>
    </el-row>


</div>
</body>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

<script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script>

<script>
    new Vue({
        el: '#app',
        data: function () {
            return {
                visible: false,
                username: '',
                password: ''
            }
        },
        methods: {
            login: function () {
                axios.post('/login', {       // 還可以直接把參數拼接在url後邊
                    username: this.username,
                    password: this.password
                }).then(function (res) {
                    console.log(res.data)
                    if (res.data.code == 0) {
                        alert(res.data.msg)
                        window.location.href = "/user/index"
                    } else {
                        alert("失敗:" + res.data.msg)
                    }
                }).catch(function (error) {
                    console.log(error);
                });
            }
        }
    })
</script>
</html>

user_index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <style>
        .el-row {
            margin-bottom: 20px;
        }
    </style>
</head>
<body>
<div id="app">
    <el-row>
        <el-col :span="6" :offset="6" style="text-align: center">
            <span>${ .title }</span>
        </el-col>
    </el-row>
    <el-row>
        <el-col :span="24">
            <template>
                <el-table
                        :data="tableData"
                        style="width: 100%">
                    <el-table-column
                            prop="date"
                            label="日期"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="name"
                            label="姓名"
                            width="180">
                    </el-table-column>
                    <el-table-column
                            prop="address"
                            label="地址">
                    </el-table-column>
                </el-table>
            </template>
        </el-col>
    </el-row>
    <el-row>
        <el-col :span="6" :offset="6" style="text-align: center">
            <el-button @click="logout">登出</el-button>
        </el-col>
    </el-row>


</div>
</body>
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

<script src="https://cdn.bootcss.com/axios/0.19.2/axios.min.js"></script>

<script>
    ${/*
    tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀區金沙江路 1518 弄'
    }]
    */}

    var listData = new Array();
    var data;
    ${range $index, $elem := .dataList}
    data = {};
    ${range $key, $value := $elem}
    data['${$key}'] = '${$value}'
    ${end}
    listData.push(data)
    ${end}

    var vm = new Vue({
        el: '#app',
        data: {
            visible: false,
            tableData: listData
        },
        methods: {
            logout: function () {
                axios.post('/user/logout', {}).then(function (res) {
                    console.log(res.data)
                    if (res.data.code == 0) {
                        alert(res.data.msg)
                        window.location.href = "/"
                    } else {
                        alert("失敗:" + res.data.msg)
                    }
                }).catch(function (error) {
                    console.log(error);
                });
            }
        },
        mounted: function () {

        }
    })
</script>
</html>

test.http

POST http://127.0.0.1:8199/user/list
#Cookie: MySessionId=C1YHEOJ167MSBFJ5K1

###


視頻地址

代碼地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章