Cookie
在 Gin 中,使用 Cookie 涉及到两个方法,Context.Cookie() 和 Context.SetCookie():
1func SetCookie(c *gin.Context) {
2 // 设置 Cookie
3 c.SetCookie("gin-cookie", "test", 3600, "/", "localhost", false, false)
4 c.JSON(http.StatusOK, gin.H{
5 "code": http.StatusOK,
6 "data": value,
7 })
8}
9func GetCookie(c *gin.Context) {
10 // 获取 Cookie
11 if value, err := c.Cookie(key); err != nil {
12 c.Status(http.StatusBadRequest)
13 } else {
14 c.JSON(http.StatusOK, gin.H{
15 "code": http.StatusOK,
16 "data": value,
17 })
18 }
19}
20
21func main() {
22 r := gin.Default()
23
24 r.POST("/cookie", SetCookie)
25 r.GET("/cookie", GetCookie)
26
27 if err := r.Run(":8080"); err != nil {
28 logrus.Error(err)
29 }
30}
其中:
-
Context.Cookie():获取指定名称的 Cookie。 -
Context.SetCookie():设置 Cookie。它的方法签名如下:1func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) { 2 // ... 3}参数解释如下:
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:
1c.SetCookie(key, value, 3600, "/", ".linner.com", false, false)
Session
Gin 是一个轻量的 Web 框架,在 Gin 中并不直接对 Session 提供支持,但是可以通过其他第三方中间件让 Gin 支持 Session。
在使用 Session 前,需要 get 对应的模块:
1go get github.com/gin-contrib/sessions
然后在需要使用到 Session 的地方引入:
1import "github.com/gin-contrib/sessions"
接着设置 Session 中间件:
1// 创建基于 Cookie 的存储引擎,secret 参数是加密密钥
2store := cookie.NewStore([]byte("secret"))
3// 配置 Session 中间件
4r.Use(sessions.Sessions("mysession", store))
具体示例如下:
1func SetSession(c *gin.Context) {
2 // 从 Context 中获取 Session 数据
3 session := sessions.Default(c)
4 // 设置 Session
5 session.Set("username", "lisi")
6 session.Set("nickname", "李四")
7
8 // 保存设置的 Session,设置完成之后必须要调用 Save()
9 if err := session.Save(); err != nil {
10 logrus.Error(err)
11 }
12
13 c.Status(http.StatusOK)
14}
15
16func GetSession(c *gin.Context) {
17 // 从 Context 中获取 Session 数据
18 session := sessions.Default(c)
19 // 获取 Session
20 username := session.Get("username")
21 nickname := session.Get("nickname")
22
23 c.JSON(http.StatusOK, gin.H{
24 "code": http.StatusOK,
25 "data": gin.H{
26 "username": username,
27 "nickname": nickname,
28 },
29 })
30}
31
32var store = cookie.NewStore([]byte("secret"))
33
34func main() {
35 r := gin.Default()
36
37 // 设置 Session 中间件
38 r.Use(sessions.Sessions("mysession", store))
39
40 r.POST("/session", SetSession)
41 r.GET("/session", GetSession)
42
43 if err := r.Run(":8080"); err != nil {
44 logrus.Error(err)
45 }
46}
Redis
github.com/gin-contrib/sessions 支持通过 Redis 缓存 Session,使其能够支持分布式系统。
在使用前需要先引入其 Redis 包:
1$ go get -u github.com/gin-contrib/sessions/redis
接着配置 Redis Store:
1// 配置 Redis Store
2func RedisStore() (store sessions.Store) {
3 if store, err := redis.NewStore(10, "tcp",
4 "localhost:6379", "", "123456", []byte("secret")); err != nil {
5 logrus.Error(err)
6 panic(err)
7 } else {
8 return store
9 }
10}
11
12var store = RedisStore()
13
14func main() {
15 r := gin.Default()
16
17 // 设置 Session 中间件
18 r.Use(sessions.Sessions("mysession", store))
19
20 r.POST("/session", SetSession)
21 r.GET("/session", GetSession)
22
23 if err := r.Run(":8080"); err != nil {
24 logrus.Error(err)
25 }
26}
redis.NewStore() 的定义如下:
1func NewStore(size int, network, address, username, password string, keyPairs ...[]byte) (Store, error) {
2 // ...
3}
其中:
size:最大连接数;network:连接方式,值为tcp或udp;address:服务器地址,需要指定端口号;username:Redis 用户名,没有配置用户名可传入空字符串;password:Redis 密码,没有配置密码可传入空字符串;keyPairs:Session 加密密钥。
评论