什么是Cookie
Cookie(也叫Web Cookie或浏览器Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie使基于无状态的HTTP协议记录稳定的状态信息成为了可能。
Cookie主要用于以下三个方面:
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
Go语言如何表示Cookie
在Go的net/http库中使用http.Cookie结构体表示一个Cookie数据,调用http.SetCookie函数则会告诉终端用户的浏览器把给定的http.Cookie值设置到浏览器Cookie里,类似下面:
func someHandler(w http.ResponseWriter, r *http.Request) { c := http.Cookie{ Name: "UserName", Value: "Casey", } http.SetCookie(w, &c) }
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=0 means no 'Max-Age' attribute specified. // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0' // MaxAge>0 means Max-Age attribute present and given in seconds MaxAge int Secure bool HttpOnly bool SameSite SameSite Raw string Unparsed []string // Raw text of unparsed attribute-value pairs }
Name和Value字段就不多说了,单独针对几个需要解释的字段进行说明。
Domain
默认值是当前正在访问的Host的域名,假设我们现在正在访问的是www.example.com,如果需要其他子域名也能够访问到正在设置的Cookie值的话,将它设置为example.com 。注意,只有正在被设置的Cookie需要被其他子域名的服务访问到时才这么设置。
c := Cookie{ ...... Domain: "example.com", }
Path
设置当前的 Cookie 值只有在访问指定路径时才能被服务器程序读取。默认为服务端应用程序上的任何路径,但是您可以使用它限制为特定的子目录。例如:
c := Cookie{ Path: "/app/", }
Secure
标记为Secure 的Cookie只应通过被HTTPS协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过Cookie传输,因为Cookie有其固有的不安全性,Secure 标记也无法提供确实的安全保障。从 Chrome 52 和 Firefox 52 开始,不安全的站点(http:)无法使用Cookie的 Secure 标记。
HttpOnly
为避免跨域脚本 (XSS) 攻击,通过JavaScript的API无法访问带有 HttpOnly 标记的Cookie,它们只应该发送给服务端。如果包含服务端Session 信息的Cookie 不想被客户端JavaScript 脚本调用,那么就应该为其设置 HttpOnly 标记。
安全地传输Cookie
接下来我们探讨两种安全传输Cookie的方法
对Cookie数据进行数字签名
对数据进行数字签名是在数据上添加“签名”的行为,以便可以验证其真实性。不需要对数据进行加密或屏蔽。
签名的工作方式是通过散列-我们对数据进行散列,然后将数据与数据散列一起存储在Cookie中。然后,当用户将Cookie发送给我们时,我们再次对数据进行哈希处理,并验证其是否与我们创建的原始哈希匹配。
我们不希望用户也用篡改后的数据创建新的哈希,因此经常会看到使用HMAC之类的哈希算法,以便可以使用密钥对数据进行哈希。这样可以防止最终用户同时编辑数据和数字签名(哈希)。
JWT也是使用的这种数字签名的方式进行传输的。
上面的数据签名过程并不需要我们自己去实现,我们可以在Go中使用gorilla/securecookie的程序包来完成此操作,在该程序包中,你可以在创建SecureCookie时为其提供哈希密钥,然后使用该对象来保护你的Cookie。
对Cookie数据进行签名:
//var s = securecookie.New(hashKey, blockKey) var hashKey = securecookie.GenerateRandomKey(64) var s = securecookie.New(hashKey, nil) func SetCookieHandler(w http.ResponseWriter, r *http.Request) { encoded, err := s.Encode("cookie-name", "cookie-value") if err == nil { cookie := &http.Cookie{ Name: "cookie-name", Value: encoded, Path: "/", } http.SetCookie(w, cookie) fmt.Fprintln(w, encoded) }
解析被签名的 Cookie:
func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { if cookie, err := r.Cookie("cookie-name"); err == nil { var value string if err = s.Decode("cookie-name", cookie.Value, &value); err == nil { fmt.Fprintln(w, value) } } }
注意这里的Cookie数据未加密,仅仅是被编码了,任何人都可以把Cookie数据解码回来。
加密Cookie 数据
每当将数据存储在Cookie中时,请始终尽量减少存储在Cookie中的敏感数据量。不要存储用户密码之类的东西,并确保任何编码数据也没有此信息。在某些情况下,开发人员在不知不觉中将敏感数据存储在Cookie或JWT中,因为它们是base64编码的,但实际上任何人都可以解码该数据。它已编码,未加密。
这是一个很大的错误,因此,如果你担心意外存储敏感内容,建议 你使用gorilla/securecookie之类的软件包。
之前我们讨论了如何将其用于对Cookie进行数字签名,但是securecookie也可以用于加密和解密Cookie数据,以使其无法轻松解码和读取。
要使用该软件包加密Cookie,只需在创建SecureCookie实例时传入一个blockKey即可。
将上面签名Cookie的代码片段进行一些小改动,其他地方完全不用动,securecookie包会帮助我们进行Cookie的加密和解密:
var hashKey = securecookie.GenerateRandomKey(64) var blockKey = securecookie.GenerateRandomKey(32) var s = securecookie.New(hashKey, blockKey)
总结
今天的文章除了阐述如何使用Go语言安全地传输Cookie数据外,再次格外强调一遍,编码和加密的不同,从数据可读性上看,两者差不多,但本质上是完全不一样的:
- 编码使用公开可用的方案将数据转换为另一种格式,以便可以轻松地将其反转。
- 加密将数据转换为另一种格式,使得只有特定的个人才能逆转转换。
我们在做数据传输时一定要记住两者的区别,某种意义上,我觉得记住这两点的区别比你学会今天文章里怎么安全传输Cookie更重要。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 中国武警男声合唱团《辉煌之声1天路》[DTS-WAV分轨]
- 紫薇《旧曲新韵》[320K/MP3][175.29MB]
- 紫薇《旧曲新韵》[FLAC/分轨][550.18MB]
- 周深《反深代词》[先听版][320K/MP3][72.71MB]
- 李佳薇.2024-会发光的【黑籁音乐】【FLAC分轨】
- 后弦.2012-很有爱【天浩盛世】【WAV+CUE】
- 林俊吉.2012-将你惜命命【美华】【WAV+CUE】
- 晓雅《分享》DTS-WAV
- 黑鸭子2008-飞歌[首版][WAV+CUE]
- 黄乙玲1989-水泼落地难收回[日本天龙版][WAV+CUE]
- 周深《反深代词》[先听版][FLAC/分轨][310.97MB]
- 姜育恒1984《什么时候·串起又散落》台湾复刻版[WAV+CUE][1G]
- 那英《如今》引进版[WAV+CUE][1G]
- 蔡幸娟.1991-真的让我爱你吗【飞碟】【WAV+CUE】
- 群星.2024-好团圆电视剧原声带【TME】【FLAC分轨】