-
Notifications
You must be signed in to change notification settings - Fork 3
/
new.go
131 lines (111 loc) · 3.2 KB
/
new.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package cookieKit
import (
"github.com/richelieu-yang/chimera/v3/src/core/strKit"
"github.com/richelieu-yang/chimera/v3/src/urlKit"
"net/http"
)
type (
options struct {
// Path 可以为""(此时将采用默认值"/")
Path string
// Domain 可以为""(此时为对应url的hostname,可能是ip)
Domain string
// MaxAge
/*
(1) > 0: 表示此cookie从创建到过期所能存在的时间,以秒为单位
(2) == 0: 存储在浏览器进程中,进程退出cookie就会消失
(3) < 0: 删除此cookie(一般用-1)
*/
MaxAge int
// Secure
/*
true: 浏览器只会在https、SSL等安全协议中传输此Cookie,不会在不安全的HTTP协议中传输此Cookie
false: 此Cookie在所有协议中传输
*/
Secure bool
// HttpOnly
/*
true: 不能被js检测到(读||写),发送请求时依旧会携带此Cookie(允许的话)。
false: 能被js检测到(读||写),发送请求时依旧会携带此Cookie(允许的话)
*/
HttpOnly bool
// SameSite
/*
http.SameSiteDefaultMode: 默认值
http.SameSiteStrictMode: Scrict最为严格,完全禁止第三方Cookie,跨站点时,任何情况下都不会发送Cookie。
http.SameSiteLaxMode: Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
http.SameSiteNoneMode: 网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。
*/
SameSite http.SameSite
}
CookieOption func(*options)
)
func WithPath(path string) CookieOption {
return func(opts *options) {
opts.Path = path
}
}
func WithDomain(domain string) CookieOption {
return func(opts *options) {
opts.Domain = domain
}
}
func WithMaxAge(maxAge int) CookieOption {
return func(opts *options) {
opts.MaxAge = maxAge
}
}
func WithSecure(secure bool) CookieOption {
return func(opts *options) {
opts.Secure = secure
}
}
func WithHttpOnly(httpOnly bool) CookieOption {
return func(opts *options) {
opts.HttpOnly = httpOnly
}
}
func WithSameSite(sameSite http.SameSite) CookieOption {
return func(opts *options) {
opts.SameSite = sameSite
}
}
func loadOptions(cookieOptions ...CookieOption) *options {
opts := &options{
Path: "/",
Domain: "",
MaxAge: 0,
Secure: false,
HttpOnly: false,
SameSite: http.SameSiteDefaultMode,
}
for _, option := range cookieOptions {
option(opts)
}
// 参考: gin.Context.SetCookie()
opts.Path = strKit.BlankToDefault(opts.Path, "/")
return opts
}
// NewCookie
/*
e.g. 跨域情况下,iframe页面(子页面)设置cookie失败的一种解决方法
满足以下条件:
(1) WithSameSite(http.SameSiteNoneMode)
(2) WithSecure(true)
(3) https协议
*/
func NewCookie(name, value string, cookieOptions ...CookieOption) *http.Cookie {
opts := loadOptions(cookieOptions...)
cookie := &http.Cookie{
Name: name,
Value: urlKit.EncodeURIComponent(value),
Path: opts.Path,
Domain: opts.Domain,
MaxAge: opts.MaxAge,
Secure: opts.Secure,
HttpOnly: opts.HttpOnly,
SameSite: opts.SameSite,
}
SetCookieMaxAge(cookie, opts.MaxAge)
return cookie
}