cookie介绍
- HTTP是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出
- Cookie就是解决HTTP协议无状态的方案之一,中文是小甜饼的意思
- Cookie实际上就是服务器保存在浏览器上的一段信息。浏览器有了Cookie之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求
- Cookie由服务器创建,并发送给浏览器,最终由浏览器保存
- 测试服务端发送cookie给客户端,客户端请求时携带cookie
cookie使用
测试服务端发送cookie给客户端,客户端请求时携带cookie
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
// 测试服务端发送cookie给客户端,客户端请求时带有路由
func main() {
r := gin.Default()
//服务端要给客户端cookie
r.GET("cookie", func(ctx *gin.Context) {
//获取客户端是否携带cookie
cookie, err := ctx.Cookie("key_cookie")
if err != nil {
cookie = "NotSet"
//给客户端设置cookie
//MaxAge,int单位位秒
//path,cookie所在目录
//domain string 域名
//secure是否只能通过https访问
//httpOnly bool,是否允许别人通过js获取自己的cookie
ctx.SetCookie("key_cookie", "vaule_cookie", 60, "/", "localhost", false, true)
}
//fmt.Printf("cookie的值是: %s\n", cookie)
ctx.JSON(http.StatusOK, gin.H{
"cookie的值是": cookie,
})
})
r.Run()
}
客户端不带cookie时访问,同时客户端已经将cookie添加
cookie练习
- 模拟实现权限验证中间件
- 有2个路由,login和home
- login用于设置cookie
- home是访问查看信息的请求
- 在请求home之前,先跑中间件代码,检验是否存在cookie
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
/*
模拟实现权限验证中间件
有2个路由,login和home
login用于设置cookie
home是访问查看信息的请求
在请求home之前,先跑中间件代码,检验是否存在cookie
*/
func AuthMiddleWare() gin.HandlerFunc {
return func(ctx *gin.Context) {
//获取客户端的cookie并校验
if cookie, err := ctx.Cookie("abc"); err == nil {
if cookie == "123" {
ctx.Next()
return
}
}
//返回错误
ctx.JSON(http.StatusUnauthorized, gin.H{
"error": "err",
})
//若验证不通过,不再强调后续的函数处理
ctx.Abort()
return
}
}
func main() {
//创建路由
r := gin.Default()
r.GET("/login", func(ctx *gin.Context) {
//设置cookie
ctx.SetCookie("abc", "123", 60, "/", "localhost", false, true)
//返回信息
ctx.String(200, "Login success!")
})
r.GET("/home", AuthMiddleWare(), func(ctx *gin.Context) {
ctx.JSON(200, gin.H{
"data": "home",
})
})
r.Run()
}
第一访问/home,会显示错误,因为权限校验没有通过
然后访问login,登陆并设置了cookie返回给客户端
再次访问home,访问成功
session
主要功能是:
- 简单的API:将其用作设置签名(以及可选的加密)cookie的简便方法。
- 内置的后端可将session存储在cookie或文件系统中。
- Flash消息:一直持续读取的session值。
- 切换session持久性(又称“记住我”)和设置其他属性的便捷方法。
- 旋转身份验证和加密密钥的机制。
- 每个请求有多个session,即使使用不同的后端也是如此。
- 自定义session后端的接口和基础结构:可以使用通用API检索并批量保存来自不同商店的session。
package main
import (
"fmt"
"net/http"
"github.com/gorilla/sessions"
)
// 初始化一个cookie存储对象
// something-very-secret是一个自己的密钥
var store = sessions.NewCookieStore([]byte("something-very-secret"))
func SaveSession(w http.ResponseWriter, r *http.Request) {
// 得到一个session,忽略从解码结果的错误
//存在session: GET()方法总是返回一个会话,哪怕是空的
//获取一个session对象,session-name是session的名字
sessions, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
//在session中存储值
sessions.Values["foo"] = "bar"
sessions.Values[42] = 43
//保存更改
sessions.Save(r, w)
}
func GetSession(w http.ResponseWriter, r *http.Request) {
sessions, err := store.Get(r, "session-name")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
foo := sessions.Values["foo"]
fmt.Println(foo)
}
func main() {
http.HandleFunc("/save", SaveSession)
http.HandleFunc("/get", GetSession)
err := http.ListenAndServe(":8000", nil)
if err != nil {
fmt.Println("HTTP server failed,err:", err)
return
}
}