Cookie 工具 (cookieutil)
Cookie 工具 (cookieutil)
带安全默认值的认证 Cookie 与 CSRF double-submit 防护
cookieutil
带安全默认值的认证 Cookie 下发与 CSRF 防护,配套 Cookie 登录认证方案(禁止 localStorage 存凭证)。
安全基线:
- 认证 Cookie 强制 HttpOnly(调用方无法关闭),防 XSS 窃取
- 默认
Path=/、SameSite=Lax;生产环境应设置Secure: true - CSRF 采用 double-submit:随机 token 同时写入可读 Cookie 与请求头,服务端恒定时间比较
函数签名
type Options struct {
Domain string
Path string // 默认 "/"
Secure bool // 生产必须 true
SameSite http.SameSite // 默认 Lax
MaxAge time.Duration // <=0 为会话 Cookie
}
func SetAuth(w http.ResponseWriter, name, value string, opts Options)
func Clear(w http.ResponseWriter, name string, opts Options)
func NewCSRFToken() (string, error)
func SetCSRF(w http.ResponseWriter, token string, opts Options)
func ValidateCSRF(r *http.Request) bool
func ValidateCSRFNames(r *http.Request, cookieName, headerName string) bool登录下发
func loginHandler(w http.ResponseWriter, r *http.Request) {
sid := createSession(user)
opts := cookieutil.Options{Secure: true, MaxAge: 7 * 24 * time.Hour}
cookieutil.SetAuth(w, "session_id", sid, opts) // HttpOnly 强制开启
token, _ := cookieutil.NewCSRFToken()
cookieutil.SetCSRF(w, token, opts) // 特意可读, 前端取出放请求头
resputil.OK(w, nil)
}写操作校验 CSRF
func csrfMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet && r.Method != http.MethodHead {
if !cookieutil.ValidateCSRF(r) { // Cookie csrf_token vs 请求头 X-CSRF-Token
resputil.FailStatus(w, 403, 40300, "CSRF 校验失败")
return
}
}
next.ServeHTTP(w, r)
})
}前端配合:读取 csrf_token Cookie,写操作请求带 X-CSRF-Token 请求头。
登出清除
cookieutil.Clear(w, "session_id", opts) // Domain/Path 须与下发时一致