面试官问:Http请求中如何保持状态?
共 3158字,需浏览 7分钟
·
2020-08-16 06:11
这是一个被无数程序员撸过的问题,却只有少数人了解了真相。大体上搜了一下,网上关于http协议保持状态误导大家的文章还是有的,比如:有人说利用ViewState,那是asp.net下独有的东西,请注明“asp.net下如何保持状态”!!
关于用户认证方案可以查看以前的文章:
程序员过关斩将--cookie和session的关系其实很简单
http协议相对我们的年龄来说,是一个比较古老的协议,它的诞生之初是为了能让人们在互联网的领域自由冲浪。到了现代,http协议不谦虚的讲,已经成为了分布式网络的基础之一,从最初的1.0版本到现在的2.0乃至研发中的3.0,它在分布式通信领域已经越来越重要。
无论http协议什么样的文章,都需要把http大体说上一下,这里就简单啰嗦几句
http协议在报文的编码方式上采用了文本方式,通信上采用客户端到服务器的请求-响应方式。
http协议是基于tcp协议之上的应用层协议,所以它的传输速度注定会收到tcp协议的约束。有人说http协议采用文本协议是一个天大的错误,我不这么认为,首先在http协议被发明之初,可供的选择并不多,在当时看来,文本协议已经是比较好的选择了。其次,文本协议除了在传输性能上比二进制方式差一些,其他都还好,尤其是在数据的直观性上,很容易被我们理解。尤其是程序员,在看到http的请求和返回文本内容的时候,就可以大体猜出很多东西。
在我看来,http最大的缺陷在于交互中的设计,换句话说,http的状态保持问题,才是在我们平时开发中面临的最大问题。http天生是无状态的,但这并不意味着不能解决。
为什么我们要保持状态呢?根本原因在于现在的互联网的交互需求。什么是保持状态呢?通俗来讲,客户端发起的http请求,服务端需要知道来自于哪个客户端。设想,如果没有状态,当你逛淘宝的时候,剁手下了单,服务器怎么知道是你下的单呢?如果把你的单发给别人,你是不是要去骂娘了呢?
说到http保持状态,我有一点要声明,http和浏览器是有区别的,浏览器只不过是利用http协议来进行通信,有不少同学一提到http协议,就以浏览器来举例,这个是不健全的
http协议要想保持状态,无非就是利用http协议本身定义的那些属性来实现。比如:Header,Body ......只要服务器能识别,理论上就可以作为保持状态的凭据
http保持状态最简单并且最粗暴的莫过于直接采用参数了。服务器把参数凭据通过http协议下发给客户端,客户端无论存储到哪,只要下次请求把这个参数携带上,服务器就可以根据约定读取相应的参数来进行识别。
这种方式目前大多数用来保持那些非敏感信息,比如最常见的分页参数
https://www.cnblogs.com/#p2
有人会有疑问?分页参数也算是状态吗?虽然大多数的文章中所说的状态是指用户的登录状态,但是从状态的抽象定义上来看,分页也算是一种状态的定义。而用户身份状态的保持,由于涉及到隐私,一般不会采用url参数的方式来维持。
Cookie是http请求中header中的一个属性,它保存在客户端。
很多文章里,都说Cookie是服务端下发给客户端的,你们这样说是不是不太好?Cookie本质是上客户端的东西,客户端不能自己创建Cookie吗?客户端当然可以自己创建Cookie!!只不过在用户进行认证的流程中,标识用户身份的cookie是服务器下发的,所以在介绍Cookie本身定义的时候请不要误导别人。
利用Cookie来保持http的状态是现在很常见的解决方案,其中的一个原因是:在浏览器中没有跨域的情况下,浏览器会在http请求中自动携带cookie,非常方便。在非浏览器环境中,可能需要写代码来保证每次都携带对应的cookie。
服务端在接收到http请求,解析对应的cookie即可得到需要保持的状态标识。说到服务端,不少人提到了session会保持http状态,这是不是又不太好了,首先session本质上是一个抽象的概念,其次我们平时所说的用户信息等session是属于服务端的kv数据,不同的客户端可以识别不同的session本质上也是通过cookie机制来实现,我认为那些说session可以保持http状态的说法是不明确的。
除了以上两种方式还有其他方式可以保持http的请求状态吗?当然有!!
http状态的保持需要客户端和服务端同时协作来保证,如果客户端上传了cookie,但是服务端不能正常解析,这也算不上状态的保持。理论上服务端只要能识别http请求中携带的某些数据,就能达到保持状态的目的。
在浏览器中,受限于每个浏览器的功能,浏览器发送一个http请求,自动携带的只有规定的那些header和body数据,而多数header只能携带协议规定的那些固定值,这也是浏览器中要想保持http状态方案少的原因之一。body一般用在post的http请求中,所以它的应用场景是有限的。
关于http的header的属性有很多,有兴趣的同学可以去研究一下。这里提及一个“Authorization”,从字面意思就可以知道它和认证相关,当我们要保持http请求中用户的登录状态时候可以用此字段。那保持其他状态是否可以用呢?当然可以,header中的那些值本质上对于服务端来说就是kv数据,这些数据用于什么用途,每个业务都可以灵活控制。比如:通常情况下,“Authorization”这个header用于用户认证,那我可不可以用于识别是A页面还是B页面呢,当然可以,只要客户端在不同的页面上传不同的“Authorization”值,然后服务端去识别这些值就可以了。
从来没有人说过http协议只能用于客户端和服务端。服务端和服务端通信同样能够使用http协议,而且现在很多分布式系统都是这样来通信的。至于服务端和服务端通信,那http协议保持状态就更加灵活了(这里针对浏览器来比较),请求方和接受方可以约定任意的header头来标识状态,这还要得益于http协议header头可以自定义的特性。比如:如果喜欢“XXOO”,完全可以采用“XXOO”的header来标识状态
Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language:
.
.
.
XXOO:10次/天
每个问题的解决方案有很多,没有完美的方案,只有最适合业务场景的方案。认清技术的本质,才是我们提高自身技能的捷径。能力有限,技术无限,欢迎批评指正!
往期推荐