Cookie、Session和Token

前言:新公司项目中使用到了Cookie,在各大Android技术讨论群向前辈们取经讨论这cookie、session、token这仨哥们的时候,很多开发者说法不一各抒已见,所以是时候回顾下http基础以及总结开发经验了。本文重在科普分析Cookie、Session、Token的基本概念和应用场景;Okhttp框架下对Cookie的管理使用。文章如果写的不好请各位开发者老司机私聊或者在评论区指点提出issue。

前言

Cookie是在客户端保存状态的方式

一、Session

Web诞生之初,功能比较单一:允许Internet上任意一个用户都可以从许多文档服务计算机的数据库中搜索和获取文档。服务器不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议,
即请求加响应,服务器不用记住是谁刚刚发了HTTP请求,
每个请求对服务器来说都是全新的。

Cookie 技术产生源于 HTTP
协议在互联网上的急速发展。随着互联网时代的策马奔腾,带宽等限制不存在了,人们需要更复杂的互联网交互活动,就必须同服务器保持活动状态。于是,在浏览器发展初期,为了适应用户的需求技术上推出了各种保持
Web 浏览状态的手段
,其中就包括了 Cookie 技术。Cookie
在计算机中是个存储在浏览器目录中的文本文件,当浏览器运行时,存储在 RAM
中发挥作用 (此种 Cookies 称作 Session
Cookies),一旦用户从该网站或服务器退出,Cookie 可存储在用户本地的硬盘上
(此种 Cookies 称作 Persistent Cookies)。

Web诞生之初,功能比较单一:允许Internet上任意一个用户都可以从许多文档服务计算机的数据库中搜索和获取文档。服务器不需要记录谁在某一段时间里都浏览了什么文档,每次请求都是一个新的HTTP协议,
即请求加响应,服务器不用记住是谁刚刚发了HTTP请求,
每个请求对服务器来说都是全新的。

Session是在服务器端保存状态的方式

Session是什么

随着交互式Web应用的兴起,网站有了登录的需求,如在线购物网站,社交网站等等。这就面临一个问题,服务器必须记住哪些人登录了系统,
哪些人往自己的购物车中添加了商品, 也就是说服务器要识别每个用户。

Cookie 起源:1993 年,网景公司雇员 Lou Montulli
为了让用户在访问某网站时,进一步提高访问速度,同时也为了进一步实现个人化网络,发明了今天广泛使用的
Cookie。(所以,适当的偷懒也会促进人类计算机发展史的一小步~)

随着交互式Web应用的兴起,网站有了登录的需求,如在线购物网站,社交网站等等。这就面临一个问题,服务器必须记住哪些人登录了系统,
哪些人往自己的购物车中添加了商品, 也就是说服务器要识别每个用户。

登录信息等不要保存在Cookie上,因为Cookie保存在客户端,容易被研究伪造

Session实际上是一个特定的时间概念,Web中的Session指的就是用户在浏览某个网站时,从进入网站到关闭这个网站所经过的这段时间,也就是用户浏览这个网站所花费的时间。

因为HTTP请求是无状态的,所以想出的办法就是给大家发一个会话标识(session
id)
, 说白了就是一个随机的字串,每个用户收到的都不一样。
当用户向服务器发起HTTP请求的时候,带上这个字符串,
这样服务器就能识别不同的用户了。

Cookie时效性:目前有些 Cookie 是临时的,有些则是持续的。临时的
Cookie 只在浏览器上保存一段规定的时间,一旦超过规定的时间,该 Cookie
就会被系统清除。

因为HTTP请求是无状态的,所以想出的办法就是给大家发一个会话标识(session
id), 说白了就是一个随机的字串,每个用户收到的都不一样。
当用户向服务器发起HTTP请求的时候,带上这个字符串,
这样服务器就能识别不同的用户了。

但是Session和Cookie都不能避免被劫持的风险

Session代表服务器与浏览器的一次会话过程,这个过程是连续的,也可以时断时续的

所以就有了Session的引入,即服务端和客户端都保存一段文本,客户端每次发起请求都带着,这样服务器就知道客户端是否发起过请求。

Cookie使用限制:Cookie 必须在 HTML
文件的内容输出之前设置;不同的浏览器 (Netscape Navigator、Internet
Explorer) 对 Cookie
的处理不一致,使用时一定要考虑;客户端用户如果设置禁止 Cookie,则 Cookie
不能建立。 并且在客户端,一个浏览器能创建的 Cookie 数量最多为 300
个,并且每个不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20
个。

所以就有了Session的引入,即服务端和客户端都保存一段文本,客户端每次发起请求都带着,这样服务器就知道客户端是否发起过请求。

Token则是用来验证身份和防止跨站请求的令牌,客户端每次向服务器请求更改的时候都要带上这个Token,下一次服务器则签发新的Token,不存在更改的页面请求不需要Token。

Session的创建

这样,就导致客户端频繁向服务端发出请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否。而Session的存储是需要空间的,频繁的查询数据库给服务器造成很大的压力。

执行流程:

这样,就导致客户端频繁向服务端发出请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否。而Session的存储是需要空间的,频繁的查询数据库给服务器造成很大的压力。

当JSP页面没有显式禁止session的时候,在打开浏览器第一次请求该jsp的时候,服务器会自动为其创建一个session,并赋予其一个sessionID,发送给客户端的浏览器。以后客户端接着请求本应用中其他资源的时候,会自动在请求头上添加:

随着Web移动端的兴起,这种验证的方式逐渐暴露出了问题。尤其是在可扩展性方面。

A:首先,客户端会发送一个http请求到服务器端。

随着Web移动端的兴起,这种验证的方式逐渐暴露出了问题。尤其是在可扩展性方面。

Cookie:JSESSIONID=客户端第一次拿到的session ID

基于服务器验证方式暴露的一些问题

B:
服务器端接受客户端请求后,发送一个http响应到客户端,这个响应头,其中就包含Set-Cookie头部。

基于服务器验证方式暴露的一些问题

这样,服务器端在接到请求时候,就会收到session
ID,并根据ID在内存中找到之前创建的session对象,提供给请求使用。

1.Seesion:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。

C:在客户端发起的第二次请求(注意:如果服务器需要我们带上Cookie,我们就需要在B步骤上面拿到这个Cookie然后作为请求头一起发起第二次请求),提供给了服务器端可以用来唯一标识客户端身份的信息。这时,服务器端也就可以判断客户端是否启用了cookies。尽管,用户可能在和应用程序交互的过程中突然禁用cookies的使用,但是,这个情况基本是不太可能发生的,所以可以不加以考虑,这在实践中也被证明是对的。

1.Seesion:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。当越来越多的用户发请求时,内存的开销也会不断增加。

Session的删除

2.可扩展性:在服务端的内存中使用Seesion存储登录信息,伴随而来的是可扩展性问题。

为了方便理解,可以先看下这张流程执行图加深概念

2.可扩展性:在服务端的内存中使用Seesion存储登录信息,伴随而来的是可扩展性问题。

(1)Session超时:超时指的是连续一定时间服务器没有收到该Session所对应客户端的请求,并且这个时间超过了服务器设置的Session超时的最大时间

3.CORS:当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax抓取另一个域的资源,就可以会出现禁止请求的情况。

图片 1客户端与服务端的Cookie流程图

3.CORS:当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用Ajax抓取另一个域的资源,就可以会出现禁止请求的情况。

(2)程序调用HttpSession.invalidate()

4.CSRF:用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。

那么,在浏览器上面的请求头和Cookie在那?下图给大家截取了其中一种。

4.CSRF:用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。

(3)服务器关闭或服务停止

于是有人就一直在思考, 服务器为什么要保存这些信息呢,
只让每个客户端去保存该多好?

图片 2请求头上面的Cookie

于是有人就一直在思考, 服务器为什么要保存这些信息呢,
只让每个客户端去保存该多好?

Session的存放

在这种情况下,Token应用而生。

那么,上面都是谈浏览器上的Cookie,那么在Android开发中,我们该如何去管理和使用Cookie?Okhttp作为经典到爆的网络框架,它的API(本文是基于Okhttp3.0版本以上,3.0以下的版本API有所不同)是通过OkhttpClient中的CookieJar或者拦截器去管理Cookie的。理论上,我们只需在构建单例OkhttpClient的时候,设置cookiejar或者拦截器,然后具体的操作(具体的操作也就是保存Cookie,取Cookie),Okhttp框架就会帮我们自动管理Cookie。如下图:

在这种情况下,Token应用而生。

服务器端的内存中。不过session可以通过特殊的方式做持久化管理。

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌。当客户端第一次访问服务端,服务端会根据传过来的唯一标识userId,运用一些算法,并加上密钥,生成一个Token,然后通过BASE64编码一下之后将这个Token返回给客户端,客户端将Token保存起来(可以通过数据库或文件形式保存本地)。下次请求时,客户端只需要带上Token,服务器收到请求后,会用相同的算法和密钥去验证Token。

图片 3OKhttp的管理策略

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌。当客户端第一次访问服务端,服务端会根据传过来的唯一标识userId,运用一些算法,并加上密钥,生成一个Token,然后通过BASE64编码一下之后将这个Token返回给客户端,客户端将Token保存起来(可以通过数据库或文件形式保存本地)。下次请求时,客户端只需要带上Token,服务器收到请求后,会用相同的算法和密钥去验证Token。

session是一个容器,可以存放会话过程中的任何对象。

图片 4image图片 5image

这是其中一种通过集合的增查特性,就可以简单有效的帮我们管理Cookie。但我们还是要通过源代码去一探究竟。首先,CookieJar是一个接口。

图片 6

二、Cookies

cookie
是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。

图片 7CookieJar

图片 8

Cookies要解决的问题

cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

英文注释翻译过来就是:

Cookie

有些开发者借助请求中的ip头部来唯一标识发出此次请求的客户端,但是这种方式存在很多问题。因为,有些用户是通过代理来访问的,比如用户A通过代理B连接网站www.example.com,
服务器端获取的ip信息是代理B分配给A的ip地址,如果用户这时断开代理,然后再次连接代理的话,它的代理ip地址又再次改变,也就说一个用户对应了多个ip地址,这种情况下,服务器端根据ip地址来标识用户的话,会认为请求是来自不同的用户,事实上是同一个用户。
还用另外一种情况就是,比如很多用户是在同一个局域网里通过路由连接互联网,然后都访问www.example.com的话,由于这些用户共享同一个外网ip地址,这会导致服务器认为这些用户是同一个用户发出的请求,因为他们是来自同一个ip地址的访问。

Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。Cookie存储的数据量有限,且都是保存在客户端浏览器中。不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用Cookie实际上只能存储一小段的文本信息。

CookieJar这个接口为HTTP cookies提供了强大的支持和相关策略。

cookie
是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。

保持应用程序状态的第一步就是要知道如何来唯一地标识每个客户端。因为只有在http中请求中携带的信息才能用来标识客户端,所以在请求中必须包含某种可以用来标识客户端唯一身份的信息。Cookie设计出来就是用来解决这一问题的。

例如:登录网站,今输入用户名密码登录了,第二天再打开很多情况下就直接打开了。这个时候用到的一个机制就是Cookie。

这种策略的实现作用会负责选择接受和拒绝那些cookie。一个合理的策略是拒绝所有的cookie,尽管这样会干扰需要cookie的基于会话的自身身份验证方案。

cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

Token

session
从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征表明他就是张三。

作为Cookie的持久性,该接口的实现也必须要提供Cookie的存储。一种简单的实现可以将cookie存储在内存中;复杂的系统可以使用文件系统用于保存已接受的cookie的数据库。这里的链接指定cookie存储模型更新和过期的cookie的策略。

Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。Cookie存储的数据量有限,且都是保存在客户端浏览器中。不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用Cookie实际上只能存储一小段的文本信息。

既然我们可以检查User-Agent这个头部来加强安全性,那么不妨再利用其它的一些头部信息,把他们组合起来生成一个加密的token,并且让客户端在后续的请求中携带这个token!这样的话,攻击者基本上不可能猜测出这样一个token是怎么生成出来的。这好比你用信用卡在超市付款,一个你必须有信用卡(好比session
id),另外你也必须输入一个支付密码(好比token),这有这两者都符合的情况下,你才能成功进入账号付款。

Session是另一种记录客户状态的机制,它是在服务端保存的一个数据结构(主要存储的的SessionID和Session内容,同时也包含了很多自定义的内容如:用户基础信息、权限信息、用户机构信息、固定变量等),这个数据可以保存在集群、数据库、文件中,用于跟踪用户的状态。

所以,Okhttp的源码告知我们可以将cookie存储在内存中;复杂的系统可以使用文件系统用于保存已接受的cookie的数据库。因此,我们就可以通过Map去简单的管理和使用。

例如:登录网站,今输入用户名密码登录了,第二天再打开很多情况下就直接打开了。这个时候用到的一个机制就是Cookie。Session

客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

继续分析CookieJar接口里面的方法,依旧上源码

session
从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征表明他就是张三。

session
也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用
cookie 的方式。

图片 9CookieJar里面的方法

Session是另一种记录客户状态的机制,它是在服务端保存的一个数据结构(主要存储的的SessionID和Session内容,同时也包含了很多自定义的内容如:用户基础信息、权限信息、用户机构信息、固定变量等),这个数据可以保存在集群、数据库、文件中,用于跟踪用户的状态。

服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。

里面有方法一个是saveFromResponse(HttpUrl url, List
cookies)、loadForRequest(HttpUrl url)

客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

用户第一次登录后,浏览器会将用户信息发送给服务器,服务器会为该用户创建一个SessionId,并在响应内容中将该SessionId一并返回给浏览器,浏览器将这些数据保存在本地。当用户再次发送请求时,浏览器会自动的把上次请求存储的Cookie数据自动的携带给服务器。

saveFromResponse方法翻译:根据这个jar的方法,可以将cookie从一个HTTP响应保存到这里。请注意,如果响应,此方法可能被称为第二次HTTP响应,包括一个追踪。对于这个隐蔽的HTTP特性,这里的cookie只包含其追踪的cookie。简单点理解就是如果我们使用了这个方法,就会进行追踪(说白了就是客户端请求成功以后,在响应头里面去存cookie)

session
也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用
cookie 的方式。

服务器接收到请求信息后,会通过浏览器请求的数据中的SessionId判断当前是哪个用户,然后根据SessionId在Session库中获取用户的Session数据返回给浏览器。

loadForRequest方法翻译:将cookie从这个方法加载到一个HTTP请求到指定的url。这个方法从网络上返回的结果可能是一个空集合。简单的实现将返回尚未过期的已接受的cookie去进行匹配。(说白了就是加载url的时候在请求头带上cookie)。

服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。

例如:购物车,添加了商品之后客户端处可以知道添加了哪些商品,而服务器端如何判别呢,所以也需要存储一些信息就用到了Session。

图片 10通过CookieJar打印Cookie信息

用户第一次登录后,浏览器会将用户信息发送给服务器,服务器会为该用户创建一个SessionId,并在响应内容中将该SessionId一并返回给浏览器,浏览器将这些数据保存在本地。当用户再次发送请求时,浏览器会自动的把上次请求存储的Cookie数据自动的携带给服务器。

如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

这样,我们通过以上代码就可以完成了Cookie的非持久化。什么,非持久化,这又是神马?

服务器接收到请求信息后,会通过浏览器请求的数据中的SessionId判断当前是哪个用户,然后根据SessionId在Session库中获取用户的Session数据返回给浏览器。

Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。

继续给大家科普,在上面说道,Cookie是具有时效性的,所以,Cookie的管理又分为持久化Cookie和非持久化Cookie。非持久化Cookie存储在内存中,也就意味着,其生命周期基本和app保持一致,app关闭后,Cookie丢失。而持久化Cookie则是存储在本地磁盘中,app关闭后不丢失。那么,如果我们要使用Cookie的持久化策略,思想可以参考上面的非持久化策略,只需要将存储方式改一下即可:

例如:购物车,添加了商品之后客户端处可以知道添加了哪些商品,而服务器端如何判别呢,所以也需要存储一些信息就用到了Session。

在Web领域基于Token的身份验证随处可见。在大多数使用Web
API的互联网公司中,tokens 是多用户下处理认证的最佳方式。

A:通过响应拦截器从response取出cookie并保存到本地,通过请求拦截器从本地取出cookie并添加到请求中

Cookie和Session比较

大部分你见到过的API和Web应用都使用tokens。例如Facebook, Twitter,
Google+, GitHub等。

B:自定义CookieJar,在saveFromResponse()中保存cookie到本地,在loadForRequest()从本地取出cookie。

如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。

最简单的Token组成:uid(用户唯一的身份标识)、time、sign(签名,由Token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接Token请求服务器)

那么在这里主要介绍如何通过Okhttp逼格值较高的拦截器去进行持久化cookie操作。(拦截器源码见文章末尾处

Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。为防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除。这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了。Token

基于Token的身份验证是无状态的,我们不将用户信息存在服务器或Session中。

图片 11保存cookie拦截器-1图片 12保存cookie拦截器-2

在Web领域基于Token的身份验证随处可见。在大多数使用Web
API的互联网公司中,tokens 是多用户下处理认证的最佳方式。

这种概念解决了在服务端存储信息时的许多问题,NoSession意味着你的程序可以根据需要去增减机器,而不用去担心用户是否登录。

这个SaveCookiesInterceptor拦截器的实现,是首先从response获取set-cookie字段的值,然后通过SharedPreferences保存在本地。

大部分你见到过的API和Web应用都使用tokens。例如Facebook, Twitter,
Google+, GitHub等。

使用基于 Token
的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

图片 13将Cookie添加到请求头

最简单的Token组成:uid(用户唯一的身份标识)、time、sign(签名,由Token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接Token请求服务器)

  • 客户端使用用户名跟密码请求登录
  • 服务端收到请求,去验证用户名与密码
  • 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  • 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie
    里或者数据库里
  • 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  • 服务端收到请求,然后去验证客户端请求里面带着的
    Token,如果验证成功,就向客户端返回请求的数据

AddCookiesInterceptor请求拦截器,这个拦截的作用就是判断如果该请求存在cookie,则为其添加到Header的Cookie中。

基于Token的验证原理

每一次请求都需要token。token应该在HTTP的头部发送从而保证了Http请求无状态。我们同样通过设置服务器属性Access-Control-Allow-Origin:*
,让服务器能接受到来自所有域的请求。需要主要的是,在ACAO头部标明(designating)*时,不得带有像HTTP认证,客户端SSL证书和cookies的证书。

写好这两个拦截器之后,我们只需要将实例对象放进OkhttpClient里面即可快速的完成Cookie持久化操作。(PS:这两个拦截器在同步Cookie的时候也是超级好用)。

基于Token的身份验证是无状态的,我们不将用户信息存在服务器或Session中。

实现思路:

图片 14Okhttp使用cookie拦截器

这种概念解决了在服务端存储信息时的许多问题,NoSession意味着你的程序可以根据需要去增减机器,而不用去担心用户是否登录。

图片 15image

拓展:如何通过客户端的cookie与H5上面的cookie进行同步,针对这个问题,给大家推荐笔者的另外一篇文章

使用基于 Token
的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

1.无状态、可扩展

客户端与H5同步Cookie

客户端使用用户名跟密码请求登录

在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。

Session :

Session是对于服务端来说的,客户端是没有Session一说的。Session是服务器在和客户端建立连接时添加客户端连接标志,最终会在服务器软件(Apache、Tomcat、JBoss)转化为一个临时Cookie发送给给客户端,当客户端第一请求时服务器会检查是否携带了这个Session,如果没有则会添加Session,如果有就拿出这个Session来做相关操作。

在这里引用别人家的一个小故事来加深印象:

在说session是啥之前,我们先来说说为什么会出现session会话,它出现的机理是什么?

我们知道,我们用浏览器打开一个网页,用到的是HTTP协议,了解计算机的应该都知道这个协议,它是无状态的,什么是无状态呢?就是说这一次请求和上一次请求是没有任何关系的,互不认识的,没有关联的。但是这种无状态的的好处是快速。所以就会带来一个问题就是,我希望几个请求的页面要有关联,比如:我在www.a.com/login.php里面登陆了,我在www.a.com/index.php
也希望是登陆状态,但是,这是2个不同的页面,也就是2个不同的HTTP请求,这2个HTTP请求是无状态的,也就是无关联的,所以无法单纯的在index.php中读取到它在login.php中已经登陆了!

那咋搞呢?我不可能这2个页面我都去登陆一遍吧。或者用笨方法这2个页面都去查询数据库,如果有登陆状态,就判断是登陆的了。这种查询数据库的方案虽然可行,但是每次都要去查询数据库不是个事,会造成数据库的压力。
所以正是这种诉求,这个时候,一个新的客户端存储数据方式出现了:cookie。cookie是把少量的信息存储在用户自己的电脑上,它在一个域名下是一个全局的,只要设置它的存储路径在域名www.a.com下
,那么当用户用浏览器访问时,php就可以从这个域名的任意页面读取cookie中的信息。所以就很好的解决了我在www.a.com/login.php页面登陆了,我也可以在www.a.com/index.php获取到这个登陆信息了。同时又不用反复去查询数据库。
虽然这种方案很不错,也很快速方便,但是由于cookie
是存在用户端,而且它本身存储的尺寸大小也有限,最关键是用户可以是可见的,并可以随意的修改,很不安全。那如何又要安全,又可以方便的全局读取信息呢?于是,这个时候,一种新的存储会话机制:session
诞生了。

Session
就是在一次会话中解决2次HTTP的请求的关联,让它们产生联系,让2两个页面都能读取到找个这个全局的session信息。session信息存在于服务器端,所以也就很好的解决了安全问题。

服务端收到请求,去验证用户名与密码

如果我们将已验证的用户的信息保存在Session中,则每次请求都需要用户向已验证的服务器发送验证信息(称为Session亲和性)。用户量大时,可能会造成

Token :

token是用户身份的验证方式,我们通常叫它:令牌。最简单的token组成:uid(用户唯一的身份标识)、time、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库。

应用场景:

A:当用户首次登录成功(注册也是一种可以适用的场景)之后,
服务器端就会生成一个 token
值,这个值,会在服务器保存token值,再将这个token值返回给客户端.

B:客户端拿到 token
值之后,进行本地保存。(SP存储是大家能够比较支持和易于理解操作的存储)

C:当客户端再次发送网络请求的时候,就会将这个 token
值附带到参数中发送给服务器.

D:服务器接收到客户端的请求之后,会取出token值与保存在本地中的token值做对比

对比一:如果两个 token 值相同, 说明用户登录成功过!当前用户处于登录状态!

对比二:如果没有这个 token 值, 则说明没有登录成功.

对比三:如果 token 值不同: 说明原来的登录信息已经失效,让用户重新登录.

Cookie和Session的区别:

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。

4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

5、所以个人建议:

将登陆信息等重要信息存放为session

其他信息如果需要保留,可以放在cookie中

Token 和 Session 的区别:

session和
token并不矛盾,作为身份认证token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击,而session就必须靠链路层来保障通讯安全了。如上所说,如果你需要实现有状态的会话,仍然可以增加session来在服务器端保存一些状态

App通常用restful
api跟server打交道。Rest是stateless的,也就是app不需要像browser那样用cookie来保存session,因此用session
token来标示自己就够了,session/state由api
server的逻辑处理。如果你的后端不是stateless的rest
api,那么你可能需要在app里保存session.可以在app里嵌入webkit,用一个隐藏的browser来管理cookie
session.

Session是一种HTTP存储机制,目的是为无状态的HTTP提供的持久机制。所谓Session认证只是简单的把User信息存储到Session里,因为SID的不可预测性,暂且认为是安全的。这是一种认证手段。而Token,如果指的是OAuth
Token或类似的机制的话,提供的是 认证 和 授权
,认证是针对用户,授权是针对App。其目的是让 某App有权利访问 某用户
的信息。这里的Token是唯一的。不可以转移到其它App上,也不可以转到其它
用户
上。转过来说Session。Session只提供一种简单的认证,即有此SID,即认为有此User的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方App。所以简单来说,如果你的用户数据可能需要和第三方共享,或者允许第三方调用API接口,用Token。如果永远只是自己的网站,自己的App,用什么就无所谓了。

token就是令牌,比如你授权一个程序时,他就是个依据,判断你是否已经授权该软件;cookie就是写在客户端的一个txt文件,里面包括你登录信息之类的,这样你下次在登录某个网站,就会自动调用cookie自动登录用户名;session和cookie差不多,只是session是写在服务器端的文件,也需要在客户端写入cookie文件,但是文件里是你的浏览器编号.Session的状态是存储在服务器端,客户端只有session
id;而Token的状态是存储在客户端。

如果觉得这篇文章对你有帮助,希望点下一个小小的star,谢谢。

文章使用到的源码

Ps:著作权归作者所有,转载请注明作者,
商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果,谢谢。

验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端

一些拥堵。

客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者数据库里

但是不要着急。使用tokens之后这些问题都迎刃而解,因为tokens自己hold住了用户的验证信息。

客户端每次向服务端请求资源的时候需要带着服务端签发的 Token

2.安全性

服务端收到请求,然后去验证客户端请求里面带着的
Token,如果验证成功,就向客户端返回请求的数据

请求中发送token而不再是发送cookie能够防止CSRF。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。

每一次请求都需要token。token应该在HTTP的头部发送从而保证了Http请求无状态。我们同样通过设置服务器属性Access-Control-Allow-Origin:*
,让服务器能接受到来自所有域的请求。需要主要的是,在ACAO头部标明(designating)*时,不得带有像HTTP认证,客户端SSL证书和cookies的证书。

token是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token
revocataion可以使一个特定的token或是一组有相同认证的token无效。

实现思路:

3.可扩展性

图片 16

Tokens能够创建与其它程序共享权限的程序。例如,能将一个随便的社交帐号和自己的大号(Fackbook或是Twitter)联系起来。当通过服务登录Twitter(我们将这个过程Buffer)时,我们可以将这些Buffer附到Twitter的数据流上(we
are allowing Buffer to post to our Twitter stream)。

Tokens的优势

使用tokens时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问它们的数据,我们可以通过建立自己的API,得出特殊权限的tokens。

1.无状态、可扩展

4.多平台跨域

在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。

我们提前先来谈论一下CORS,对应用程序和服务进行扩展的时候,需要介入各种各种的设备和应用程序。

如果我们将已验证的用户的信息保存在Session中,则每次请求都需要用户向已验证的服务器发送验证信息(称为Session亲和性)。用户量大时,可能会造成

Having our API just serve data, we can also make the design choice to
serve assets from a CDN. This eliminates the issues that CORS brings up
after we set a quick header configuration for our application.

一些拥堵。

只要用户有一个通过了验证的token,数据和资源就能够在任何域上被请求到。

但是不要着急。使用tokens之后这些问题都迎刃而解,因为tokens自己hold住了用户的验证信息。

 Access-Control-Allow-Origin: * 

2.安全性

App示例:

请求中发送token而不再是发送cookie能够防止CSRF。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。

APP登录的时候发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果成功,以某种方式比如随机生成32位的字符串作为Token,存储到服务器中,并返回Token到APP,以后APP请求时,凡是需要验证的地方都要带上该Token,然后服务器端验证Token,成功返回所需要的结果,失败返回错误信息,让他重新登录。

token是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token
revocataion可以使一个特定的token或是一组有相同认证的token无效。

对于同一个APP同一个手机当前只有一个Token;手机APP会存储一个当前有效的Token。其中服务器上Token设置一个有效期,每次APP请求的时候都验证Token和有效期。

3.可扩展性

下面这个例子,可以很好的理解:

Tokens能够创建与其它程序共享权限的程序。例如,能将一个随便的社交帐号和自己的大号(Fackbook或是Twitter)联系起来。当通过服务登录Twitter(我们将这个过程Buffer)时,我们可以将这些Buffer附到Twitter的数据流上(we
are allowing Buffer to post to our Twitter stream)。

『给我来份煎饼(token我是你对面摊卖烤冷面的,scope赊账)』『好』『鸡蛋(token我是你对面摊卖烤冷面的,scope赊账)』『好』『再加个鸡蛋(token我是你对面摊卖烤冷面的,scope赊账)』『好』

最终得到一份普通煎饼,外加两个鸡蛋……

如果服务器重启或者因为其他理由,服务器端已保存token丢失。那么用户需
要重新登录和认证。

『给我来份煎饼(token我是你对面摊卖烤冷面的)』『那个……我没见过你』

使用tokens时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问它们的数据,我们可以通过建立自己的API,得出特殊权限的tokens。

4.多平台跨域

我们提前先来谈论一下CORS,对应用程序和服务进行扩展的时候,需要介入各种各种的设备和应用程序。

Having our API just serve data, we can also make the design choice to
serve assets from a CDN. This eliminates the issues that CORS brings up
after we set a quick header configuration for our application.

只要用户有一个通过了验证的token,数据和资源就能够在任何域上被请求到。
Access-Control-Allow-Origin: *

App示例:

APP登录的时候发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果成功,以某种方式比如随机生成32位的字符串作为Token,存储到服务器中,并返回Token到APP,以后APP请求时,凡是需要验证的地方都要带上该Token,然后服务器端验证Token,成功返回所需要的结果,失败返回错误信息,让他重新登录。

对于同一个APP同一个手机当前只有一个Token;手机APP会存储一个当前有效的Token。其中服务器上Token设置一个有效期,每次APP请求的时候都验证Token和有效期。

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图