// 定义了cookie结构体,以及各个字段的判断合法方法,以及解析cookie和生成cookie的方法
// 一个Cookie实例 表示在HTTP响应的Set-Cookie头或HTTP请求的Cookie头中发送的HTTP Cookie
type Cookie struct {
Name string
Value string
Path string // optional
Domain string // optional // 范围
Expires time.Time // optional // 过期时间
RawExpires string // for reading cookies only // 可读过期时间
MaxAge int // 0表示未指定,<0表示立即删除cookie,存在和给定的最大年龄属性(以秒为单位)
Secure bool // 是否安全
HttpOnly bool // 是否仅http携带
SameSite SameSite // 相同网址,int
Raw string
Unparsed []string // 原始未解析文本
}
// SameSite允许服务器定义cookie属性,使得浏览器无法将此cookie与跨站点请求一起发送。 其主要目标是降低跨源信息泄漏的风险,并提供一些针对跨站点请求伪造攻击的保护。
type SameSite int // 默认模式1,lax模式2,Strict模式3,None模式4
const (
SameSiteDefaultMode SameSite = iota + 1
SameSiteLaxMode
SameSiteStrictMode
SameSiteNoneMode
)
// readSetCookies 解析Header中的所有“Set Cookie”值
// "Set Cookie" 用于把cookie 发送到客户端浏览器, 每一个写入cookie都会生成一个Set-Cookie.
func readSetCookies(h Header) []*Cookie {
cookieCount := len(h["Set-Cookie"])
if cookieCount == 0 {
return []*Cookie{
}
}
cookies := make([]*Cookie, 0, cookieCount)
for _, line := range h["Set-Cookie"] {
parts := strings.Split(textproto.TrimString(line), ";")
if len(parts) == 1 && parts[0] == "" {
continue
}
parts[0] = textproto.TrimString(parts[0])
j := strings.Index(parts[0], "=")
if j < 0 {
continue
}
name, value := parts[0][:j], parts[0][j+1:]
if !isCookieNameValid(name) {
continue
}
value, ok := parseCookieValue(value, true)
if !ok {
continue
}
c := &Cookie{
Name: name,
Value: value,
Raw: line,
}
for i := 1; i < len(parts); i++ {
parts[i] = textproto.TrimString(parts[i])
if len(parts[i]) == 0 {
continue
}
attr, val := parts[i], ""
if j := strings.Index(attr, "="); j >= 0 {
attr, val = attr[:j], attr[j+1:]
}
lowerAttr := strings.ToLower(attr)
val, ok = parseCookieValue(val, false)
if !ok {
c.Unparsed = append(c.Unparsed, parts[i])
continue
}
switch lowerAttr {
case "samesite":
lowerVal := strings.ToLower(val)
switch lowerVal {
case "lax":
c.SameSite
golang源码解读之http.cookie
最新推荐文章于 2023-03-03 17:58:12 发布