最近在用thinkjs写自己的博客,发现总是掉到cookie的坑,于是就好好八一八这个小甜饼,没想到居然还说很有意思的,每一个知识点都能拉出一条大鱼,想想自己之前对cookie,简直就是它认识我,我只能叫出他的名字。
我将基于我自己的理解,使用原生koa2 + mysql来简单演示一下一些cookie的处理方案,有什么出岔子的地方,希望大家友好指正
1、cookie介绍
1.1 项目中cookie的使用场景
在实际的应用场景中,Cookie被用来做得最多的一件事是保持身份认证的服务端状态。比如登录状态的判断
1.2 为什么需要cookie呢?
敲黑板,HTTP是无状态协议,他不对之前发生过的请求和响应的状态进行管理。也就是每次服务器接收到请求后,并不知道请求到底用户是谁,
是否是登录态,这样服务端就懵逼了。cookie可以解决这个问题。如图,cookie的实现过程如下(盗了个图):
- 客户端向服务器发送HTTP Resuest
- 服务器接收到请求,在返回的HTTP Response响应头中加入set-cookie字段以及对应的cookie值
- 客户端接收到服务器的响应,解析出头部的set-cookie字段并将其中的cookie保存到本地
- 下次向服务器发送请求时, 会将cookie附加在HTTP请求的头字段Cookie中
- 服务器收到请求,判断cookie,便知道了发送请求的是客户端是谁了
我是一个jser,通过原生nodejs和浏览器调试工具看到每一个服务器和浏览器交互的细节。代码如下,欢迎交流并star:
https://github.com/LaputaGit/...
有兴趣的可以了解一下,运行一下代码,代码里面有详细的注释。
2、那么问题来了,你的cookie安全吗
首先,检测你的项目使用cookie有没有以下情况
- 能不能用js操作客户端cookie?
- 对于Cookie的域(Domain)和路径(Path)设置是如何制定策略的?为何这样划分?
- 在有SSL的应用中,你的Cookie是否可以在HTTP请求和HTTPS请求中通用?这一条暂时放放不介绍
我个人对于cookie的安全是这么理解的,我觉得cookie不是为安全而生的,所以没必要承担安全的责任,很多人拿cookie来做登录验证,包括我自己以前也这么搞过,而且搞得很简单。。。囧
来说一下cookie的安全性话题吧,谈到"为了cookie更安全",大概会做以下工作
- 设置httpOnly为true,来保证客户端无法操作cookie
设置secure为true- cookie在服务器以各种方式加密后,生成token
比如,用户发起登录 -> 服务器根据客户端的username, ip, expiration, useragent等组合信息,用可加密函数加密生成token,将此token保存到数据库,并将token写入cookie。
服务端验证流程: 客户端发来请求 -> 服务器解析出cookie中的token信息 -> 将token解密,验证客户端的username是否存在,如果存在 -> 验证token是否和数据库中的token相同,如果相同 -> 验证token的有效期expiration,如果有效 -> 验证ip是否变化,如果有效 -> 验证user agent等 …我们可以把很多的选项加入到cookie的加密中。
或者,有一些方案是把敏感信息交有后端session来保存,但是数据仍然放在cookie中,通过http传输
问题来了,不管你是通过cookie加密,或者是通过session包装敏感信息,这解决的是Cookie是可以被篡改的问题!这是个内部问题,可以发送HTTP请求的不只是浏览器,很多HTTP客户端软件,比如postman, paw等等,都可以发送任意的HTTP请求,可以设置任何头字段。 假如我们直接设置Cookie字段为authed=true
并发送该HTTP请求, 服务器岂不是被欺骗了?这种攻击非常容易,Cookie是可以被篡改的!
但是,这样是不能保证数据的安全性的,基于HTTP的cookie的传输是明文的,可以通过抓包获取数据,这个是传输层所决定的。这个才是cookie不安全的决定因素,不管你cookie如何加密,一旦我劫持到你的cookie,再把这个cookie原封不动地发送到服务器,退一步来说,即使加密,有时也可以通过一些手段破解,只要符合服务器cookie验证的规则,那么这个cookie是"合法的",自然就不安全了。
未完待续。。。后续会补上相关代码示例