一、Cookie的基本概念
1.什么是Cookie
CookieWeb CookieCookieCookie
Cookie
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
2.Go语言如何表示Cookie
Gonet/httphttp.CookieCookiehttp.SetCookiehttp.CookieCookiehttp.Cookie
大概用法如下:
Cookie的各个字段意义如下:
Domain
Hostwww.example.comCookieexample.comCookie
Path
设置当前的 Cookie 值只有在访问指定路径时才能被服务器程序读取。默认为服务端应用程序上的任何路径,但是您可以使用它限制为特定的子目录。例如:
Secure
SecureHTTPSSecureCookieCookieSecure http:CookieSecure
HttpOnly
JavaScriptHttpOnlySessionCookieJavaScriptHttpOnly
二、Cookie的使用
1.设置cookie:
2.读取cookie:
3.删除cookie
4.具体使用例子:
三、Cookie的数据安全传输
Cookie
1.对Cookie数据进行数字签名
数字签名是对数据添加一个签名,以便验证其真实性。终端用户无需对数据进行加密或做掩码,但是我们需要向 cookie 添加足够的数据,这样如果用户更改了数据的话,我们能够检测出来。
通过哈希来实现这个方案——会对数据进行 hash,然后将数据和数据的哈希值都存到 cookie 中。之后当用户发送 cookie 给我们,我们会对数据再次做哈希,验证是否和之前的哈希值匹配。
我们也不希望用户创建新的哈希值,所以你通常会看到使用 HMAC 这类哈希算法,通过一个密钥对数据做哈希。防止用户同时修改数据以及数字签名(哈希值)。对数据进行数字签名是在数据上添加“签名”的行为,以便可以验证其真实性。不需要对数据进行加密或屏蔽。
CookieCookie
HMAC
JWT
SecureCookieCookie
Cookie
解析被签名的 Cookie:
CookieCookie
这里有个非常重要的警告:对于同时往数字签名的数据中添加用户信息和过期时间的情况,如果用上述方法保证可靠性,你必须非常小心,严格遵守 JWT 的使用模式。不能单单依赖 cookie 的过期时间,因为该日期未被加密,用户可以创建一个新的没有过期时间的 cookie,然后把 cookie 签名的部分拷贝过去,基本上就是创建了一个保证他们永久在线的 cookie。
2.加密Cookie 数据
CookieCookieCookieJWTbase64
gorilla/securecookie
CookiesecurecookieCookie
CookieSecureCookieblockKey
CookiesecurecookieCookie
3. 混淆数据
另外一种方式是对数据做掩码,确保用户无法伪造数据。例如,不要像如下方式一样保存 cookie:
remember_tokens
然后就可以只在 cookie 中保存记录 token,这样即便用户想要伪造,也不知道要改什么。它看起来就像乱码。
后面当用户访问我们的应用,我们会在数据库中查找其记录 token,然后判断是哪个用户登录了。
为了使该方案能够运行,你需要确保混淆数据是 :
- 映射到了一个用户(或者其他资源)
- 随机的
- 熵值较高
- 可以设为失效状态(例如,删除 / 改变 DB 中保存的 token)
这个方法的一个缺点是,对于每个需要验证用户身份的页面请求,都需要进行数据库查询,不过这个缺点一般不会被注意到,可以通过缓存或其他类似技术解决掉。该方法相对 JWT 的优点是你可以快速废弃 session。
这是我知道的最常见的验证策略,尽管 JWT 最近在所有的 JS 框架得到流行。
4.数据泄露(Data leaks)
像 cookie 盗用一样,在成为真正的威胁之前,数据泄露通常需要有其他的攻击途径,不过谨慎一些总是好的。也是因为,cookie 被盗并不意味着我们想要故意告诉黑客用户密码。
无论何时往 cookie 中保存数据,都要尽可能减少存储敏感数据的量。不要存储用户的密码,确保编码过得数据中也没有密码。类似这篇 文章指出的几个例子,开发者不知不觉地在 cookie 或者 JWT 中保存了敏感数据,采用 base64 编码,但实际上任何人都可以解码该数据。数据是被编码了,而不是加密了。
securecookie
SecureCookie
其他和文章数字签名部分例子类似。
还是要着重强调下,不要在 cookie 中保存任何敏感的数据;尤其不要存密码。加密简单来说就是让内容更加安全一点的方法,防止有半敏感数据出现在 cookie 中。
5.跨站脚本(Cross-site scripting(XSS))
跨站脚本,通常写做 XSS,黑客尝试向你的网站注入你没有写的 Javascript,但是由于攻击起作用的方式浏览器不知道,所以会像运行你服务器提供的代码一样运行。
通常,你需要尽最大的能力阻止 XSS 攻击,这里不会讨论 XSS 的过多细节,但以防蒙混过关,我建议不需要访问 cookie 的 JavaScript 代码就禁止其权限。之后如果有需要的话,可以在启用,所以这不是写低可靠性代码的理由。
HttpOnly
6.跨站请求伪造(CSRF(Cross Site Request Forgery))
当用户访问一个不是你的网站,但是那个网站有一个表单提交到你的 Web 应用时候,可能会发生 CSRF。由于终端用户提交了表单且不是通过脚本提交的,浏览器会视为用户触发行为,在提交表单的同时传输 cookie 过去。
开始,这看起来并不坏,但如果外部网站发送非用户想要的数据呢?例如,badsite.com 可能有一个表单提交一个要求转 ¥ 100 到他们银行账户的请求,该请求会被发到 chase.com,你可能会在那里登录银行账户,这可能导致钱在未经用户允许情况下被转移。
cookie 本身并没有什么错,但是如果你用 cookie 做一些验证工作,你就需要 Gorilla 的csrf 包。
csrf
有关 CSRF 的更多内容,请看如下内容:
7.限制访问 cookie
最后要讨论的和特定的攻击没有关系,更多的是一种使用 cookie 的指导性原则:尽量限制对 cookie 的访问,只在给需要的地方提供访问权限。
前面只在讨论 XSS 的地方简单的提及到了这一点,但是其实你应该在任何地方限制对 cookie 的访问。例如,如果你的 Web 应用不使用子域名,那么就没有理由提供所有子域名访问 cookie 的权限。cookie 默认就是限制子域名的,所以实际上,你不需要做任何事情去限制特定的域名。
另一方面,如果你确实要和子域名共享 cookie,那么可以这么做:
除了指定域名外,你也可以对指定路径限制 cookie。
/blah
为什么不直接用 JWT ?
这个问题没法逃避,这里简单的解释一下。
尽管有很多人可能会告诉你,cookie 可以像 JWT 一样安全。实际上,JWT 和 cookie 解决的都不是一类问题,因为 JWT 可以存在 cookie 中,实质上和提供 header 的使用方式一样。
不管怎样,cookie 可以用于非验证数据,即便在这些案例中,了解适当的安全措施也是有用的。
总结
GoCookie
- 编码使用公开可用的方案将数据转换为另一种格式,以便可以轻松地将其反转。
- 加密将数据转换为另一种格式,使得只有特定的个人才能逆转转换。
Cookie