Cookie、Session、Token
Cookie
Cookie 的定义
Cookie 是小量信息,由网络服务器发送出来以存储在网络浏览器上,从而当下次这位独一无二的访客又回到该网络服务器时,可从该浏览器读回此信息。这是很有用的,可以让浏览器记住这位访客的特定信息,如上次访问的位置、花费的时间或用户首选项(如样式表)。
Cookic是存储在浏览器目录的文本文件,当浏览器运行时,存储在 RAM 中。一旦从该网站或网络服务器退出,Cookie 也可存储在计算机的硬驱上。当访客结束其浏览器对话时,即终止所有 Cookie。
Cookie 四大要素:
Name / Value
:cookie 内容本身。Domain
:空间维度的安全性(限定共享范围,超出不可见)。Expires
:时间维度的安全性(限定共享时间,过期即销毁)。
使用 Cookie 的原因
Web 程序是使用 HTTP 进行传输的,而 HTTP 是无状态的协议,对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
Cookie 的产生
Cookie 的使用先要看需求。因为浏览器可以禁用 Cookie,同时服务端也可以不使用 Set-Cookie。
客户端向服务器端发送一个请求时,服务端向客户端发送一个 Cookie,然后浏览器将 Cookie 保存。Cookie 有两种保存方式:一种是浏览器会将 Cookie 保存在内存中;还有一种是保存在客户端的硬盘中,之后每次 HTTP 请求浏览器都会将 Cookie 发送给服务器端。
具体流程如下:
-
客户端提交一个 HTTP 请求给服务端
服务端这个时候做了两件事:一是 Set-Cookie;二是返回响应内容给客户端,客户端再次向服务器请求时会在请求头中携带一个 Cookie。 -
服务端提交响应内容给客户端
例如,可以分为登录前和登录后。登录前服务端给浏览器一个 Cookie,但是这个 Cookie 里面没有用户信息;但是登录成功之后,服务端给浏览器一个 Cookie,这个时候的 Cookie 已经记录了用户的信息,在系统内任意访问,可以实现免登录。
Cookie 的生存周期
Cookie 在生成时就会被指定一个 Expire 值,这就是 Cookie 的生存周期,在这个周期内 Cookie 有效,超出这个周期 Cookie 就会被清除。
有些页面将 Cookie 的生存周期设置为“0”或负值这样在关闭浏览器时,就马上清除 Cookie,不会记录用户信息,更加安全。
Cookie 的优缺点
优点:
-
Cookie 非常轻便,非常小,且对于服务端是没有任何压力的,因为是 cookie 存在浏览器里面,还可以设置失效时间,生效时间等。
-
客户端和服务端都能生成 cookie,它用来存放一些不敏感的数据,数据类型只能是字符串(json)。
缺点:
-
数量受到限制
一个浏览器能创建的 Cookie 数量最多为 300 个,并且每个不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20 个。 -
安全性无法得到保障
- Cookie 欺骗:Cookie 记录了用户的帐户 ID、密码之类的信息,通常使用 MD5 方法加密后在网上传递。经过加密处理后的信息即使被网络上一些别有用心的人截获也看不懂。然而,现在存在的问题是,截获 cookie 的人不需要知道这些字符串的含义,只要把别人的 cookie 向服务器提交,并且能够通过验证,就可以冒充受害人的身份登录网站,这种行为叫做 cookie 欺骗。非法用户通过 cookie 欺骗获得相应的加密密钥,从而访问合法用户的所有个性化信息,包括用户的 E-mail 甚至帐户信息,对个人信息造成严重危害。
- Cookie 截获:Cookie 以纯文本的形式在浏览器和服务器之间传送,很容易被他人非法截获和利用。任何可以截获 Web 通信的人都可以读取 cookie。Cookie 被非法用户截获后,然后在其有效期内重放,则此非法用户将享有合法用户的权益。例如,对于在线阅读,非法用户可以不支付费用即可享受在线阅读电子杂志。
-
浏览器可以禁用 Cookie
禁用 Cookie 后,也就无法享有 Cookie 带来的方便。
Session
Session 的定义及产生
在计算机中,尤其是在网络应用中,Session 称为“会话控制”。
Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。
当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。当会话过期或被放弃后,服务器将终止该会话。
简单地说,当登录一个网站的时候 如果 Web 服务器端使用的是 Session,那么所有的数据都保存在服务器上面,客户端每次请求服务器的时候会发送当前会话的 SessionID,服务器根据当前 SessionID 判断相应的用户数据标志,以确定用户是否登录,或具有某种权限。
由于数据是存储在服务器上面,所以不能伪造。
SessionID 是服务器和客户端连接时随机分配的,一般来说是不会有重复的,但如果有大量的并发请求,也不是没有重复的可能性。
Session 是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的 SessionID,用该 SessionID 为标识符来存取服务器端的 Session 存储空间。而 SessionID 这一数据则是保存到客户端,且用 Cookie 保存的,用户提交页面时,会将这一 SessionID 提交到服务器端,来存取 Session 数据。这一过程,是不用开发人员干预的。所以一旦客户端禁用 Cookie,那么 Session 也会失效。
Session 一般保存在服务器端的文件或数据库中,默认则保存在文件中,session 文件是公有的。目前还可以通过使用 redis 来保存 session 信息。
使用 Session 的原因
因为很多第三方可以获取到 Cookie,服务器无法判断 Cookie 是不是真实用户发送的,所以 Cookie 可能被伪造,比如可以伪造 Cookie 实现登录进行一些 HTTP 请求。
如果从安全性上来讲,Session 比 Cookie 安全性稍微高一些,客户端第一次请求服务器的时候,服务器会为客户端创建一个 Session,并将通过特殊算法算出一个 Session 的 ID,下次请求资源时(Session 未过期),浏览器会将 SessionID(实质是 Cookie)放置到请求头中,服务器接收到请求后就得到该请求的 SessionID,服务器找到该 ID 的 Session 返还给请求者使用。
Session 的生命周期
根据需求设定,一般来说为半小时。例如,登录一个服务器,服务器返回给一个 SessionlD 登录成功之后的半小时之内没有对该服务器进行任何 HTTP 请求,若半小时后进行一次 HTTP 请求,会提示重新登录。
Session 的缺陷
-
因为 Session 是存储在服务器当中的,所以 Session 过多,会对服务器产生压力(Session 的生命周期算是减少服务器压力的一种方式)。
-
当 Web 站点做了负载均衡时会遇到的问题:同一个用户的 Session 可能会请求到不同的 Web 应用服务器,而 Session 只认被产生的那台 Web 服务器。
Cookie 与 Session 的比较
- Cookie 保存在客户的浏览器上;Session 保存在服务器上(禁用 Cookie 后,Session 不能正常使用)。
- Session 比 Cookie 更具有安全性(服务器使用 session 技术把用户的信息临时保存在了服务器上,用户离开网站后其 session 会被销毁)。
- 单个 Cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 Cookie;而 Session 理论上是无限量的。
- Session 会在一定时间内保存在服务器上。当访问增多时会比较占用服务器资源;所以考虑到减轻服务器压力方面,应当使用 Cookie。
建议:将登录信息等重要信息存放为 Session;其他信息如果需要保留,可以放在 Cookie 中。
Token
Token 的定义
Token 是服务端生成的一串加密字符串
,以作为客户端进行请求的一个令牌。当第一次登录后,服务器生成一个 token 并将此返回给客户端,以后客户端只需带上这个 token 前来请求数据即可,无需再次带上用户名和密码。
Token 的目的
Token 技术主要是解决 session 的性能问题
。客户端登录成功之后 session 保存在内存。一台服务器的内存大小是固定的,当内存越满时,服务器的性能就越低。那怎么去解决的呢?就是这个 token。
Token 其实也是一个字符串,它最大的一个特点就是不会存储在服务器,还有一个特点就是不再依赖于 cookie 的形式,它可以是请求头或者是请求体的方式。而 Session 则依赖于 cookie,由服务器生成、存储和验证,并以 cookie 的方式存在于客户端,客户端以同样方式发送给服务端。
Session 有状态,Token 无状态。因此使用 Token 的话,服务器不需要保存会话状态,不用担心会话丢失,利用这种方式也方便部署分布式服务,将一个服务拆分成多个小服务,减轻单台服务器的压力。
基于 Token 的身份认证流程
-
首先客户端输入用户名、密码进行登录操作;
-
服务器验证用户名、密码的正确性,验证通过之后,服务器对一个 json 字符串进行加密,加密的内容、加密方法可以自己确定。然后将加密后的字符串(token)返回给客户端;
-
客户端需要自己将 token 保存起来,比如放在 Cookie 里或者 Local Storage 里;
-
接下来,客户端的每次请求都需要带上这个 token;
-
对于客户端的每次请求,服务器首先都要去获取 token,检查 token 是否合法,并解密 token 内容,检查 token 是否过期等。
Token 的优点
在 Web 领域,基于 token 的身份验证随处可见。在大多数使用 Web API 的互联网公司中(Facebook、Twitter、Google+、GitHub 等),token 是多用户下处理认证的最佳方式,其好处有:无状态、可扩展、支持移动设备、跨程序调用、安全等。
-
无状态、可扩展
在客户端存储的 token 是无状态的,并且能够被扩展。基于这种无状态和不存储 session 信息,负载均衡服务器能够将用户信息从一个服务传到其他服务器上。如果我们将已验证的用户的信息保存在 session 中,则每次请求都需要用户向已验证的服务器发送验证信息(称为 session 亲和性)。当用户量大时,可能会造成一些拥堵。而使用 token 之后这些问题都迎刃而解,因为 token 自己 hold 住了用户的验证信息。 -
安全性
- 在整个过程中是没有用户名和密码的传递的,不会存在密码被盗用的风险。
- 对于自己的系统来说,不会让第三方公司知道自己的加密策略或手段,因为生成 token 和验证 token 的过程都是在自己系统上进行,第三方系统并不关心这个过程是如何进行的,只需要返回一个验证结果就行了。
- 比较担心的是如果 token 可以从别的地方(如浏览器的 cookie 中)被拦截获取,就可以用来冒充登录了呢?分情况讨论吧:
- 首先一般这个 token 是一串很长的字符串,凭肉眼记忆几乎是不可能的。被盗的情况很可能是电脑中病毒了,从而请求被拦截并获取盗这些参数。对于内网环境、或者安全级别比较高的办公环境来说,这种中病毒的可能性很小;
- Token 往往具有时效性、一般有效期在 2~3 分钟(每个厂子的安全策略不同,控制的时间也不同),即使被拷贝给其他人,很快也会失效;
- 更高级的做法,就是 One-Time Token(一次性令牌),即 token 只能检验一次,然后就会被回收,这样几乎不存在泄露的问题。
-
多平台、跨域
CORS(跨域资源共享),对应用程序和服务进行扩展的时候,需要介入各种的设备和应用程序。只要用户有一个通过了验证的 token,数据和资源就能够在任何域上被请求到。 -
基于标准
创建 token 的时候,你可以设定一些选项,标准的用法会在 JSON Web Token 体现,它支持众多的语言。这意味在未来的使用中你可以真正地转换你的认证机制。
Token 的应用场景
-
身份验证。
-
单点登录:单点登录(Single Sign On)简称为 SSO,在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
-
Anti CSRF(防跨站请求伪造):防止别的站点伪造你的请求。
-
防止表单重复提交:解决方案可以是将 session 和 token 套用。首先 Session 可以始终保证请求是来自同一个对象,而不是多个对象,而在服务器端第一次验证 token 相同后,会将 session 中的 token 值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的 token 没变,但服务器端 session 中 token 已经改变了。