一、HTTP Cookie
1.1 为什么要有 cookie?
假设现在在浏览一个视频网站。有些视频是不登陆就可以看的,有些视频需要登陆,还有一些是 VIP 才可以看得。比如你现在是 VIP,你点击一个视频,实际上就是向服务器请求了一个资源。但是服务器怎样判断是否能够给你这个资源呢?这就需要进行用户鉴权。
我们使用的用户层 HTTP协议,是无连接、无状态的,那么我们需要每次都鉴权。说着容易,只需要每次提供用户名、密码就可以。但是难道每点击一个视频都让你输一个密码吗?从实际体验上来说,当然不是。很多网站,登陆过一次之后,即使是新标签页,也能够直接完成登陆;从时间维度,有可能半年后再登陆都还能够直接登陆成功,这就是 cookie 的作用
1.2 什么是 cookie?
cookie 其实就是服务端发送到浏览器的一个数据块,有浏览器进行保存。这个数据块中,保存着用户名、密码等用户鉴权信息。
第一次浏览器与服务器进行连接时,服务端会在返回报文的 Set-Cookie 字段中,设置 cookie 中应该具有的信息。浏览器会对服务端返回的 cookie 进行保存。再次请求时,只需要在自己 HTTP 报头的 Cookie 字段放入保存的 cookie 信息,服务端就可以完成用户的鉴权。
这里的"保存",分为两种方式:
- 到文件的持久化保存,一般是通过类似于
SQLite通过二进制的形式保存,虽然直接看是无法解读的,但是这种方式是可以截取 cookie 中的私密信息的 - 只在会话中有效,即在内存中保存 cookie,不持久化到文件。浏览器关闭,这些 cookie 也就失效了
在 cookie 中,基本格式如下
Set-Cookie: <name>=<value>
其中,name 提供设置的字段,常用的主要有以下几个
username,指定 cookie 的名称和值,同时对用户名进行标识expires,指定过期时间,有明确的格式要求,如Tue, 01 Jan 2030 12:34:56 GMT(UTC)path,指定 cookie 的作用范围。如果设置为网站根目录的话,那么就表示 cookie 在所有路径都有效;如果是某个特定的目录,比如/a/b,就表示访问 '/a/b' 目录下的资源时,浏览器才会随请求报头发送 cookie 信息HttpOnly,机制 JavaScript 等读取 CookieSecure,是否只在使用 HTTPS 这种加密请求时才携带 Cookie
1.3 cookie 安全性
虽然一般 cookie 会由浏览器二进制保存。但是,由 cookie 的原理我们不难得出一个结论:cookie 鉴权的其实不是用户,而是"文件"------只要你能提供这样的 cookie,服务端就认为你是这样的用户。所以哪怕不能直接从 cookie 中获得明文的用户信息,我也能直接把这个 cookie 文件放到我自己的浏览器的相应位置,浏览器在把 cookie 放到报头中,这不就完成了用户信息的窃取或者说"盗号"了吗?(先不考虑实际的服务端的其他机制)
一方面,可以将防御和业务绑定。比如上一秒用户再上海登陆,下一秒在美国登陆,这样服务端就可以把这个用户标记为异常,下次再请求时不认 cookie,而是通过比如让用户做人脸识别;另一方面,更加安全的,我们可以引入 session
二、HTTP Session
引入了 session 机制后,在第一次请求时,服务端不再返回包含各种用户信息的 Cookie,而是只在 Cookie 里放一个 session_id。现在,在浏览器的 cookie 里只放一个 session_id,后续请求依旧会携带 cookie。服务器在再次接受到请求时,会检查 session_id 是否合法,如果合法的话,就在本地存储的信息中获得用户信息进行处理。
从效果上来讲,可以认为 Session 机制建立在 cookie 之上,使得原来浏览器保存的完整用户隐私数据的 cookie 保存在了服务端,浏览器现在保存的 cookie 只是一个获得这些数据的钥匙。因此 cookie 泄漏了,也不至于导致用户信息的全部泄漏
但是一方面,Session 也没有解决 session_id 在浏览器泄漏的问题;另一方面,用户元信息存储在服务器,对于服务器的存储能力和检索能力也提供了要求(可以引入比如 Redis)