Gin -- 会话控制
10.1 cookie
1. 概述
- HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出
- Cookie就是解决HTTP协议无状态的方案之一,中文是小甜饼的意思
- Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求
- Cookie由服务器创建,并发送给浏览器,最终由浏览器保存
2. 操作方法
1. 获取 cookie
ctx.Cookie("cookie的key")
2. 设置 cookie
SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool)
// name为cookie的key
// value为cookie的值,
// maxAge为过期时间,单位为秒,
// path为给哪个url设置cookie
// domain为本服务器的ip
// secure为是否只能通过https访问
// httpOnly为是否允许别人通过js获取自己的cookie
c.SetCookie("name","xiaohuang",60,"/login","127.0.0.1",false,true)
3. 示例
func indexHandler(c *gin.Context) {
// 客户端是否携带Cookie
cookie, err := c.Cookie("key_cookie")
if err != nil{
cookie = "NoSet"
// 设置cookie函数
c.SetCookie("name","xiaohuang",60,"/login","127.0.0.1",false,true)
}
fmt.Println(cookie)
c.HTML(http.StatusOK,"user/index.html",gin.H{"title": "我是测试", "address": "www.5lmh.com"})
}
3. 练习
1. 模拟实现权限验证中间件
- 有两个路由:login和home
- login用于设置cookie
- home是访问查看信息的请求
- 在请求home之前,先跑中间件代码,检验是否存在cookie
- 访问home,会显示错误,因为权限校验未通过
由于我使用的是不同app的不同路由,我的目录结构如下:

编写中间件
func MiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
// 通过请求路径,避开登录时验证cookie
if c.Request.RequestURI != "/userlogin"{
fmt.Println(">>>>中间件开始执行")
cookieStr,err := c.Cookie("authStr")
if err != nil{
fmt.Println("cookie 为空")
// 设置变量到Context的key中,可以通过Get()取,在Handler中通过判断middleware的值,返回对应的错误
c.Set("middleware","nil")
}
if cookieStr != "awersxcxcfwefbweva"{
fmt.Println("cookie错误")
// 设置变量到Context的key中,可以通过Get()取
c.Set("middleware","err")
}
status := c.Writer.Status()
fmt.Println("中间件执行完毕>>>",status)
}
}
}
注册Middleware

func Init() *gin.Engine {
r := gin.New()
// 注册全局中间件
r.Use(MiddleWare())
for _, opt := range options{
opt(r)
}
return r
}
Handler根据不同的middleware值返回不同的错误
func userLoginHandler(c *gin.Context) {
var userLogin model.Login
// 获取中间件设置的值,进行判断
errStr,exit := c.Get("middleware")
if !exit{
fmt.Println(">>>>> 后端设置错误")
}
if errStr == "nil"{
c.JSON(http.StatusOK, gin.H{"code": 40000003, "error": "cookie不允许为nil", "data": ""})
return
}
if errStr == "err"{
c.JSON(http.StatusOK, gin.H{"code": 40000004, "error": "cookie串不合法", "data": ""})
return
}
if err := c.ShouldBindJSON(&userLogin); err != nil {
c.JSON(http.StatusOK, gin.H{"code": 40000001, "error": "参数错误", "data": ""})
return
}
if userLogin.User != "root" || userLogin.Password != "admin" {
c.JSON(http.StatusOK, gin.H{"code": 40000002, "error": "账号或密码错误", "data": ""})
return
}
c.SetCookie("authStr", "awersxcxcfwefbweva", 60, "/userlogin", "127.0.0.1", false, true)
c.JSON(http.StatusOK, gin.H{"code": 20000000, "error": "登录成功", "data": "hello"})
}
第二种方式
func AuthMiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
// 获取客户端cookie并校验
if cookie, err := c.Cookie("abc"); err == nil {
if cookie == "123" {
c.Next()
return
}
}
// 返回错误
c.JSON(http.StatusUnauthorized, gin.H{"error": "err"})
// 若验证不通过,不再调用后续的函数处理
c.Abort()
return
}
}
4. 缺点
不安全,明文
增加带宽消耗
可以被禁用
cookie有上限
2. session
0. 官网地址
http://www.gorillatoolkit.org/pkg/sessions
1. 概述
gorilla/sessions为自定义session后端提供cookie和文件系统session以及基础结构。
主要功能是:
- 简单的API:将其用作设置签名(以及可选的加密)cookie的简便方法。
- 内置的后端可将session存储在cookie或文件系统中。
- Flash消息:一直持续读取的session值。
- 切换session持久性(又称“记住我”)和设置其他属性的便捷方法。
- 旋转身份验证和加密密钥的机制。
- 每个请求有多个session,即使使用不同的后端也是如此。
- 自定义session后端的接口和基础结构:可以使用通用API检索并批量保存来自不同商店的session。
2. 示例
package main
import (
"fmt"
"net/http"
"github.com/gorilla/sessions"
)
// 初始化一个cookie存储对象
// something-very-secret应该是一个你自己的密匙,只要不被别人知道就行
var store = sessions.NewCookieStore([]byte("something-very-secret"))
func main() {
http.HandleFunc("/save", SaveSession)
http.HandleFunc("/get", GetSession)
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println("HTTP server failed,err:", err)
return
}
}
func SaveSession(w http.ResponseWriter, r *http.Request) {
// Get a session. We're ignoring the error resulted from decoding an
// existing session: Get() always returns a session, even if empty.
// 获取一个session对象,session-name是session的名字
session, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// 在session中存储值
session.Values["foo"] = "bar"
session.Values[42] = 43
// 保存更改
session.Save(r, w)
}
func GetSession(w http.ResponseWriter, r *http.Request) {
session, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
foo := session.Values["foo"]
fmt.Println(foo)
}
3. 操作方法
1. 删除session
// 将session的最大存储时间设置为小于零的数即为删除
session.Options.MaxAge = -1
session.Save(r, w)
python防脱发技巧

浙公网安备 33010602011771号