HTTP 无状态中的 "状态" 到底指的是什么?

图片


引子:
web

最近在好好了解http,发现对介绍http的第一句话【http协议是无状态的,无链接的】就没法理解了:无状态的【状态】到底指的是什么?!数据库


找了不少资料不只没有发现有一针见血正面回答这个问题的,并且有些解释还充斥了各类错误,看着看着就以为内心憋着一股浊气吐不出来缓存


因而在看了不少资料以后,我一口吐出浊气,大声正面提出这个问题:http协议无状态中的【状态】到底指的是什么?!安全


而后开始不断探索解决这个问题。。。服务器


最终很高兴的是我找到了让人满意的答案,先卖个关子,各位若是着急能够直接拉到最下查看cookie

 

正文:网络

http协议无状态中的【状态】到底指的是什么?!session

 

先来看这句话的另外两个概念:(标准的http协议是无状态的,无链接的)app


1. 标准的http协议指的是不包括cookies, session,application的http协议,他们都不属于标准协议,虽然各类网络应用提供商,实现语言、web容器等,都默认支持它ide


2. 无链接指的是什么

  • 每个访问都是无链接,服务器挨个处理访问队列里的访问,处理完一个就关闭链接,这事儿就完了,而后处理下一个新的
  • 无链接的含义是限制每次链接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开链接

 

对于【无状态】,我看到不少隔着一层磨砂玻璃同样的模糊说法(官方或者教程里的说法),看着很是难受(但其实算是对的)


后来我发现我为何以为它看着难受了,由于他们引入了不少新的,并且明显是一个可能用在不少地方的广义名词,这些词最大的做用就是,混淆概念,下面我标注了


1. 协议对于事务处理没有记忆能力【事物处理】【记忆能力】


2. 对同一个url请求没有上下文关系【上下文关系】


3. 每次的请求都是独立的,它的执行状况和结果与前面的请求和以后的请求是无直接关系的,它不会受前面的请求应答状况直接影响,也不会直接影响后面的请求应答状况【无直接联系】【受直接影响】


4. 服务器中没有保存客户端的状态,客户端必须每次带上本身的状态去请求服务器【状态】

 

我必须获得确切而具体的解释!

 

这几点给了我下一步思考的方向:


1. 【服务器中没有保存客户端的状态,客户端必须每次带上本身的状态去请求服务器 】这里的客户端的状态是否是确切地指服务器没有保存客户的信息呢?但显然不是啊


2. 【HTTP无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是须要承前启后的,简单的购物车程序也要知道用户到底在以前选择了什么商品】我对此质疑为何无状态就不能实现购物车呢?服务器就不能存储东西了么?


3. 【 每次的请求都是独立的,<它的执行状况和结果>与<前面的请求>和<以后的请求>是无直接关系的】我以为这个说法比较靠谱,可是所谓的不一样请求间的没有关系,是指的请求内容没有关系,仍是只是指请求自己没有关系?

  • 请求内容没有关系只多是服务器上不存有用户数据才可能啊,可是显然是存有的啊
  • 请求自己没有关系,这又有什么意义呢,每一次的请求有什么价值?

 


根据这个方向我作了一个模拟访问实验:假如没有cookie没有session,只有http的时候,那当一个注册用户访问这个购物网站的时候,会发生这些事情:


前提状况:

  • 服务器确定为每一个注册用户创建了数据表,记录用户的数据
  • http是无链接的


第一步须要登陆

用户经过http把用户的用户名和密码发送给服务器,服务器把他们跟本身存有的用户资料对比,若是一致,则返回信息登陆成功


而后用户点击某一商品页

1. 这个动做至关于输入一个商品页的网址


2. 假如商品页比较机密不对外公开,须要是用户才能访问


3. 而虽然http能传送用户名和密码,并且刚才也输入了,还验证成功了,可是由于服务器既不会记得你登陆的状态,你的客户端也不会存储你刚才输入的用户名和密码


4. 因此由于这一次访问由于没法肯定你的身份,只能访问失败

  • 这时候若是要解决这个问题,并且没有cookie没有session,那就只能你在访问网址的同时继续带上你的用户名和密码(继续输入咯)其实就像我如今的APP同样


假设上一步的问题解决了,就是每次访问的时候都会手动输入用户名和密码,而后如今的状况是:你已经选了几件商品在你的购物车中,你想再添加一件商品,因而你点击某个商品旁边的加号


  • 这个动做也至关于输入一个网址,网址的内容是发送一个请求,往你的购物车中加入这个商品


  • 系统首先用你传来的用户名和密码验证你的身份,而后访问你的数据库,在其中的购物车属性下加一条数据,就是这个商品的数据


  • 操做结束后,返回操做成功,并结束访问


OK,实验结束,看似没有cookie没有session也能凑合解决问题,其实两个操做都有很大的问题


1. 你每访问一次须要权限的内容都须要在客户端输入用户名和密码,这一项的繁琐就没必要赘述了


2. 你的每一次操做都要与系统底层的数据库进行交互

  • 屡次少许的访问存在很是大的性能浪费。很是容易就能想到确定是一次大量的操做更加有效率,因而就想到了缓存区


3. 你的非重要琐碎数据也被写进数据库中,跟你的主要数据放在一块儿

  • 一次次添加和删除购物车其实只是跟你此次浏览,或者叫此次会话有关,是临时的数据,跟用户的主要信息无关,它们没什么价值,纯粹的冗余数据(不排除如今有的公司以为这种数据也有很是大的价值可让它们巧妙的利用),用什么存放这些临时的数据,咱们也很容易想到缓存区


通过这个模拟访问实验,结合前面的思考方向,咱们知道了三点:


  • 服务器上确定存有用户的数据,你提交的增删改查它也可以处理,因此这句话中【服务器中没有保存客户端的状态】的状态并非指用户的数据,咱们的猜想不对


  • 咱们的质疑对了,无状态能实现购物车,能够经过服务器上存有的用户数据来实现


  • 可是,使用上面这种方式实现购物车,存在三个比较大的问题。由此,咱们不由会想,这三个问题的解决是否是跟咱们不确切了解的【状态】一词有关?因而,接下来咱们来经过解决这三个问题来把【状态】的意义探寻下去

 

由上所述,咱们能够在http的基础上增长一些机制来解决上面出现的三个问题


1. 在用户端增长一个记录本是很是有必要的,正好官方加入的cookie机制跟这个同样,它的用处也确实是上面讨论的那样,通常就是用来标识访问者的身份


2. 在服务器增长一个缓存区能同时解决后两个问题

  • 有了这个缓存区做为一个数据缓冲,就不用一次次地访问数据库,浪费大量计算机资源,而是在最后统一纳入数据库
  • 有了这个缓存区,你就不用把临时的数据放到数据库中了,只须要在大家交流告一段落以后,再把数据整理,把有用的数据纳入数据库


3. 这里就天然引伸出了一个重要的概念:会话,它做为一个缓冲存储区被从数据库中分离出来,理由并不生硬,它有其独特的重要且不可替代的做用。这个东西刚好跟官方加入的session机制同样



另外说一个很是具备迷惑性的容易让人对session的主要做用产生偏离的理解:认为session存在的价值就是给访问者分配一个sessionID代替用户名和密码


为何很是具备迷惑性,由于session确实作了这件事,并且也起到了很大的做用,因此它是对的,可是只对一半,并且没有涉及问题的本质,这种状况是最危险的(看似颇有说服力,把你说服了,因此你很难有动力继续找下去,可是真实状况跟它有误差,可是误差不大,因此又很难把你说服回来,只有隐隐的不对劲,这个时候你离真实最近,也离真实最远)


那就顺便说说它为何是对的,也就是用session作的另外一件有用的事:


给每一个session一个ID,一方面用来方便本身查询,另外一方面把这个ID给用户,用户下一次访问的时候就能够不用用户名和密码,而是直接使用这个ID来代表本身的身份


首先,这个ID安全吗?这个ID比直接传用户名和密码安全吗?


你很容易会想到,原本用户名和密码的组合还特意设置地比较复杂,你这换一组数字就代替了,是否是太不安全了?咱们知道http协议自己是彻底不加密的,若是使用用户名和密码,第一次访问是放在http头中,后边自动保存了密码就会放在cookie中,这些都彻底没有加密,它的安全性基本为0,就是裸奔了,只要被窃取,那就丢失了因此,就这个意义来说,sessionID的安全性跟使用用户名和密码没什么区别可是其实,虽然http自己不能加密,可是有些软件什么的,能在应用层面手动给你加密,好比QQ就会使用户名密码加临时验证码联合哈希,sessionID加一个时间戳简单加密也是很是经常使用的方法并且由于sessionID自己有有效期,即便丢了,也可能很快失效,形成的损失可能没那么大,而用户名跟密码丢了,那就大了

因此总结就是:不严格加密的sessionID和用户名和密码同样,都不太安全;可是相比较来讲,sessionID要安全一些;而使用https是彻底安全的


而后,使用sessionID有哪些好处?

  • 方便直接根据ID查询用户对应的session
  • 加密的时候计算量小
  • 安全性不会下降,甚至还更高一些


OK,经过独立地解决纯http机制会产生的问题,咱们探讨了cookie和session机制的本质。


并且想到:【使用http协议,服务器中不会保存客户端的状态】所产生的问题经过增长cookie和session机制解决了,是否是就意味着这个【状态】跟cookie和session的关系很是紧密?


因此这个无状态指的是【没有对 本次会话 设置一个缓存区,记录此次会话的状态,缓存区包括服务器端和用户端】但好像仍是没有点破关键(主要是以为跟前面那些官方对状态的说法不太吻合,甚至没有对应关系)

 

突然我想到一个问题:一个有状态的http是什么样的?


很难直接想象有状态的http是什么样,由于http这种机制是自然无状态的


那就类比一下吧,另外一个自然有状态的机制叫TCP


若是有状态的意思是它的每次请求是有联系的,那么有状态的TCP的样子是:假如一份数据分了三份TCP包发送,那这个包上面会标明这是第几个包,会标明这个包跟那几个包是有联系的,有什么联系


但好像这个有状态的TCP跟咱们想要的有状态的HTTP没有关系,由于即便每次http请求之间互相有联系,它也不能解决上面提到的http无状态的问题


诶,等等,好像能类比:


假如每一个http链接都有一个签名,因而第一次登录成功以后,服务器就知道了这个签名是容许登录的,因而以后全部一样签名的http链接都能登录,这里利用了同一个用户发出的http链接之间的同主人关系,这里解决了一个保持登陆状态的问题


一样,来尝试利用这个【每次http请求之间互相有联系】来解决上面碰到的那个问题【每一次操做都要与系统底层的数据库进行交互】,但想了半天确实没法进行下去


不过我灵机一动,从另外一个角度来想,好像解决了这个问题:


1. 只有【每次http请求之间互相有联系】这个条件,没法解决【每一次操做都要与系统底层的数据库进行交互】


2. 由于很明显,要解决【每一次操做都要与系统底层的数据库进行交互】就必须在服务器端开辟一块缓存区


3. 不过若是你思考一下如何实现【每次http请求之间互相有联系】,你就会发现,它也须要在服务器端开辟一块缓存区


4. 因此【在服务器端开辟一块缓存区】才是真正的条件,也就是说,它确实等价于【有状态】


5. 并且我也找到了这个【在服务器端开辟一块缓存区】的条件跟前面那些官方对状态的说法对应的点,那就是:


经过在服务器端开辟一块缓存区,存储、记忆、共享一些临时数据,你就能够:

  • 协议对于事务处理有记忆能力【事物处理】【记忆能力】

  • 对同一个url请求有上下文关系【上下文关系】

  • 每次的请求都是不独立的,它的执行状况和结果与前面的请求和以后的请求是直接关系的【不独立】【直接关系】

  • 服务器中保存客户端的状态【状态】


因此,这个状态,加上前面说的客户端也有cookie,就是指,客户端和服务器在临时会话中产生的数据!而前面也说道了,使用缓存区保存临时会话中的数据是多么重要


  • 因此状态不只包括不一样URL访问之间的关系,还有对其余URL访问的数据记录,还有一些其余的东西,因此更确切地说,状态应该是【实现了这些东西所凭借的后面的缓存空间】中的客户的临时数据


  • cookie和session应该是彻底实现了有状态这个功能


 

一种常见的对状态的误解:

1. 有人在解释HTTP的无状态时,把它跟有链接对立,说是两种方式,也就是若是想不无状态,就必须有链接,但其实否则


2. 有链接和无链接以及以后的Keep-Alive都是指TCP链接


3. 有状态和无状态能够指TCP也能够指HTTP


4. TCP一直有状态,HTTP一直无状态,可是应用为了有状态,就给HTTP加了cookie和session机制,让使用http的应用也能有状态,但http仍是无状态


5. 开始TCP是有链接,后来TCP无链接,再后来也就是如今TCP是Keep-Alive,有点像有链接

相关文章
相关标签/搜索