HTTP请求

认识请求"报头"

header的整体的格式也是"键值对"的结构.

每个键值对占一行,键和值之间使用分号进行分割.

报头的种类有很多,此处仅介绍几个常见的. 

Host

 表示服务器主机的地址和端口.(Host和URL中的ip地址端口啥的,绝大部分情况下都是一样的,少数情况可能不同).

Content-Length

表示body中的数据长度.(如果数据包没有body,则没有该字段).

可以通过这个长度来处理粘包问题,HTTP底层也是基于TCP的.连续传输多个HTTP数据报,此时接收方这边的接收缓冲区里就会积累多个包的数据,应用程序在读取这些数据的时候就需要明确包之间的边界.

如果是没有body的请求/响应,直接使用空行作为分隔符了. 如果有body,空行就不是结束标记了,从空行开始读取body,body要读取多长就取决于Content-Length.读完之后,这个包就结束了.

 Content - Type

表示请求的body中的数据格式,body是可以传输很多格式的,包括程序员自己约定的格式.(同上,数据包没有body,则没有该字段),以下是比较常见的选项.

(1)application/json:数据为json格式(body就是json),body格式形如

{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16

(2)application/x-www-form-urlencoded:form表单提交的数据格式, 是通过HTML中的form标签构造出来的一种格式.这个格式的特点,认为是把query string放到body里了.(这个也可以上传文件).body格式形如:

title=test&content=hello

(3)multipart/form-data:form表单提交的数据格式(在form标签中加上

enctyped="multipart/from-data",通常用于提交图片/文件.body格式形如:

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3Trw ------WebKitFormBoundaryrGKCBY7qhFd3TrwA Content-Disposition: form-data; name="text" title ------WebKitFormBoundaryrGKCBY7qhFd3TrwA Content-Disposition: form-data; name="file"; filename="chrome.png" Content-Type: image/png PNG ... content of chrome.png ... ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

User-Agent(简称UA)

表示浏览器/操作系统的属性. 形如:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/91.0.4472.77Safari/537.36

其中Windows NT 10.0; Win64; x64 表示操作系统信息. 

AppleWebKit/537.36 (KHTML, like Gecko)Chrome/91.0.4472.77Safari/537.36表示浏览器信息.

上古时期,UA是非常关键的部分,不同用户使用的上网设备,差异很大.(当年计算机发展日新月异),同一个时间段,新的和旧的会同时存在.如果你是一个程序员,要写一个网站.那么你写的网站是否要使用新的特性呢?使用新的特性,老的设备就无法正常打开;不使用新特性,你的网站就打不过竞争对手.

借助UA就能解决上述问题.

服务器此时就可以针对此时的UA信息进行判定,如果用户使用的是很老的设备,返回的页面就不包含新特性,确保这个页面能够正确访问出来;如果用户用的是新的设备,返回的页面就包含新特性,确保这个页面体验足够好.

但随着时间的推移,浏览器好像都差不多了,UA感觉好像无用武之地了? 其实仍然很有用.

PC 屏幕大,更宽/手机 屏幕小,更窄. 因此对应返回的页面布局就应该有差异.

UA里包含了系统信息,就可以判定系统是PC端的系统,还是移动端的系统.此时就可以根据这个信息来返回不同的页面了.(使用手机浏览器时,很多手机浏览器都有一个功能,手动修改UA,手动把UA改成PC的UA,就能访问电脑端的网页了).

但是,到后面又有一个问题,即使是手机和PC,各类也有许多不同的屏幕尺寸,再者,程序员认为同时维护两份代码也太麻烦了.  

于是引入了响应式布局(前端后来提出的解决上述问题的技术方案).通过一套代码,适应不同尺寸的显示器.

CSS3提供了一个特性,"媒体查询"可以感知到当前屏幕的尺寸,根据不同的尺寸,应用不同的样式. 现在也有越来越多的网站不再依赖UA进行区分了.

Referer

表示这个页面是从哪个页面跳转过来的.形如:

https://v.bitedu.vip/login

如果直接在浏览器中输入URL,或者直接通过收藏夹访问页面时是没有Referer.

Referer是否可以被篡改? 是的

解决方法:HTTPS -> SSL(网络加密协议).加密就可以把header和body加密,网络上传的也就是密文了.

Cookie

这是非常重要的报头属性. 本质:浏览器这边本地化存储数据(存储在硬盘里)的机制.

Cookie中存储了一个字符串,这个数据可能是客户端(网页)自行通过JS写入的,也可能来自于服务器(服务器在HTTP响应的header中通过Set-Cookie字段给浏览器返回数据).  HTTP请求中的Cookie字段,就是把本地存的Cookie信息发到服务器,HTTP响应中会有一个Set-Cookie字段,就是服务器告诉浏览器你要在本地存哪些信息.

往往可以通过这个字段实现身份标识的功能.

每个不同的域名下都可以有不同的Cookie,不同网站中的Cookie并不冲突.

浏览器作为电脑上的一个程序,可以直接读写本地磁盘文件.系统提供了api操作文件,作为一个程序可调用api操作. 

而浏览器上运行的网页,理论能通过浏览器提供的api读写本地文件,但是被浏览器禁止了(没有提供api),这是为了安全性.

但是确实,有些网站是要把一些信息保存到浏览器这边的,比如当前登录的用户身份信息. 浏览器选择退而求其次,给网页提供了这样的api,能够按照键值对格式有限度地存储数据,而不能随意地访问文件系统.

可以通过抓包观察页面登陆的过程(以码云为例):

在码云的页面上,点击URL左侧的图标,选择Cookie.

 

然后移除已经存在的Cookie:

 

2)登录操作

登录请求:

POST https://gitee.com/login HTTP/1.1 Host: gitee.com Connection: keep-alive Content-Length: 394 Cache-Control: max-age=0 sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91" sec-ch-ua-mobile: ?0 Upgrade-Insecure-Requests: 1 Origin: https://gitee.com Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/w Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: https://gitee.com/login Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 encrypt_key=password&utf8=%E2%9C%93&authenticity_token=36ZqO9tglSN6EB6pF6f2Gt%2B  

登录响应

HTTP/1.1 302 Found Date: Thu, 10 Jun 2021 04:15:58 GMT Content-Type: text/html; charset=utf-8 Connection: keep-alive Keep-Alive: timeout=60 Server: nginx X-XSS-Protection: 1; mode=block X-Content-Type-Options: nosniff X-UA-Compatible: chrome=1 Expires: Sun, 1 Jan 2000 01:00:00 GMT Pragma: must-revalidate, no-cache, private Location: https://gitee.com/HGtz2222 Cache-Control: no-cache Set-Cookie: oschina_new_user=false; path=/; expires=Mon, 10 Jun 2041 04:16:00 -0 Set-Cookie: gitee_user=true; path=/ Set-Cookie: gitee-session-n=M1Rhbk1QUUxQdWk1VEZVQ1BvZXYybG13ZUJFNGR1V0pSYTZyTllE X-Request-Id: 77f12d095edc98fab27d040a861f63b1 X-Runtime: 0.166621 Content-Length: 92 You are being redirected

可以看到,响应中包含了3个Set-Cookie属性.

 其中我们重点关注第三个.里面包含了一个gittee-session-n这样的属性,属性值是一串很长的加密之后的信息.这个信息就是用户当前登录的身份标识.也称"令牌(token)"

3)登录成功后,此时就可以看到后续访问码云的其它页面(比如个人主页),请求中就会带着刚才获取到的Cookie信息.

GET https://gitee.com/HGtz2222 HTTP/1.1 Host: gitee.com Connection: keep-alive Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/w Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91" sec-ch-ua-mobile: ?0 Referer: https://gitee.com/login Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: oschina_new_user=false; user_locale=zh-CN; yp_riddler_id=1ce4a551-a160-4 

请求中的Cookie字段也包含了一个gitee-session-n属性,里面的值和刚才服务器返回的值相同.后续只需要访问gitee网站,就会一直带着这个令牌,直到令牌过期/下次重新登陆. 

理解登录过程

 

这个过程和去医院看病很相似.

1.到了医院先挂号.挂号时需要提供身份证,同时得到了一张"就诊卡",这个就诊卡就相当于患者的"令牌"

2.后续去各个科室进行检查,诊断,开药,都不必再出示身份证了,只需要凭就诊卡即可识别处当前患者的身份.

3.看完病之后,又不想要就诊卡了,就可以注销这个卡,此时患者的身份和就诊卡的关联就销毁了.(类似于网站的注销操作).

4.又来看病,就可以办一张新的就诊卡,此时就得到了一个新的"令牌". 

关于Cookie的几个重要结论.

1.Cookie从哪来?服务器返回给浏览器的,通常都是首次访问/登陆成功之后.

2.Cookie到哪去?Cookie会存储在浏览器本地主机的硬盘上,后续每次访问服务器都会带上Cookie.

3.Cookie中存什么?键值对格式数据,这里的内容由程序员定义,和query string一样外人无从了解.

4.Cookie在浏览器中如何组织?在硬盘本地中保存,按照不同域名为维度存储.比如一个浏览器,有一组cookie访问搜狗的,有一组访问百度的.

5.Cookie用途: 在客户端保存数据 -> 最重要的是保护用户的身份标识,服务器就可以通过标识区分用户了.一些其它的业务数据一般不存放在Cookie中.Cookie可以随时删除. 因为业务是存储在浏览器中,通过相同的cookie身份标识可以找到对应数据. 

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。