Cookie 是 Web 开发中常用的状态保持机制,Gin 提供了便捷的 Cookie 操作方法。
使用 SetCookie 方法:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/set-cookie", func(c *gin.Context) {
c.SetCookie(
"username",
"张三",
3600,
"/",
"localhost",
false,
true,
)
c.String(http.StatusOK, "Cookie 已设置")
})
r.Run(":8080")
}
SetCookie 参数说明:
r.GET("/get-cookie", func(c *gin.Context) {
username, err := c.Cookie("username")
if err != nil {
c.String(http.StatusOK, "没有找到 Cookie")
return
}
c.String(http.StatusOK, "用户名: %s", username)
})
r.GET("/all-cookies", func(c *gin.Context) {
cookies := c.Request.Cookies()
result := make(map[string]string)
for _, cookie := range cookies {
result[cookie.Name] = cookie.Value
}
c.JSON(http.StatusOK, result)
})
r.GET("/delete-cookie", func(c *gin.Context) {
c.SetCookie(
"username",
"",
-1,
"/",
"",
false,
true,
)
c.String(http.StatusOK, "Cookie 已删除")
})
func AuthCookie() gin.HandlerFunc {
return func(c *gin.Context) {
token, err := c.Cookie("auth_token")
if err != nil || token == "" {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"error": "请先登录",
})
return
}
user, err := validateToken(token)
if err != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
"error": "登录已过期",
})
return
}
c.Set("currentUser", user)
c.Next()
}
}
r.POST("/login", func(c *gin.Context) {
var login struct {
Username string `json:"username"`
Password string `json:"password"`
}
if err := c.ShouldBindJSON(&login); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if login.Username != "admin" || login.Password != "123456" {
c.JSON(401, gin.H{"error": "用户名或密码错误"})
return
}
token := generateToken(login.Username)
c.SetCookie(
"auth_token",
token,
3600*24*7,
"/",
"",
false,
true,
)
c.JSON(200, gin.H{"message": "登录成功"})
})
r.GET("/profile", AuthCookie(), func(c *gin.Context) {
user, _ := c.Get("currentUser")
c.JSON(200, user)
})
r.POST("/logout", func(c *gin.Context) {
c.SetCookie("auth_token", "", -1, "/", "", false, true)
c.JSON(200, gin.H{"message": "已退出登录"})
})
生产环境的安全配置:
func setSecureCookie(c *gin.Context, name, value string, maxAge int) {
c.SetCookie(
name,
value,
maxAge,
"/",
"",
true,
true,
)
}
r.GET("/secure", func(c *gin.Context) {
setSecureCookie(c, "session", "abc123", 3600)
c.String(200, "安全 Cookie 已设置")
})
Go 1.11+ 支持 SameSite 属性:
r.GET("/samesite", func(c *gin.Context) {
http.SetCookie(c.Writer, &http.Cookie{
Name: "session",
Value: "abc123",
Path: "/",
MaxAge: 3600,
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteStrictMode,
})
c.String(200, "SameSite Cookie 已设置")
})
SameSite 值:
http.SameSiteDefaultMode - 默认值,等同于 Laxhttp.SameSiteLaxMode - 允许顶级导航携带 Cookiehttp.SameSiteStrictMode - 完全禁止跨站发送http.SameSiteNoneMode - 允许跨站发送(需要 Secure)Cookie 值需要编码处理特殊字符:
import "net/url"
r.GET("/encode-cookie", func(c *gin.Context) {
value := url.QueryEscape("张三&李四")
c.SetCookie("names", value, 3600, "/", "", false, true)
c.String(200, "编码 Cookie 已设置")
})
r.GET("/decode-cookie", func(c *gin.Context) {
encoded, err := c.Cookie("names")
if err != nil {
c.String(200, "没有 Cookie")
return
}
decoded, _ := url.QueryUnescape(encoded)
c.String(200, "解码后: %s", decoded)
})
Gin 的 Cookie 操作简单直观,SetCookie 和 Cookie 方法足够日常使用。生产环境记得设置 HttpOnly 和 Secure 属性,有条件的话也设置 SameSite,提高安全性。