golang Cookie结构体解析与操作辅助插件库cookie的使用

Golang Cookie结构体解析与操作辅助插件库cookie的使用

概述

cookie是一个Go语言包,旨在简化HTTP cookie的处理,并支持将cookie解析到结构体中。它支持标准数据类型、自定义数据类型和签名cookie以确保数据完整性。

特性

  • 易于使用:简单的API用于管理web应用中的cookie
  • 基于结构体的cookie值:轻松将cookie解析到结构体中
  • 自定义类型支持:扩展cookie解析以支持自定义数据类型
  • 签名cookie:使用HMAC签名确保cookie的完整性
  • 无外部依赖:仅使用标准库

安装

go get github.com/syntaqx/cookie

基本用法

cookie包提供了DefaultManager,可以直接在现有应用中使用:

cookie.Get(r, "DEBUG")
cookie.GetSigned(r, "Access-Token")
cookie.Set(w, "DEBUG", "true", cookie.Options{})
cookie.Set(w, "Access-Token", "token_value", cookie.Options{Signed: true})
cookie.SetSigned(w, "Access-Token", "token_value")

或者将cookie填充到结构体中:

type RequestCookies struct {
  Theme       string    `cookie:"THEME"`
  Debug       bool      `cookie:"DEBUG,unsigned"`
  AccessToken string    `cookie:"Access-Token,signed"`
}

var c RequestCookies
cookie.PopulateFromCookies(r, &c)

要使用签名cookie,必须提供签名密钥:

signingKey := []byte("super-secret-key")
cookie.DefaultManager = cookie.NewManager(
  cookie.WithSigningKey(signingKey),
)

完整示例Demo

package main

import (
	"fmt"
	"net/http"
	"time"
	
	"github.com/syntaqx/cookie"
)

func main() {
	// 设置签名密钥
	signingKey := []byte("super-secret-key")
	cookie.DefaultManager = cookie.NewManager(
		cookie.WithSigningKey(signingKey),
	)

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// 设置cookie
		err := cookie.Set(w, "THEME", "dark", cookie.Options{
			Expires: time.Now().Add(24 * time.Hour),
		})
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// 设置签名cookie
		err = cookie.SetSigned(w, "Access-Token", "abc123xyz")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// 获取cookie
		theme, err := cookie.Get(r, "THEME")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// 获取签名cookie
		token, err := cookie.GetSigned(r, "Access-Token")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// 使用结构体解析
		type RequestCookies struct {
			Theme       string `cookie:"THEME"`
			AccessToken string `cookie:"Access-Token,signed"`
		}
		
		var cookies RequestCookies
		err = cookie.PopulateFromCookies(r, &cookies)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		fmt.Fprintf(w, "Theme: %s\nToken: %s\nStruct Theme: %s\nStruct Token: %s", 
			theme, token, cookies.Theme, cookies.AccessToken)
	})

	http.ListenAndServe(":8080", nil)
}

高级用法:Manager

对于更高级的用法,可以创建一个Manager来处理cookie,而不是依赖DefaultManager

manager := cookie.NewManager()

可以可选地提供签名密钥:

signingKey := []byte("super-secret-key")
manager := cookie.NewManager(
  cookie.WithSigningKey(signingKey),
)

设置Cookie

使用Set方法设置cookie,可以指定路径、域名、过期时间等选项:

err := manager.Set(w, "DEBUG", "true", cookie.Options{})
err := manager.Set(w, "Access-Token", "token_value", cookie.Options{Signed: true})

获取Cookie

使用Get方法获取未签名的cookie,使用GetSigned获取签名cookie:

value, err := manager.Get(r, "DEBUG")
value, err := manager.GetSigned(r, "Access-Token")

从Cookie填充结构体

使用PopulateFromCookies将cookie值填充到结构体中,结构体字段应使用cookie名称标记:

type RequestCookies struct {
  Theme       string    `cookie:"THEME"`
  Debug       bool      `cookie:"DEBUG,unsigned"`
  AccessToken string    `cookie:"Access-Token,signed"`
  NotRequired string    `cookie:"NOT_REQUIRED,omitempty"`
}

var c RequestCookies
err := manager.PopulateFromCookies(r, &c)

支持自定义类型

要支持自定义类型,可以向Manager注册自定义处理程序:

import (
  "reflect"
  "github.com/gofrs/uuid/v5"
  "github.com/syntaqx/cookie"
)

manager := cookie.NewManager(
  cookie.WithSigningKey(signingKey),
  cookie.WithCustomHandler(reflect.TypeOf(uuid.UUID{}), func(value string) (interface{}, error) {
    return uuid.FromString(value)
  }),
)

这个库提供了简单而强大的cookie处理功能,特别适合需要将cookie值映射到结构体的应用场景。


更多关于golang Cookie结构体解析与操作辅助插件库cookie的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang Cookie结构体解析与操作辅助插件库cookie的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Golang Cookie结构体解析与操作辅助库

Cookie结构体解析

在Go语言中,net/http包提供了Cookie结构体,用于表示HTTP cookie。以下是Cookie结构体的定义:

type Cookie struct {
    Name       string
    Value      string
    Path       string
    Domain     string
    Expires    time.Time
    RawExpires string
    MaxAge     int
    Secure     bool
    HttpOnly   bool
    SameSite   SameSite
    Raw        string
    Unparsed   []string
}

各字段含义:

  • Name: cookie名称
  • Value: cookie值
  • Path: cookie路径
  • Domain: cookie域名
  • Expires: cookie过期时间
  • MaxAge: cookie有效期(秒)
  • Secure: 是否仅通过HTTPS传输
  • HttpOnly: 是否仅限HTTP访问(防止JavaScript访问)
  • SameSite: 跨站请求策略

标准库操作示例

设置Cookie

http.HandleFunc("/set", func(w http.ResponseWriter, r *http.Request) {
    cookie := &http.Cookie{
        Name:     "session_id",
        Value:    "abc123",
        Path:     "/",
        MaxAge:   3600,
        HttpOnly: true,
        Secure:   true,
        SameSite: http.SameSiteLaxMode,
    }
    http.SetCookie(w, cookie)
    fmt.Fprintln(w, "Cookie set")
})

读取Cookie

http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) {
    cookie, err := r.Cookie("session_id")
    if err != nil {
        if err == http.ErrNoCookie {
            fmt.Fprintln(w, "Cookie not found")
            return
        }
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }
    fmt.Fprintf(w, "Cookie value: %s", cookie.Value)
})

删除Cookie

http.HandleFunc("/delete", func(w http.ResponseWriter, r *http.Request) {
    cookie := &http.Cookie{
        Name:   "session_id",
        Value:  "",
        Path:   "/",
        MaxAge: -1, // 设置为负值表示删除
    }
    http.SetCookie(w, cookie)
    fmt.Fprintln(w, "Cookie deleted")
})

辅助插件库推荐

1. gorilla/securecookie

gorilla/securecookie提供了安全的cookie编码/解码功能,防止cookie被篡改。

import "github.com/gorilla/securecookie"

var hashKey = securecookie.GenerateRandomKey(64)
var blockKey = securecookie.GenerateRandomKey(32)
var s = securecookie.New(hashKey, blockKey)

// 编码
func setSecureCookie(w http.ResponseWriter, name string, value map[string]string) {
    if encoded, err := s.Encode(name, value); err == nil {
        cookie := &http.Cookie{
            Name:  name,
            Value: encoded,
            Path:  "/",
        }
        http.SetCookie(w, cookie)
    }
}

// 解码
func getSecureCookie(r *http.Request, name string) (map[string]string, error) {
    cookie, err := r.Cookie(name)
    if err != nil {
        return nil, err
    }
    value := make(map[string]string)
    return value, s.Decode(name, cookie.Value, &value)
}

2. gofiber/fiber

Fiber框架提供了更简洁的cookie操作API:

import "github.com/gofiber/fiber/v2"

app := fiber.New()

// 设置cookie
app.Get("/set", func(c *fiber.Ctx) error {
    c.Cookie(&fiber.Cookie{
        Name:     "token",
        Value:    "123456",
        Expires:  time.Now().Add(24 * time.Hour),
        HTTPOnly: true,
        SameSite: "Lax",
    })
    return c.SendString("Cookie set")
})

// 获取cookie
app.Get("/get", func(c *fiber.Ctx) error {
    return c.SendString("Cookie value: " + c.Cookies("token"))
})

// 删除cookie
app.Get("/delete", func(c *fiber.Ctx) error {
    c.ClearCookie("token")
    return c.SendString("Cookie deleted")
})

3. go-chi/chi

Chi路由器的中间件方式处理cookie:

import "github.com/go-chi/chi"

func cookieMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 读取或设置cookie
        cookie, err := r.Cookie("visits")
        if err != nil {
            cookie = &http.Cookie{
                Name:  "visits",
                Value: "1",
            }
        } else {
            visits, _ := strconv.Atoi(cookie.Value)
            cookie.Value = strconv.Itoa(visits + 1)
        }
        http.SetCookie(w, cookie)
        
        next.ServeHTTP(w, r)
    })
}

func main() {
    r := chi.NewRouter()
    r.Use(cookieMiddleware)
    // ...其他路由
}

自定义Cookie辅助函数

以下是一些常用的cookie操作辅助函数:

// 设置cookie
func SetCookie(w http.ResponseWriter, name, value string, maxAge int) {
    http.SetCookie(w, &http.Cookie{
        Name:     name,
        Value:    value,
        Path:     "/",
        MaxAge:   maxAge,
        HttpOnly: true,
        Secure:   true,
        SameSite: http.SameSiteLaxMode,
    })
}

// 获取cookie
func GetCookie(r *http.Request, name string) (string, error) {
    cookie, err := r.Cookie(name)
    if err != nil {
        return "", err
    }
    return cookie.Value, nil
}

// 删除cookie
func DeleteCookie(w http.ResponseWriter, name string) {
    http.SetCookie(w, &http.Cookie{
        Name:   name,
        Value:  "",
        Path:   "/",
        MaxAge: -1,
    })
}

// 检查cookie是否存在
func HasCookie(r *http.Request, name string) bool {
    _, err := r.Cookie(name)
    return err == nil
}

这些辅助库和函数可以简化cookie操作,提高开发效率,同时增强安全性。根据项目需求选择合适的工具,或基于标准库封装自己的cookie处理逻辑。

回到顶部