cookie、session、token之间的关系

 Cookie机制

由于HTTP是一种无状态协议,服务器没有办法单单从网络连接上面知道访问者的身份,为了解决这个问题,就诞生了Cookie。Cookie实际上是一小段的文本信息。Cookies是由服务器产生的。接下来我们描述一下Cookie产生的过程。浏览器第一次访问服务端时,服务器此时肯定不知道他的身份,所以创建一个独特的身份标识数据,格式为key=value,放入到Set-Cookie字段里,随着响应报文发给浏览器。浏览器看到有Set-Cookie字段以后就知道这是服务器给的身份标识,于是就保存起来,下次请求时会自动将此key=value值放入到Cookie字段中发给服务端。服务端收到请求报文后,发现Cookie字段中有值,就能根据此值识别用户的身份然后提供个性化的服务。相当于服务器给每个客户端都贴上了一个小纸条。上面记录了服务器给我们返回的一些信息。然后服务器再看到这张小纸条就知道我们是谁了。这就是Cookie的工作原理。

Cookie就是服务器委托浏览器存储在客户端里的一些数据,而这些数据通常都会记录用户的关键识别信息。所以Cookie需要用一些其他的手段用来保护,防止外泄或者窃取,这些手段就是Cookie的属性。

cookie的内容主要包括name(名字)、value(值)、 maxAge(失效时间)、path(路径)、domain(域)和secure。
name : cookie的名字,一旦创建,名称不可更改。
value : cookie的值,如果值为Unicode字符,需要为字符编码。如果为二进制数据,则需要使用BASE64编码。
maxAge : cookie失效时间,单位秒。如果为正数,则该cookie在maxAge后失效。如果为负数,该cookie为临时cookie ,关闭浏览器即失效,浏览器也不会以任何形式保存该cookie。如果为0,表示删除该cookie。默认为-1。
path:该cookie的使用路径。如果设置为"/sessionWeb/" ,则只有ContextPath为"/sessionWeb/“的程序可以访问该cookie。如果设置为“/”,则本域名下ContextPath都可以访问该cookie。

Cookie缺点

如果浏览器使用的是cookie,那么所有的数据都保存在浏览器端,cookie可以被用户禁止;cookie不安全(对于敏感数据,需要加密);cookie只能保存少量的数据(大约是4k);cookie存储数据的格式:字符串key=value,对服务器压力小;cookie的数量也有限制(大约是几百个),不同浏览器设置不一样,反正都不多;cookie存储有效期:可以自行通过expires进行具体的日期设置,如果没设置,默认是关闭浏览器时失效;cookie有效范围:当前域名下有效。所以session这种会话存储方式方式只适用于客户端代码和服务端代码运行在同一台服务器上(前后端项目协议、域名、端口号都一致,即在一个项目下)

Session机制

Session称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。Session机制是一种服务端的机制 ,服务器使用一种类似散列表的结构来保存信息。当程序需要为某个客户端的请求创建一个session的时候 ,服务器首先检查这个客户端里的请求里是否已包含了一个session标识-sessionID ,如果已经包含一个sessionID ,则说明以前E经为此客户端创建过session,服务器就按照sessionID把这个session检索出来使用。如果客户端请求不包含sessionlD,则为此客户端创建一个session并且声称一个与此session相关联的sessionID ,sessionID的值应该是一个既不会重复 ,又不容易被找到规律以仿造的字符串(服务器会自动创建),这个sessionID将被在本次响应中返回给客户端保存。浏览器第一次访问服务器,服务器会创建一个session,然后同时为该session生成一个唯一的会话的key,也就是sessionid,然后,将sessionid及对应的session分别作为key和value保存到缓存中,也可以持久化到数据库中,然后服务器再把sessionid,以cookie的形式发送给客户端。这样浏览器下次再访问时,会直接带着cookie中的sessionid。然后服务器根据sessionid找到对应的session进行匹配。session的两种实现方式(也就是传递方式):第一种通过cookies实现,第二种通过URL重写来实现(cookie禁用)

Session过期

客户端:和Cookie过期一致,如果没设置,默认是关了浏览器就没了,即再打开浏览器的时候初次请求头中是没有SessionId了。
服务端:服务端的过期是真的过期,即服务器端的Session存储的数据结构多久不可用了,默认是30分钟。

Session缺点

每个人只需要保存自己的sessionID ,而服务器要保存所有人的sessionID ! 如果访问服务器多了, 就得由成千上万,甚至几十万个。这对服务器说是一个巨大的开销 , 严重的限制了服务器扩展能力, 比如说我用两个机器组成了一个集群, 小F通过机器A登录了系统, 那sessionID 会保存在机器A上, 假设小F的下一次请求被转发到机器B怎么办? 机器B可没有小F的 sessionID 啊。有时候会采用一点小伎俩: session sticky , 就是让小F的请求一直粘连在机器A上, 但是这也不管用, 要是机器A挂掉了, 还得转到机器B去。那只好做session 的复制了, 把sessionID 在两个机器之间搬来搬去, 快累死了。

后来有个叫Memcached的支了招: 把sessionID 集中存储到一个地方, 所有的机器都来访问这个地方的数据, 这样一来,就不用复制了, 但是增加了单点失败的可能性, 要是那个负责session的机器挂了, 所有人都得重新登录一遍, 估计得被人骂死。

也尝试把这个单点的机器也搞出集群,增加可靠性, 但不管如何, 这小小的session 对我来说是一个沉重的负担,于是有人就一直在思考, 我为什么要保存这可恶的session呢, 只让每个客户端去保存该多好?可是如果不保存这些sessionID , 怎么验证客户端发给我的sessionID 的确是我生成的呢? 如果不去验证,我们都不知道他们是不是合法登录的用户, 那些不怀好意的家伙们就可以伪造sessionID , 为所欲为了。嗯,对了,关键点就是验证 !

 Token机制

适用于项目级的前后端分离(前后端代码运行在不同的服务器下),请求登录时,token和sessionId原理相同,是对key和key对应的用户信息进行加密后的加密字符,登录成功后,会在响应主体中将{token:'字符串'}返回给客户端。客户端通过cookie、sessionStorage、localStorage都可以进行存储。再次请求时不会默认携带,需要在请求拦截器位置给请求头中添加认证字段Authorization(HTTP协议授权认证简介)携带token信息,服务器端就可以通过token信息查找用户登录状态。比如说, 小F已经登录了系统, 我给他发一个令牌(token), 里边包含了小F的 user id, 下一次小F 再次通过Http 请求访问我的时候, 把这个token 通过Http header 带过来不就可以了。不过这和session id没有本质区别啊, 任何人都可以可以伪造, 所以我得想点儿办法, 让别人伪造不了。那就对数据做一个签名吧, 比如说我用HMAC-SHA256 算法,加上一个只有我才知道的密钥, 对数据做一个签名, 把这个签名和数据一起作为token , 由于密钥别人不知道, 就无法伪造token了。

这个token 我不保存, 当小F把这个token 给我发过来的时候,我再用同样的HMAC-SHA256 算法和同样的密钥,对数据再计算一次签名, 和token 中的签名做个比较, 如果相同, 我就知道小F已经登录过了,并且可以直接取到小F的user id , 如果不相同, 数据部分肯定被人篡改过, 我就告诉发送者: 对不起,没有认证。 

Token 中的数据是明文保存的(虽然我会用Base64做下编码, 但那不是加密), 还是可以被别人看到的, 所以我不能在其中保存像密码这样的敏感信息。当然, 如果一个人的token 被别人偷走了, 那我也没办法, 我也会认为小偷就是合法用户, 这其实和一个人的session id 被别人偷走是一样的。这样一来, 我就不保存session id 了, 我只是生成token , 然后验证token , 我用我的CPU计算时间获取了我的session 存储空间 !解除了session id这个负担, 可以说是无事一身轻, 我的机器集群现在可以轻松地做水平扩展, 用户访问量增大, 直接加机器就行。token和session其实都是为了身份验证,session一般翻译为会话,而token更多的时候是翻译为令牌;session服务器会保存一份,可能保存到缓存,文件,数据库;同样,session和token都是有过期时间一说,都需要去管理过期时间;其实token与session的问题是一种时间与空间的博弈问题,session是空间换时间,而token是时间换空间。两者的选择要看具体情况而定。

如何使用token验证代替session

Token的优点

简洁:可以通过URL、POST参数或者是在HTTP头参数发送,因为数据量小,传输速度也很快。
自包含:由于串包含了用户所需要的信息,避免了多次查询数据库,因为Token是以Json的形式保存在客户端的,所以JWT是跨语言的,不需要在服务端保存会话信息,特别适用于分布式微服务。

token可以抵御CSRF跨站请求伪造(cross site request forgery)攻击,常见的Web攻击手段有XSS、CRSF、SQL注入、(常规的不包括文件上传漏洞、DDoS攻击)等。

彻底搞懂Cookie、Session、Token到底是什么

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值