基于 gorilla/sessions 包在 Go 语言中启动和管理 Session
Go 语言官方提供的 http 包虽然对 HTTP 编程提供了丰富的 API,但是没有提供官方的 Session 实现。如果在 Web 应用中使用到了 Session,需要自行去实现(就像在线论坛这个入门项目中所做的那样),或者使用第三方工具包,比如 gorilla/sessions,这里我们以后者为例演示如何通过它在 Go Web 应用中启动和管理 Session。
gorilla/sessions
内置了基于 Cookie 和文件系统作为存储引擎的 Session 实现,此外,还为其他后端自定义 Session 存储驱动提供了底层接口(比如 Memcache、Redis、MySQL、MongoDB、PostgreSQL、CockroachDB 等,更多第三方驱动实现请参考项目官方文档)。
下面我们基于 gorilla/sessions
通过 Session 来实现一个简单的计数器,这里我们使用 Cookie 作为存储器。新建一个 counter
目录,运行 go mod init demo/counter
进行模块初始化 :
然后在该目录下编写计数器服务端实现代码 main.go
:
package main
import (
"github.com/gorilla/sessions"
"html/template"
"log"
"net/http"
"os"
)
// 初始化存储器(基于 Cookie)
var store = sessions.NewCookieStore([]byte(os.Getenv("SESSION_KEY)")))
func counter(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "GOSESSID")
count := session.Values["count"];
if count == nil {
session.Values["count"] = 1
} else {
session.Values["count"] = count.(int) + 1
}
err := session.Save(r, w)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
t, _ := template.ParseFiles("counter.gtpl")
w.Header().Set("Content-Type", "text/html")
t.Execute(w, session.Values["count"])
}
func main() {
http.HandleFunc("/counter", counter)
err := http.ListenAndServe(":8888", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
运行 go mod tidy
自动下载依赖。
通过上述源码可以看到,要基于 gorilla/sessions
管理 Session,首先要初始化一个 Session 存储器,这里我们使用 sessions.NewCookieStore
创建一个基于 Cookie 的 Session 存储器,并且通过系统变量传入 SESSION_KEY
进行认证。
在具体某个 Web 路由处理器方法中使用 Session(这里是处理 /counter
路由的 counter
处理器方法),可以通过 store.Get
方法获取或者创建一个新的 Session 对象(通过 GOSESSID
进行标识),然后我们试图通过 session.Values["count"]
从这个 Session 对象上获取存储在其中的 count
变量值,如果值为空,将其初始化为 1,否则在原来的基础上加 1,从而实现计数器的功能。最后,我们通过 session.Save
方法保存 Session 更改。
注:
session.Values
是一个字典结构(map[interface{}]interface{}
),所以可以向其中添加任意多个键值对存储信息。
我们通过 counter.gtpl
作为页面模板来渲染这个计数器视图,并且将 Session 中存储的 count
值传递给该视图模板。
在 counter
目录下创建这个 counter.gtpl
并编写一段简单的视图模板代码:
<h1>当前计数器的值:{{ . }}</h1>
运行 go run main.go
启动计数器服务(不要忘了传递 SESSION_KEY
系统变量):
然后在浏览器中就可以通过 http://localhost:8888/counter
访问这个计数器了:
每次刷新页面,计数器的值都会 +1:
打开浏览器开发者工具,在 Application | Storage | Cookies 中可以看到存储在 Cookie 中的 Session 信息(加密过),其默认有效期是 1 个月:
如果我们删除这个 Cookie,则 Session 数据会清空,计数器归零,刷新页面,计数器的值恢复成 1:
我们还可以将上述 Cookie 存储调整为文件存储:
// 初始化存储器
var store = sessions.NewFilesystemStore("session", []byte(os.Getenv("SESSION_KEY)")))
在 counter
目录下新建一个 session
子目录,重启服务,访问 http://localhost:8888/counter
,可以看到 session
目录下现在会创建对应的 Session 文件:
由于 Session 本身需要依赖 Cookie 存储 Session ID,所以在开发者工具中依然会包含名为 GOSESSID
的 Cookie 信息。
你还可以通过存储对象提供的 API 设置 Session 有效期,通过 Session 对象设置一次性消息(Flash Message),更多细节,请查看 gorilla/sessions
包底层源码。
1 Comment
counter 路由访问后会出现乱码, 建议
counter.gtpl
的代码为: