Cookie
在 Gin 中,使用 Cookie 涉及到两个方法,Context.Cookie() 和 Context.SetCookie():
func SetCookie(c *gin.Context) {
// 设置 Cookie
c.SetCookie("gin-cookie", "test", 3600, "/", "localhost", false, false)
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"data": value,
})
}
func GetCookie(c *gin.Context) {
// 获取 Cookie
if value, err := c.Cookie(key); err != nil {
c.Status(http.StatusBadRequest)
} else {
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"data": value,
})
}
}
func main() {
r := gin.Default()
r.POST("/cookie", SetCookie)
r.GET("/cookie", GetCookie)
if err := r.Run(":8080"); err != nil {
logrus.Error(err)
}
}
其中:
-
Context.Cookie():获取指定名称的 Cookie。 -
Context.SetCookie():设置 Cookie。它的方法签名如下:func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) { // ... }数解释如下: `name`:设置 Cookie 的名称。 `value`:设置 Cookie 的值。 `maxAge`:Cookie 的最大存活时间,单位为秒。如果为负数,则表示会话 Cookie(在浏览器关闭之后删除);如果为零,则表示立即删除Cookie。 `path`:Cookie 的生效路径。如果为空字符串,则使用当前请求的 URI 路径作为默认值。如果是 `"/"`,那么所有路径都访问该 Cookie。 `domain`:Cookie 的生效域。如果为空字符串,则不设置域名。 `secure`:Cookie 是否仅用于 HTTPS 连接。如果为 `true`,则仅通过 HTTPS 连接发送 Cookie;否则,使用 HTTP 或 HTTPS 连接都可以发送 Cookie。 `httpOnly`:Cookie 是否允许通过客户端程序访问。如果为 `true`,则无法通过客户端程序访问 Cookie;否则,可以通过客户端程序访问 Cookie。
httpOnly是微软对 Cookie 做的扩展。如果在 Cookie 中设置了httpOnly属性,则通过程序(JS 脚本、Applet 等)将无法读取到 Cookie 信息,防止 XSS 攻击产生。
多个二级域名共享 Cookie
服务器的 IP 配置了多个域名解析,此时设置 Cookie 就需要配置多个生效域。
例如,服务器的 IP 配置了域名泛解析 *.linner.com:
c.SetCookie(key, value, 3600, "/", ".linner.com", false, false)
Session
Gin 是一个轻量的 Web 框架,在 Gin 中并不直接对 Session 提供支持,但是可以通过其他第三方中间件让 Gin 支持 Session。
在使用 Session 前,需要 get 对应的模块:
go get github.com/gin-contrib/sessions
然后在需要使用到 Session 的地方引入:
import "github.com/gin-contrib/sessions"
接着设置 Session 中间件:
// 创建基于 Cookie 的存储引擎,secret 参数是加密密钥
store := cookie.NewStore([]byte("secret"))
// 配置 Session 中间件
r.Use(sessions.Sessions("mysession", store))
具体示例如下:
func SetSession(c *gin.Context) {
// 从 Context 中获取 Session 数据
session := sessions.Default(c)
// 设置 Session
session.Set("username", "lisi")
session.Set("nickname", "李四")
// 保存设置的 Session,设置完成之后必须要调用 Save()
if err := session.Save(); err != nil {
logrus.Error(err)
}
c.Status(http.StatusOK)
}
func GetSession(c *gin.Context) {
// 从 Context 中获取 Session 数据
session := sessions.Default(c)
// 获取 Session
username := session.Get("username")
nickname := session.Get("nickname")
c.JSON(http.StatusOK, gin.H{
"code": http.StatusOK,
"data": gin.H{
"username": username,
"nickname": nickname,
},
})
}
var store = cookie.NewStore([]byte("secret"))
func main() {
r := gin.Default()
// 设置 Session 中间件
r.Use(sessions.Sessions("mysession", store))
r.POST("/session", SetSession)
r.GET("/session", GetSession)
if err := r.Run(":8080"); err != nil {
logrus.Error(err)
}
}
Redis
github.com/gin-contrib/sessions 支持通过 Redis 缓存 Session,使其能够支持分布式系统。
在使用前需要先引入其 Redis 包:
$ go get -u github.com/gin-contrib/sessions/redis
接着配置 Redis Store:
// 配置 Redis Store
func RedisStore() (store sessions.Store) {
if store, err := redis.NewStore(10, "tcp",
"localhost:6379", "", "123456", []byte("secret")); err != nil {
logrus.Error(err)
panic(err)
} else {
return store
}
}
var store = RedisStore()
func main() {
r := gin.Default()
// 设置 Session 中间件
r.Use(sessions.Sessions("mysession", store))
r.POST("/session", SetSession)
r.GET("/session", GetSession)
if err := r.Run(":8080"); err != nil {
logrus.Error(err)
}
}
redis.NewStore() 的定义如下:
func NewStore(size int, network, address, username, password string, keyPairs ...[]byte) (Store, error) {
// ...
}
其中:
size:最大连接数;network:连接方式,值为tcp或udp;address:服务器地址,需要指定端口号;username:Redis 用户名,没有配置用户名可传入空字符串;password:Redis 密码,没有配置密码可传入空字符串;keyPairs:Session 加密密钥。
评论