傲娇大少之---【理解session、cookie、token】

liao一下浏览器de缓存

今天的鸡汤有点毒:
你必须敢爱敢恨,才会发现你的爱恨别人真的不在乎

本来想写的挺多,看了很多别人优秀的文章后,突然感觉,我写的可能是个渣渣~but,我还是要写的,毕竟有的时候自己写过的东西比较容易回忆起来。

最近看了很多关于cookie、session和token的资料,在此总结一下吧,留着以后想起来的时候看看。有一些个人理解,慎重~~
我废话是真的多,哎……

追本溯源

这一切都要源于客户端和服务器端之间的爱恨情仇吧。

最初的WEB端,页面就是个辅助的作用。一般就是个form表单,action指向一个http接口。提交表单,发起请求,接受响应,仅此而已。(感觉这句话真的说过好多次~)

每个http请求是相互独立的,毫无关联的。这就是人家说的http是一个无状态协议的意思。干净利落,运行快速。棒棒!

但是随着交互式Web应用的兴起,前端作用越来越重要,逻辑越来越复杂。这种无状态协议已经不能满足我们的大多数需求,比如现在市场上绝大多数的网站都是有登录系统的,登录后看到的页面都是我们自己的信息,以及一些个性化定制的页面展示。比如说某宝,我们登录后,购物车是我们之前添加的物品,给我们推荐的全都是我们感兴趣的东西,所以我们操作任何一步的时候服务器必定是知道当前用户的信息的。

所以现在的需求是需要服务器记住用户的登录信息

想要实现这样的需求,就需要让服务器知道每个http请求是哪个用户发送的,这样才能根据不同的用户返回不同的信息。但是总不能每发送一次http请求都携带着用户名和密码,这很奇怪,很啰嗦,也很不安全。

有问题就要解决嘛,所以有大牛提出了解决方案:用户登录成功时,服务器给这个用户分配一个会话标识sessionId保存在数据库,就是一个唯一的随机字符串,并将该sessionId返回给浏览器,浏览器再次发送http请求时,携带上这个参数,服务器端对该用户的sessionId进行验证,这样就能确定用的登录信息了。用户退出时,注销这个sessionId就可以了。

我们采用了这个方案。并将这个sessionId的保存在cookie中。所以你可以理解为cookie其实是一个用于保存sessionId的文本文件。

Cookie

Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。

Cookie是一个很具象的概念。看图:
我们打开F12的开发者工具,如果当前的网站是存在Cookie信息的话,在这里是可以看到的。
在这里插入图片描述
所以,cookie其实就是用来存储数据的。未设置超时时间的cookie保存在临时存储器中,浏览器关闭后,会自动清除;设置了超时时间的cookie,会将这些数据保存在本地的一个文本文件中。

Cookie是一个保存在客户机中的简单的文本文件, 这个文件与特定的 Web 文档关联在一起,保存了该客户机访问这个Web 文档时的信息,当客户机再次访问这个 Web 文档时这些信息可供该文档使用。是一段不超过4KB的小型文本数据,由键值对和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。

Cookie的属性:

  • Name/Value:设置Cookie的名称及相对应的值,对于认证Cookie,Value值包括Web服务器所提供的访问令牌
  • Expires:设置Cookie的生存周期。有两种存储类型的Cookie:会话性与持久性。Expires属性缺省时,为会话性Cookie,仅保存在客户端内存中,并在用户关闭浏览器时失效;持久性Cookie会保存在用户的硬盘中,直至生存期到或用户直接在网页中单击“注销”等按钮结束会话时才会失效 。
  • Path:定义了Web站点上可以访问该Cookie的目录 。
  • Domain:指定了可以访问该 Cookie 的 Web 站点或域。Cookie 机制并未遵循严格的同源策略,允许一个子域可以设置或获取其父域的 Cookie。当需要实现单点登录方案时,Cookie 的上述特性非常有用,然而也增加了 Cookie受攻击的危险,比如攻击者可以借此发动会话定置攻击。因而,浏览器禁止在 Domain 属性中设置.org、.com 等通用顶级域名、以及在国家及地区顶级域下注册的二级域名,以减小攻击发生的范围 。
  • Secure:指定是否使用HTTPS安全协议发送Cookie。使用HTTPS安全协议,可以保护Cookie在浏览器和Web服务器间的传输过程中不被窃取和篡改。该方法也可用于Web站点的身份鉴别,即在HTTPS的连接建立阶段,浏览器会检查Web网站的SSL证书的有效性。但是基于兼容性的原因(比如有些网站使用自签署的证书)在检测到SSL证书无效时,浏览器并不会立即终止用户的连接请求,而是显示安全风险信息,用户仍可以选择继续访问该站点。由于许多用户缺乏安全意识,因而仍可能连接到Pharming攻击所伪造的网站 。
  • HTTPOnly :用于防止客户端脚本通过document.cookie属性访问Cookie,有助于保护Cookie不被跨站脚本攻击窃取或篡改。但是,HTTPOnly的应用仍存在局限性,一些浏览器可以阻止客户端脚本对Cookie的读操作,但允许写操作;此外大多数浏览器仍允许通过XMLHTTP对象读取HTTP响应中的Set-Cookie头 。

所以关于cookie,在我的理解上大概是这么回事:
在用户填写登录信息发起登录请求时,服务器端生成该用户唯一的sessionId之类的唯一标识,将其与该用户的登录信息,一起保存在数据库中(现在大多保存在临时数据库redis之类的)。
然后将sessionId之类的标识数据放在响应头中,命名为set-cookie,返回给浏览器。
浏览器将这些信息保存在cookie临时文件中。
然后再次向服务器发送请求的时候,浏览器会自动将cookie中的信息放在请求头中一同发送到服务器,服务器会根据cookie中的信息来获取当前用户的登录信息。
这样就解决了http无状态协议的问题啦。

cookie验证流程:

  1. 客户端向服务器端发送http请求(HTTP Request);
  2. 服务器端接受请求,生成sessionID,在响应头中通过set-cookie携带改sessionId,返回到客户端(HTTP Response Headers + set-cookie);
  3. 客户端再次向服务器端发起请求,并自动在请求头中携带返回的SessionId(HTTP Request Headers + Cookie);
  4. 服务器端根据sessionId判断用户的登录信息,做出对应响应。(HTTP Response);

打开F12,可以在响应头(Response Headers)中发现返回了set-cookie:
在这里插入图片描述
再次发送请求时,会发现请求头(Request Headers)中自动携带了cookie的参数。
在这里插入图片描述
所谓cookie,大概就是这么回事。

接下来说下Cookie的特点

  • Cookie的存储:浏览器运行时,cookie会存储在 RAM (随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。)中发挥作用,一旦用户从该网站或服务器退出,Cookie 可存储在用户本地的硬盘上(只有设置了cookie的保存时间,才会存储在本地硬盘上)。
  • Cookie时效性:需要设置cookie的保存时间,没有设置Cookie的保存时间时,默认是关闭浏览器,自动清除。
  • Cookie使用限制:必须在html文件的内容输出之前设置Cookie的属性;不同的浏览器 (Netscape Navigator、Internet Explorer) 对 Cookie 的处理不一致,使用时一定要考虑;客户端用户如果设置禁止 Cookie,则 Cookie 不能建立。 并且在客户端,一个浏览器能创建的 Cookie 数量最多为 300 个,并且每个不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20 个(IE6或更低版本最多20个cookie,IE7及之后可以有50个cookie,firefox最多50个cookie)。

了解了cookie之后,咱们来点实际的,如何在前端拿到cookie的值呢?(虽然一般情况下,前端不会去操作cookie的值。)
JavaScript 可以使用 document.cookie 属性来创建 、读取、及删除 cookie。

document.cookie = "sessionid=88888"; // 注:给cookie新增个属性
console.log(document.cookie); // 获取cookie的值,当前cookie值为(sessionid=88888)
document.cookie = "pp=123"; // 重新给cookie赋值
console.log(document.cookie); // 再次获取cookie的值
// 删除cookie,设置它的超时时间为一个过去的时间,比如我设置为这个Thu, 01 Jan 1970 00:00:00 GMT
// 然后咱们删除之前添加的pp属性
document.cookie = 'pp=;expires=Thu, 01 Jan 1970 00:00:00 GMT';
console.log(document.cookie); // 再次获取cookie的值

然后咱们来看些执行结果:
在这里插入图片描述
从这个现象中,我们可以发现一些好玩的东西,记下来哈,知识点!

  • js通过document.cookie来获取我们设置的cookie中的值!但是给cookie赋值,并不会重写覆盖掉以前的cookie。
  • 删除cookie的时候,需要标明要删除的属性,以及设置过期时间为一个过去的时间。
  • 如果某cookie的值设置了httpOnly,那么在客户端js中是无法拿到的,这个是为了防止xss攻击,为了安全性考虑的(如下图)
    在这里插入图片描述

token

通过上边的了解,我们可以发现Cookie还是存在一些弊端的:

  1. 当同时在线用户数据量较大时,自然的服务器端需要存储的sessionId就特别的多,无形中增加了服务器的压力以及内存的开销。
  2. 一般在实际项目中,如果用户量特别大的情况下,一般会采用多台服务器负载均衡的机制。那么这个sessionId怎么存储也是个问题,难道每台服务器复制一份吗?
  3. 可扩展性不好。比如现在很多App,都是可以qq或者微信登录,我们总不能把qq或微信的用户名密码给第三方App吧,然后再在第三方App上保存一份sessionId?
  4. 跨域资源共享问题。很多App都是支持多设备同时登录的,肯定会出现多个sessionId,跨平台访问数据的时候,目标服务器认为我发送来的sessionId是错的,这就很尴尬了。
  5. 跨站请求伪造问题(CSRF),用你的浏览器拿着你的sessionId去请求服务器,会造成信息泄露问题,具有一定的风险性。

所以一种新的验证方式出现了——token

token和Cookie的目的是一样的,都是为了验证用户的登录信息和状态。

token的实现思路,用我的理解大概是这个样子的:
用户填写登录信息之后呢,发送给服务器,进行验证,服务器验证用户登录成功后,将用户名通过一系列加密,转码,各种算法后,生成一个秘钥,也叫签名。然后将用户名和秘钥做成一个token返回给客户端。大概是这么个感觉:token: {‘zhangsan’,‘6bf7532j34h2jbkgjk%lk2390fj3%2’}。
客户端拿到这个token后呢,每次发送http请求的时候,都会携带上这个token一起发送至服务器,服务器端拿到token后,将前边的用户名按照那套加密转码的算法,再生成一个秘钥,如果新生成的秘钥和发送来的秘钥统一,则证明该用户登录状态是正确的。然后就可以继续下边的操作了。
这个过程,完全的略过了服务器的存储问题。棒呆!

当然有人说,那玩意这套加密算法泄露了呢,用户信息不就不安全了吗?拜托,人家又不傻,加密算法是每隔一段时间会变的。等你破解出来了,人家都换算法了。(如果你非说有高级黑客,那我只能说人家直接去攻击服务器不好吗,偷个token去看页面至于吗。)

一顿比比叨,不知道大家听明白没,没有的话,咱们再站在学术的角度说下,咳咳:

token验证流程:

  1. 用户通过用户名和密码发送请求
  2. 服务器验证登录信息,并返回客户端一个签名token。
  3. 客户端保存改token,并且每次发送http请求时,都会携带该token。
  4. 服务器每次验证token是否正确,并作出对应的响应。

token的优点:

  • 节省空间:不需要特意给sessionId分配存储空间。多台服务器也无需担心,只要公用一套验签机制就可以了。
  • 可扩展:比如我们使用微信或者qq去登录第三方App,微信和qq就可以通过一系列算法得到一个专属于这个App的特殊token。
  • 跨域资源共享:即使多设备同时在线,只要算法一致,得到的token一致,即使跨域访问资源,也不会被拒绝。
  • 可以预防CSRF:token不会有跨站请求伪造的问题,因为cookie是每次发送请求时,浏览器自动携带cookie的,而token浏览器是不会自动携带的。所以服务器端没有看到token,肯定是会报错的。

session

session,字面上的意思,就是会话。一次会话,就是一次浏览器和服务器之间的对话,所以其实你可以理解为一个http请求。上回书说道,http协议是无状态的,所以咱们在cookie中保存sessionid,可以保证用户的登录状态,才得以让多次会话之间产生关联。

但是呢,我们也知道cookie是存在弊端的,比如cookie存储在客户端的,且本身存储大小有限,最可怕的是对用户可见,可随意修改,安全性不好。所以,服务器觉得还是自己安全,于是产生了session,就是将这些信息存储在服务器端。

服务器中的session机制,即用户登录的时候,会随机生成一个唯一的32位的session_id,来唯一标识一个会话(说白了就是确定是否为同一用户),然后作为set-coolie的值传递给客户端。

sessionid生成后,服务器端肯定是要将该sessionid对应的session信息保存下来的,不然下次怎么验证呢。由于会话结束后,这些session信息肯定是要删掉的,所以一般会将这个session信息写入临时文件中,所以下次http携带着sessionid发起请求的时候,服务器需要找到对应的临时文件,来获取这个用户的登录信息。

这样大家应该就比较理解session机制了。因为session机制主要是在服务器端,而且现在存储在redis中居多,redis拥有着更快的读取和写入速度,因为redis是直接操纵内存数据的,肯定是要比文件的形式快很多,还可以更好的设置好过期时间。之前也说过session过多时,也会影响session的读取速度,设置redis 的主从同步,可以快速的同步session到各台web服务器,比文件存储更加快速。
在这里插入图片描述

拓展!!

1、cookie、token 和 session的区别是什么?

其实完全理解了三者个概念后,看这个问题就很奇怪了,cookie和session不应该是同伙么,怎么还有区别呢? 而且面试官真的很爱问这种问题……人家又不可能瞎问是吧。

所以我觉得他问的session和cookie的区别,应该是后端有无session机制的区别,即把用户所有信息都存在cookie中和存储在session中的区别,哈哈,那就很明显了:

  • 安全性,cookie肯定没session安全性好,毕竟一个存在客户端,一个存在服务器端。
  • cookie保存数据大小个数有限制,session无限制。
  • session需要借助于cookie。

然后咱们再总结一个session和cookie变成同伙之后和token的区别吧:
首先呢,两者的目的都是一样的,只不过实现方式不同。

  • 实现方式不同,cookie一般保存sessionid,然后去服务器中查找用户信息,token是将用户信息进行多种算法加密,然后发起请求时,服务器对其进行解密后获得用户信息;
  • cookie需要与session共同作用,而token不需要,所以token的效率跟高;
  • cookie浏览器自动携带在请求头中,token不是,所以cookie的安全性没有token高;
  • cookie的可扩展性不好,如果后端服务器做了负载均衡,可能会导致session丢失;token则没有这个烦恼;
  • token可支持多设备移动设备跨域资源共享,cookie可能会产生session丢失;
  • cookie容易受到CSRF(跨站请求伪造)攻击,token不会;

2、为什么token不会被CSRF攻击?

CSRF(Cross-site request forgery)跨站请求伪造:是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

简单的说,就是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。
比如,你在你的浏览器中执行了一个给zhang的转账的操作,转账的url是“http://xxxx?name=12&account=100000&for=zhang”。这时因为网站已经认证了你的信息,所以cookie中存储着你的sessionid。
然后你没有执行退出操作,即当前的sessionid还是有效的时候,你在当前浏览器中访问了另一个网站。这个新的网站中,攻击者加入了一句代码“<img src=“http://xxxx?name=12&account=100000&for=bad”/>”。
因为图片肯定是会自动加载的,那么这个http请求就会被执行,而你的浏览器的cookie中保存的sessionid还是有效的,所以浏览器会自动携带cookie中的sessionid,导致你自动给bad这个人转账了。

所以cookie容易被CSRF攻击,但是token不会,因为token不会被浏览器自动携带,所以在其它网站中如果没有手动设置token,那么就不会被CSRF攻击。

3、XSS攻击?

上边咱们说过cookie中有些值,需要设置httponly属性,目的是为了防止XSS攻击,那咱们就说一下XSS攻击吧!

XSS攻击——跨站脚本攻击:通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。

意思就是代码毕竟是代码,只要语法正确,它就会执行,它并不关心这个代码是谁写的。

比如攻击者在你的目标服务器注入可执行脚本: <script>alert("你个傻子!)</script>,页面就会弹出这个alert ,如果将script标签的src设置为恶意的js文件,那么这个网站受到的攻击会是非常大的。

所以,cookie中关于用户信息的属性需要设置httpOnly为true,否则攻击者通过document.cookie就能轻易的拿到用户的sessionid,那产生的损失将是巨大的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值