Golang通过net/http包管理Cookie,使用http.Cookie设置会话,结合HttpOnly、Secure、SameSite等属性提升安全性,通过Expires或MaxAge控制过期时间,推荐将会话ID存于Cookie,敏感数据存储在Redis等服务端存储中以保障安全。

Cookie管理在Golang中用于维护用户会话状态,允许服务器跟踪用户活动,实现个性化体验和安全控制。
解决方案
Golang提供了
net/http
设置Cookie:
立即学习“go语言免费学习笔记(深入)”;
在HTTP响应中设置Cookie,需要使用
http.Cookie
package main
import (
"net/http"
)
func setCookieHandler(w http.ResponseWriter, r *http.Request) {
cookie := &http.Cookie{
Name: "session_id",
Value: "unique_session_value",
Path: "/",
HttpOnly: true, // 防止客户端脚本访问
Secure: true, // 仅通过HTTPS传输
}
http.SetCookie(w, cookie)
w.Write([]byte("Cookie set!"))
}
func main() {
http.HandleFunc("/set_cookie", setCookieHandler)
http.ListenAndServe(":8080", nil)
}这段代码创建了一个名为
session_id
HttpOnly
Secure
HttpOnly
Secure
读取Cookie:
在后续的请求中,客户端会自动发送之前设置的Cookie。服务器可以通过
http.Request
Cookie
package main
import (
"fmt"
"net/http"
)
func readCookieHandler(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("session_id")
if err != nil {
if err == http.ErrNoCookie {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("No cookie found"))
return
}
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Error reading cookie"))
return
}
fmt.Fprintf(w, "Cookie value: %s", cookie.Value)
}
func main() {
http.HandleFunc("/read_cookie", readCookieHandler)
http.ListenAndServe(":8080", nil)
}这段代码尝试读取名为
session_id
401 Unauthorized
400 Bad Request
会话管理:
Cookie通常用于维护用户会话。服务器可以生成一个唯一的会话ID,将其存储在Cookie中,并在服务器端存储会话数据(例如,用户信息、登录状态)。
package main
import (
"fmt"
"net/http"
"net/url"
"sync"
"github.com/google/uuid"
)
type Session struct {
Username string
}
var (
sessions = make(map[string]Session)
sessionLock sync.RWMutex
)
func createSessionHandler(w http.ResponseWriter, r *http.Request) {
username := r.FormValue("username")
if username == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Username is required"))
return
}
sessionID := uuid.New().String()
sessionLock.Lock()
sessions[sessionID] = Session{Username: username}
sessionLock.Unlock()
cookie := &http.Cookie{
Name: "session_id",
Value: url.QueryEscape(sessionID), // URL编码,防止特殊字符
Path: "/",
HttpOnly: true,
Secure: true,
}
http.SetCookie(w, cookie)
fmt.Fprintf(w, "Session created for user: %s", username)
}
func getSessionHandler(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("session_id")
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("No session found"))
return
}
sessionID, err := url.QueryUnescape(cookie.Value) // URL解码
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Invalid session ID"))
return
}
sessionLock.RLock()
session, ok := sessions[sessionID]
sessionLock.RUnlock()
if !ok {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Session not found"))
return
}
fmt.Fprintf(w, "Welcome, %s!", session.Username)
}
func main() {
http.HandleFunc("/create_session", createSessionHandler)
http.HandleFunc("/get_session", getSessionHandler)
http.ListenAndServe(":8080", nil)
}这个例子使用
github.com/google/uuid
map
sync.RWMutex
Golang中如何处理Cookie的过期时间?
Cookie的过期时间可以通过
http.Cookie
Expires
MaxAge
Expires
MaxAge
package main
import (
"net/http"
"time"
)
func setCookieWithExpiration(w http.ResponseWriter, r *http.Request) {
// 使用 Expires
expires := time.Now().Add(24 * time.Hour)
cookieExpires := &http.Cookie{
Name: "expires_cookie",
Value: "expires_value",
Expires: expires,
Path: "/",
}
http.SetCookie(w, cookieExpires)
// 使用 MaxAge
cookieMaxAge := &http.Cookie{
Name: "max_age_cookie",
Value: "max_age_value",
MaxAge: 3600, // 1小时
Path: "/",
}
http.SetCookie(w, cookieMaxAge)
w.Write([]byte("Cookies with expiration set!"))
}
func main() {
http.HandleFunc("/set_expiration", setCookieWithExpiration)
http.ListenAndServe(":8080", nil)
}Expires
MaxAge
Expires
MaxAge
MaxAge
MaxAge
MaxAge
如何安全地存储会话数据?
直接将敏感数据存储在Cookie中是不安全的。应该将会话ID存储在Cookie中,然后将会话数据存储在服务器端,例如,使用Redis或数据库。同时,应该使用HTTPS来加密Cookie的传输,防止中间人攻击。
package main
import (
"fmt"
"net/http"
"net/url"
"sync"
"time"
"github.com/go-redis/redis/v8"
"github.com/google/uuid"
)
var (
redisClient *redis.Client
sessionLock sync.RWMutex
)
type Session struct {
Username string
}
func init() {
redisClient = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
}
func createSecureSessionHandler(w http.ResponseWriter, r *http.Request) {
username := r.FormValue("username")
if username == "" {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Username is required"))
return
}
sessionID := uuid.New().String()
// 将会话数据存储在Redis中
err := redisClient.Set(r.Context(), sessionID, username, 24*time.Hour).Err()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Failed to store session data"))
return
}
cookie := &http.Cookie{
Name: "session_id",
Value: url.QueryEscape(sessionID),
Path: "/",
HttpOnly: true,
Secure: true,
}
http.SetCookie(w, cookie)
fmt.Fprintf(w, "Secure session created for user: %s", username)
}
func getSecureSessionHandler(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("session_id")
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("No session found"))
return
}
sessionID, err := url.QueryUnescape(cookie.Value)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Invalid session ID"))
return
}
// 从Redis中获取会话数据
username, err := redisClient.Get(r.Context(), sessionID).Result()
if err == redis.Nil {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Session not found"))
return
} else if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Failed to retrieve session data"))
return
}
fmt.Fprintf(w, "Welcome, %s!", username)
}
func main() {
http.HandleFunc("/create_secure_session", createSecureSessionHandler)
http.HandleFunc("/get_secure_session", getSecureSessionHandler)
http.ListenAndServe(":8080", nil)
}这个例子使用Redis来存储会话数据。会话ID存储在Cookie中,而用户名存储在Redis中。这样可以避免将敏感数据直接存储在Cookie中。
如何在Golang中实现Cookie的SameSite属性?
SameSite
http.Cookie
SameSite
package main
import (
"net/http"
)
func setSameSiteCookie(w http.ResponseWriter, r *http.Request) {
cookieStrict := &http.Cookie{
Name: "samesite_strict",
Value: "strict_value",
Path: "/",
SameSite: http.SameSiteStrictMode, // 严格模式
Secure: true,
HttpOnly: true,
}
http.SetCookie(w, cookieStrict)
cookieLax := &http.Cookie{
Name: "samesite_lax",
Value: "lax_value",
Path: "/",
SameSite: http.SameSiteLaxMode, // 宽松模式
Secure: true,
HttpOnly: true,
}
http.SetCookie(w, cookieLax)
cookieNone := &http.Cookie{
Name: "samesite_none",
Value: "none_value",
Path: "/",
SameSite: http.SameSiteNoneMode, // 无限制模式
Secure: true, // SameSite=None 必须配合 Secure=true 使用
HttpOnly: true,
}
http.SetCookie(w, cookieNone)
w.Write([]byte("SameSite cookies set!"))
}
func main() {
http.HandleFunc("/set_samesite", setSameSiteCookie)
http.ListenAndServe(":8080", nil)
}SameSite
http.SameSiteStrictMode
http.SameSiteLaxMode
http.SameSiteNoneMode
SameSite=None
Secure=true
选择哪种模式取决于应用的安全需求。通常,
SameSiteStrictMode
SameSiteLaxMode
SameSiteNoneMode
以上就是Golang Cookie管理 用户会话状态维护的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号