文章目录
一 写在开始的简介和弯路(用处不大,可直接看第二部分哦)
Why session?
Session会在一定时间内保存在服务器上,相比Cookie更安全…更值得一提的当然是session的密钥key,实现session的加密功能
刚开始写session的时候,走了点“弯路”,自己跟着封装sessions的思路去封装了一个sessions包,其实可以直接用现成封装好的sessions包来使用sessions功能。
代码大纲:
一条华华丽丽的分割线,把上面没啥用的话割去(其实就是告诉大家不需要自己写session包)
然后下面就是对sessions包的使用咯(划重点哦)!!!
二 session库的准备工作
主要调用的包:
https://github.com/gin-contrib/sessions
同时需要依赖包:
https://github.com/gorilla/sessions
其实当时报错缺包是如下几种:
下图是我的golang目录结构:
安装包的方法其实不难,总结如下:
1、在命令行中go get github.com/gin-contrib/sessions
(但是其实下载时有点慢)
2、在git bash
中git clone https://github.com/gin-contrib/sessions.git
(我一般这样用的很方便的操作)
3、有时候克隆不完整/失败,就直接点,上github下载下来就OK了(其实蛮实用的万能方法)
…
三 实现session的代码逻辑
逻辑很简单,要保持登录状态嘛,在login的路由中,登录成功之后加上设置保存session的代码,但是创建cookie store
密钥及使用中间件的时候,代码放在main()或全局中哦
四 session库的代码实现方法
1 设置全局变量store(划重点:全局)
var store = cookie.NewStore([]byte("secret"))
eg. 我是将main和router分开的,所以像这样就可以:
2 在路由中使用中间件调用store
r := gin.Default()
r.Use(sessions.Sessions("sessionid", store))
3 初始化sessions
session := sessions.Default(c)
4 设置sessions的相关参数
option := sessions.Options{MaxAge: 3600}
session.Options(option)
5 生成sessions并保存(记得一定要Save的!)
session.Set("sessionid", username)
err := session.Save()
6 服务器端检查一下是否成功
if err != nil {
fmt.Println("Fail to save session")
} else {
fmt.Println("Succeed to save session")
}
v := session.Get("sessionid")
fmt.Println("sessionid:", v)
注意:这里session.Get
在终端打印出来的sessionid是未加密字符串!但是实际上对外保存的字符串是通过了key
加密后的结果!下面是postman
的测试结果:
看到那堆乱七八糟的字符串了吗?那就对啦⭐,因为它是字符串"www"对应的加密字符串~
7 获取sessions值
session := sessions.Default(c)
v := session.Get("sessionid")
fmt.Println("sessionid:", v)
8 响应头的设置
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Credentials", "true")
五 另外提一点点
其实github上的官方教程例子很好代码也简洁,也是很实用的教程,可以仔细看看(用法并不复杂,但是需要实践去测试怎么正确使用,只要掌握就很简单了)
用了sessions包以后代码也就变得很简单很多很多很多x100啦
【1】请求调试工具:Postman
【2】附上官方链接: https://github.com/gin-contrib/sessions
【3】net/http
中Cookie
的调用: 【Golang】Cookie保持会话状态的实现
【4】Cookie/Session
机制详解: Cookie/Session机制详解
六、补充
上面的写法固然没有问题,这里补充另一种写法(2020.7.19)
1 生成session
func SaveSession(w http.ResponseWriter, r *http.Request) {
// 获取一个session对象,session-name是session的名字
session, err := store.Get(r, "sessionID")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 在session中存储值
session.Values["sessionID"] = userId
// 保存更改
session.Save(r, w)
}
2 获取session
func GetSession(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "sessionID")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
id := session.Values["sessionID"]
fmt.Println("sessionID", id)
}
如上函数获取到的id是一个接口型参数,不能直接当作string返回
3 设置session
session.Options.MaxAge = -1
//负数即是直接删除session 正数即是设置time
session.Save(r, w)
如果我们使用gin框架,那么替换如下:
r ---> c.Request
w ---> c.Writer