golang高效安全的Cookie编码解码插件库securecookie的使用
Golang高效安全的Cookie编码解码插件库securecookie的使用
securecookie是一个用于编码和解码安全Cookie值的Golang包,它比Gorilla的securecookie实现快3倍且不需要堆分配,同时提供同等的安全强度。
功能特点
- 安全Cookie的值会被加密并使用消息认证码签名
- 防止远程Cookie所有者知道或修改Cookie中的信息
- 防止攻击者伪造假Cookie
- 使用AES128和SHA256保证安全性
- 与Gorilla securecookie不兼容,采用更简单高效的编码方式
安装
go get -u "github.com/chmike/securecookie"
使用示例
生成随机密钥
var key []byte = securecookie.MustGenerateRandomKey()
建议将密钥保存在文件中并使用hex.EncodeToString()
编码,限制对该文件的访问。
创建Cookie对象
obj, err := securecookie.New("session", key, securecookie.Params{
Path: "/sec", // 仅当URL以此路径开头时接收Cookie
Domain: "example.com", // 仅当URL域名匹配时接收Cookie
MaxAge: 3600, // Cookie在设置后3600秒失效
HTTPOnly: true, // 禁止远程JavaScript代码访问
Secure: true, // 仅通过HTTPS接收Cookie
SameSite: securecookie.Lax, // 接收相同或子域名的Cookie
})
if err != nil {
// 处理错误
}
或者使用MustNew()
函数,在参数无效时会panic:
var obj = securecookie.MustNew("Auth", key, securecookie.Params{
Path: "/sec",
Domain: "example.com",
MaxAge: 3600,
HTTPOnly: true,
Secure: true,
SameSite: securecookie.Lax,
})
设置Cookie值
var val = []byte("some value")
// w是http.ResponseWriter
if err := obj.SetValue(w, val); err != nil {
// 处理错误
}
获取Cookie值
// r是*http.Request
val, err := obj.GetValue(buf, r)
if err != nil {
// 处理错误
}
删除Cookie
// w是http.ResponseWriter
if err := obj.Delete(w); err != nil {
// 处理错误
}
完整示例
package main
import (
"fmt"
"log"
"net/http"
"github.com/chmike/securecookie"
)
var key = securecookie.MustGenerateRandomKey()
var sc = securecookie.MustNew("session", key, securecookie.Params{
Path: "/",
MaxAge: 3600,
HTTPOnly: true,
Secure: false, // 开发环境设为false,生产环境设为true
})
func main() {
http.HandleFunc("/set/", setHandler)
http.HandleFunc("/val", getHandler)
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func setHandler(w http.ResponseWriter, r *http.Request) {
val := []byte(r.URL.Path[5:])
if err := sc.SetValue(w, val); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Cookie set with value: %s", val)
}
func getHandler(w http.ResponseWriter, r *http.Request) {
val, err := sc.GetValue(nil, r)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
fmt.Fprintf(w, "Cookie value: %s", val)
}
测试步骤:
- 创建目录并设置为工作目录:
mkdir /tmp/sctest; cd /tmp/sctest
- 创建
main.go
文件并复制上述代码 - 创建go.mod文件:
go mod init example.com
- 获取securecookie包:
go get github.com/chmike/securecookie@v1.2.0
- 运行服务器:
go run main.go
- 使用浏览器访问
http://localhost:8080/set/someValue
设置Cookie值 - 使用浏览器访问
http://localhost:8080/val
获取Cookie值
性能对比
指标 | Chmike | Gorilla |
---|---|---|
值长度 | 84 | 112 |
Set ns/op | 2393 | 6309 |
Get ns/op | 1515 | 5199 |
Set B/op | 350 | 2994 |
Get B/op | 192 | 2720 |
Set allocs/op | 3 | 35 |
Get allocs/op | 2 | 38 |
安全建议
- 安全仅限Cookie内容,不能证明其他数据是由用户请求创建的
- 考虑CSRF攻击风险,应为表单添加随机令牌验证
- 对于REST API,客户端和服务器应共享密钥计算HMAC值验证请求
securecookie提供了一种高效安全的方式来处理Cookie,适合需要保护Cookie内容的Web应用场景。
更多关于golang高效安全的Cookie编码解码插件库securecookie的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang高效安全的Cookie编码解码插件库securecookie的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang SecureCookie 使用指南
SecureCookie 是一个用于 Go 语言的库,它提供了安全编码和解码 Cookie 的功能,能够防止客户端篡改 Cookie 值。下面我将详细介绍如何使用这个库。
安装
go get github.com/gorilla/securecookie
基本用法
package main
import (
"fmt"
"net/http"
"github.com/gorilla/securecookie"
)
var (
// HashKey 用于认证 (32或64字节)
hashKey = securecookie.GenerateRandomKey(32)
// BlockKey 用于加密 (16, 24或32字节)
blockKey = securecookie.GenerateRandomKey(32)
s = securecookie.New(hashKey, blockKey)
)
func main() {
http.HandleFunc("/set", setCookieHandler)
http.HandleFunc("/get", getCookieHandler)
http.ListenAndServe(":8080", nil)
}
func setCookieHandler(w http.ResponseWriter, r *http.Request) {
value := map[string]string{
"foo": "bar",
}
if encoded, err := s.Encode("cookie-name", value); err == nil {
cookie := &http.Cookie{
Name: "cookie-name",
Value: encoded,
Path: "/",
Secure: true,
HttpOnly: true,
}
http.SetCookie(w, cookie)
}
fmt.Fprintln(w, "Cookie set!")
}
func getCookieHandler(w http.ResponseWriter, r *http.Request) {
if cookie, err := r.Cookie("cookie-name"); err == nil {
value := make(map[string]string)
if err = s.Decode("cookie-name", cookie.Value, &value); err == nil {
fmt.Fprintf(w, "Cookie value: %v", value)
}
} else {
fmt.Fprintln(w, "Cookie not found")
}
}
高级配置
自定义编码器
s := securecookie.New(hashKey, blockKey)
s.SetSerializer(securecookie.JSONEncoder{})
自定义哈希和加密算法
s := securecookie.New(hashKey, blockKey)
s.HashFunc(func() hash.Hash {
return sha256.New()
})
s.BlockFunc(func(block []byte) (cipher.Block, error) {
return aes.NewCipher(block)
})
设置最大年龄
s.MaxAge(86400) // 1天
安全最佳实践
-
密钥管理:
- 不要硬编码密钥
- 使用环境变量或配置管理系统
- 定期轮换密钥
-
Cookie设置:
- 始终设置
Secure
标志(HTTPS) - 使用
HttpOnly
防止JavaScript访问 - 设置适当的
Path
和Domain
- 始终设置
-
错误处理:
- 不要忽略解码错误
- 无效Cookie应被视为攻击尝试
完整示例
package main
import (
"log"
"net/http"
"os"
"github.com/gorilla/securecookie"
)
type User struct {
Name string
Email string
}
var (
hashKey = []byte(os.Getenv("COOKIE_HASH_KEY"))
blockKey = []byte(os.Getenv("COOKIE_BLOCK_KEY"))
sc = securecookie.New(hashKey, blockKey)
)
func main() {
http.HandleFunc("/login", loginHandler)
http.HandleFunc("/profile", profileHandler)
log.Println("Starting server on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
func loginHandler(w http.ResponseWriter, r *http.Request) {
user := User{
Name: "John Doe",
Email: "john@example.com",
}
encoded, err := sc.Encode("user", user)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
cookie := &http.Cookie{
Name: "user",
Value: encoded,
Path: "/",
MaxAge: 3600, // 1小时
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
}
http.SetCookie(w, cookie)
w.Write([]byte("Login successful"))
}
func profileHandler(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie("user")
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
var user User
if err = sc.Decode("user", cookie.Value, &user); err != nil {
http.Error(w, "Invalid cookie", http.StatusBadRequest)
return
}
w.Write([]byte("Welcome " + user.Name + " (" + user.Email + ")"))
}
注意事项
-
密钥长度必须正确:
- HashKey: 32或64字节
- BlockKey: 16(AES-128), 24(AES-192)或32(AES-256)字节
-
生产环境不要使用随机生成的密钥,应该使用固定的安全密钥
-
对于分布式系统,所有实例必须使用相同的密钥
SecureCookie 提供了一种简单而安全的方式来处理 Web 应用中的 Cookie,防止客户端篡改数据,是构建安全 Web 应用的重要工具之一。