HTTP的主要特点
支持客服/服务器模式:HTTP协议工作于客户端/服务器的架构之上,浏览器作为HTTP客户端通过URL向HTTP服务端发送请求,web服务器根据接受到的请求向客户端发送响应信息;
简单快速:客户端向服务器请求服务的时候,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST,每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记;
无连接:无连接即限制每次连接只处理一次请求,服务器处理完客户的请求并收到客户的应答之后便断开连接,采用这种方式可以节省传输时间。从HTTP 1.1 默认使用了长连接,即服务器需要等待一定的时间后才断开连接,以保证连接特性。虽然目前的技术如 Keep-Alive使用长连接优化效率,但这些都处于HTTP请求之外的,也就是说在每一个独立的HTTP请求中是无法得知当前请求的HTTP是否处于长连接的状态。我们始终认为HTTP请求在结束后连接就会关闭,这是HTTP的特性,至于下层实现是否在结束请求之后关闭连接都不会关闭这个特性。Keep-Alive可以理解为下层实现对上层是透明。
无状态:HTTP协议是无状态协议,无状态是指协议对于事物处理没有记忆能力,缺少状态意味着如果后续处理需要前面的信息则必须被重传。这样可能导致每次传输的数据量增大,另一方面,在服务器不需要先前的信息时它的应答会变快。
HTTP请求头部
客户端发送一个HTTP请求到服务器的请求消息结构如下,主要由请求行、请求头部、空行、和请求正文这四个部分组成。
请求行主要由请求方法(GET/PST..)、URL、协议版本号(1.0/1.1/2.0)三个部分组成,最后需要一个回车换行标志;
请求头部由若干个报头组成,每个报头的结构都是头部名字+ : + 空格 + 值这样的形式,名字与大小写无关,这些请求头部用来设置HTTP请求的一些参数;
请求正文即数据体,该数据体只在POST请求中用到,表示要上传的数据;
请求正文和请求头部之间有空行,即浏览器发送一个空白行来通知服务器它已经结束了该请求头部的发送;
HTTP响应结构
服务器接收并处理客户端发送过来的请求后会返回一个HTTP的响应消息即HTTP响应报文,HTTP的响应报文如下:
HTTP的响应报文主要由状态行、响应头部、响应正文三部分组成;
状态行主要由协议版本号、状态码、状态码描述三部分组成;
响应头部主要用于描述服务器的基本信息,以及数据的描述,由响应头字段名字以及对应的值组成;
HTTP请求/响应的步骤
- 客户端连接到Web服务器(建立TCP连接)
- 发送HTTP请求
- 服务器接受请求并返回HTTP响应
- 释放TCP连接
- 客户端浏览器解析HTML内容
首先客户端连接Web服务器(一个HTTP客户端通常是浏览器),与Web服务器的HTTP端口(默认80)建立一个TCP套接字连接;然后发送HTTP请求(HTTP 协议是建立在 TCP 协议之上的应用层协议,其本质是在建立起的TCP连接中,按照HTTP协议标准发送一个索要网页的请求),即通过TCP套接字,客户端向Web服务器发送一个文本的请求报文;之后服务器接受到来自客户端的请求并返回HTTP响应,Web服务器解析该请求,定位请求资源,并将资源副本写到TCP套接字,由客户端读取;之后会释放TCP连接(若连接模式为Close,则服务器主动关闭TCP连接,客户端被动关闭连接,若连接模式为Keep-Alive,则该连接会保持一段时间,在该时间内服务器可以继续接收请求);最后客户端就拿到了HTML相关内容并进行解析,客户端浏览器首先去解析状态行,查看表明请求是否成功的状态代码,然后解析每一个响应头,响应头告知以下为若干字节的HTML文档及文档的字符集,客户端浏览器读取响应数据HTML,并根据HTML语法对其进行格式化,最后在浏览器窗口中显示。
在浏览器地址栏键入URL,按下回车后经历的流程
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- TCP连接断开
首先浏览器会依据URL逐层查询DNS如期缓存,解析URL中的域名所对应的IP地址,DNS缓存从近到远,依次是浏览器缓存、系统缓存、路由器缓存、IPS服务器缓存、根域名服务器缓存、顶级域名服务器缓存,从哪个缓存找到对应的IP则直接返回,不再查询后面的缓存;找到IP地址之后,根据IP地址和对应的端口号与服务器建立TCP连接;之后浏览器会发送读取文件的HTTP请求,该请求将发送给服务器;服务器收到HTTP请求后处理请求并把对应的带有HTML文本的HTTP响应报文发回给浏览器;浏览器收到HTML并在显示窗口中去渲染(首先解析 HTML 文件构建 DOM 树,然后解析 CSS 文件构建渲染树,等到渲染树构建完成后,浏览器开始布局渲染树并将其绘制到屏幕上);最终浏览器与服务器通过四次挥手释放TCP连接;
HTTP请求方法
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
| 方法 | 描述 |
|---|---|
| GET | 请求指定的页面信息,并返回具体内容,通常只用于读取数据。 |
| HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头。 |
| POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立或已有资源的更改。 |
| PUT | 替换指定的资源,没有的话就新增。 |
| DELETE | 请求服务器删除 URL 标识的资源数据。 |
| CONNECT | 将服务器作为代理,让服务器代替用户进行访问。 |
| OPTIONS | 向服务器发送该方法,会返回对指定资源所支持的 HTTP 请求方法。 |
| TRACE | 回显服务器收到的请求数据,即服务器返回自己收到的数据,主要用于测试和诊断。 |
| PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新。 |
GET请求和POST请求的区别
- GET将请求信息放到URL中;POST放在报文体中;
- GET提交的数据大小有限制;POST提交的数据没限制;
- GET符合幂等性和安全性;POST不符合;
- GET可以被缓存;POST不行;
注解
由于GET请求是将请求信息放到URL中的,所以对长度有限制。虽然URL本身并没有长度的限制,但是浏览器会对URL有长度有所限制;
从数据库层面看,GET请求符合幂等性和安全性。幂等性即对数据库的一次操作和多次操作获得的结果是一致的,安全性即对数据库的操作没有改变数据库中的数据。GET请求是做查询操作的,因此不会改变数据库原有的数据,大致可以认为GET请求符合幂等性和安全性。POST请求则既不幂等也不安全,因为POST请求往往是向数据库中提交数据,因此会改变数据库中的数据。同时POST请求每次获得的结果也可能不同,因为POST请求是作用到上一层的URL上的,即每一次请求都会添加一次新的资源。
GET请求可以被缓存,可以保存在浏览器的浏览记录中,以GET请求的URL能够保存为浏览器书签。这也是GET请求被广泛使用的原因。
HTTP状态码
HTTTP态码共有 5 种类型:
| 类别 | 分类描述 |
|---|---|
| 1xx | 指示信息->表示请求已接受,继续处理 |
| 2xx | 成功-> 表示请求已被成功接收、理解、接受 |
| 3xx | 重定向-> 要完成请求必须进行更进一步的操作 |
| 4xx | 客户端错误-> 请求有语法错误或请求无法实现 |
| 5xx | 服务器端错误-> 服务器未能实现合法请求 |
常见的HTTP状态码
| 状态码 | English Name | 描述 |
|---|---|---|
| 100 | continue | 继续。客户端继续处理请求 |
| 101 | Switching Protocol | 切换协议。服务器根据客户端的请求切换到更高级的协议 |
| 200 | OK | 请求成功。请求所希望的响应头或数据体将随此响应返回 |
| 301 | Moved Permanently | 永久移动。请求的资源已被永久地移动到新 URI,返回信息会包含新的 URI,浏览器会自动定向到新 URI |
| 302 | Found | 临时移动。与 301 类似。但资源只是临时被移动,客户端应继续使用原有URI |
| 400 | Bad Request | 客户端请求的语法错误,服务器无法理解;请求的参数有误 |
| 401 | Unauthorized | 当前请求需要用户验证 |
| 403 | Forbidden | 服务器已经理解请求,但是拒绝执行它 |
| 404 | Not Found | 请求失败,请求所希望得到的资源未被在服务器上发现 |
| 500 | Internal Server | 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理 |
| 501 | Not Implemented | 服务器不支持当前请求所需要的某个功能 |
| 502 | Bad Gateway | 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到无效的响应 |
| 503 | Service Unavailable | 由于临时的服务器维护或者过载,服务器当前无法处理请求,一段时间后可能恢复正常 |
| 504 | Gateway Time-out | 充当网关或代理的服务器,未及时从远端服务器获取请求 |
HTTP版本间的区别
HTTP/1.1 和 HTTP/1.0 的区别
缓存处理:在 HTTP/1.0 中主要使用 header 里的 if-modified-Since, Expries 来做缓存判断的标准。而 HTTP/1.1 请求头中添加了更多与缓存相关的字段,从而支持更为灵活的缓存策略,例如 Entity-tag, If-Unmodified-Since, If-Match, If-None-Match 等可供选择的缓存头来控制缓存策略。
节约带宽: 当客户端请求某个资源时,HTTP/1.0 默认将该资源相关的整个对象传送给请求方,但很多时候可能客户端并不需要对象的所有信息。而在 HTTP/1.1 的请求头中引入了 range 头域,它允许只请求部分资源,其使得开发者可以多线程请求某一资源,从而充分的利用带宽资源,实现高效并发。
错误通知的管理:HTTP/1.1 在 1.0 的基础上新增了 24 个错误状态响应码,例如 414 表示客户端请求中所包含的 URL 地址太长,以至于服务器无法处理;410 表示所请求的资源已经被永久删除。
Host 请求头:早期 HTTP/1.0 中认为每台服务器都绑定一个唯一的 IP 地址并提供单一的服务,请求消息中的 URL 并没有传递主机名。而随着虚拟主机的出现,一台物理服务器上可以存在多个虚拟主机,并且它们共享同一个 IP 地址。为了支持虚拟主机,HTTP/1.1 中添加了 host 请求头,请求消息和响应消息中应声明这个字段,若请求消息中缺少该字段时服务端会响应一个 404 错误状态码。
长连接:HTTP/1.0 默认浏览器和服务器之间保持短暂连接,浏览器的每次请求都需要与服务器建立一个 TCP 连接,服务器完成后立即断开 TCP 连接。HTTP/1.1 默认使用的是持久连接,其支持在同一个 TCP 请求中传送多个 HTTP 请求和响应。此之前的 HTTP 版本的默认连接都是使用非持久连接,如果想要在旧版本的 HTTP 协议上维持持久连接,则需要指定 Connection 的首部字段的值为 Keep-Alive。
HTTP/1.0/1.1 和 HTTP/2.0 的区别
二进制分帧:相比于 HTTP/1.X 的文本(字符串)传送, HTTP/2.0 采用二进制传送。客户端和服务器传输数据时把数据分成帧,帧组成了数据流,流具有流 ID 标识和优先级,通过优先级以及流依赖能够一定程度上解决关键请求被阻塞的问题。
多路复用:HTTP/2.0 支持多路复用。因为流 ID 的存在, 通过同一个 HTTP 请求可以实现多个 HTTP 请求传输,客户端和服务器可以通过流 ID 来标识究竟是哪个流从而定位到是哪个 HTTP 请求。
头部压缩:HTTP/2.0 头部压缩。HTTP/2.0 通过 gzip 和 compress 压缩头部然后再发送,同时通信双方会维护一张头信息表,所有字段都记录在这张表中,在每次 HTTP 传输时只需要传头字段在表中的索引即可,大大减小了重传次数和数据量。
服务器推送:HTTP/2.0 支持服务器推送。 服务器在客户端未经请求许可的情况下,可预先向客户端推送需要的内容,客户端在退出服务时可通过发送复位相关的请求来取消服务端的推送
Cookie与Session
因为HTTP是无状态的,理论上意味着我们每次访问有登录需求的页面的时候都需要不厌其烦的输入用户名和密码,但是实际上我们并没有如此操作的原因是引入了Cookie与Session机制。Cookie与Session弥补了HTTP无状态的不足,使HTTP具有了状态性。
Cookie
Cookie技术是客户端的解决方案,Cookie就是由服务器发送给客户端的特殊信息,而这些信息以文本文件的形式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊信息。
当用户使用浏览器访问一个支持Cookie的网站时,用户提供一个包括用户名在内的个人信息并提交至服务器,接着服务器在向客户端发送超文本的同时也会发回这些信息。当然这些信息并不存在HTTP的响应体中,而是存在HTTP的响应头中。当用户浏览器接收到来自服务器的响应后,浏览器会将这些信息存放一个统一的位置,至此客户端再向服务器发送请求时,都会把相应的Cookie再次发送到服务器中,而这次Cookie信息则存在HTTP请求头里了。 有了Cookie这样的技术实现,服务器在接受到来自客户端浏览器的请求之后就能够分析存放在请求头中的Cookie,得到客户端特有的信息,从而动态生成与该客户端相对应的内容。
Cookie的设置及发送过程如下:
Session
Session机制是一种服务器端的机制,服务器使用了一种类似于散列表的结构来保存信息,当程序需要为某个客户端请求创建一个Session的时候,服务器首先检查这个客户端的请求里是否含有Session标识(即为session id),如果已包含则说明以前已经为此客户端创建过Session,服务器就按照session id把session检索出来使用,若检索不到,可能新建一个。如果客户端请求不包含session id 则为客户端创建一个Session,并生成一个与此Session相关的 session id。(session id的值为一个既不会重复又不容易被找到规律的字符串)这个session id 将会在本次响应中发给客户端进行保存。
Session的实现方式
- 使用Cookie来实现
- 使用URL回写来实现
使用Cookie来实现服务器给每个Session 分配一个唯一的 JSESSIONID并通过Cookie发送给客户端,当客户端发送新的请求的时候,将在Cookie头中携带JSESSIONID,这样服务器就可以找到客户端对应的Session了。
URL回写是指服务器在发送给浏览器页面的所有链接中都携带JSESSIONID的参数,这样客户端点击任何一个链接都会把JSESSIONID带回服务器。如果直接在浏览器输入服务器资源的URL来请求该资源,那么Session 是匹配不到的。Tomcat对Session的使用是一开始同时使用Cookie和URL回写的,如果发现客户端支持Cookie就继续使用Cookie停止使用URL回写;如果发现Cookie被禁用,就一直使用URL回写。不管是Cookie还是Session都和 JSESSIONID息息相关。
Cookie与Session的区别
- Cookie数据存放在客户的浏览器上,Session数据存放在服务器上
- Session相对于Cookie更安全
- 若考虑减轻服务器的负担,应当使用Cookie
Cookie的数据存放在客户的浏览器上,不安全,别人可以分析存放在本地的Cookie并进行Cookie欺骗,考虑到安全应当使用Session,但是Session会在一定时间内保存在服务器上,当访问增多会比较占用服务器的性能,考虑到减轻服务器性能方面的开销,可以使用Cookie
数据加密技术
- 单向加密:哈希算法,将任意长度的信息转换成固定长度的值,算法不可逆
- 对称加密:加密和解密都使用同一个密钥
- 非对称加密:加密使用的密钥和解密使用的密钥是不同的即公钥与私钥
- 数字签名:证明某个消息或者文件是某人发出/认同的
单向加密
单向加密又称不可逆加密,通常采用了哈希算法,即明文被加密成密文后,无法再解密回明文。
- 同一明文对应同一密文
- 对明文进行微小修改,密文即会发生极大变化
- 对于不同的明文,产生的密文是定长的
在加密领域,单向加密经常用于存放用户的密码,以实现即使数据库数据完全泄露被获取,也无法直接用于登录。
对称加密
对称加密即为明文可以使用密钥加密成为密文,也能使用同一个密钥将密文解密回明文的方式。
- 加密解密的速度快,因此适合数据量大的时候使用
- 同一明文不一定都应同一密文,由加密算法决定
常用对称加密的场景有
- 服务端用于保存涉及用户隐私的数据,服务端自动进行数据加密
- 进行网络传输时,依赖其他方式进行密钥交换后,使用密钥进行对称加密解密(如SSL/TLS传输机制)
常见的对称加密算法有:DES、AES、SM4(国密),而同一加密算法又有不同的加密模式。
非对称加密
不同于对称加密,非对称加密拥有一对密钥,分别是公钥和私钥,公钥和算法是公开的,私钥是保密的。使用其中一个密钥加密后的密文必须使用另一个密钥来解密。
- 非对称加密算法的性能大大弱于对称加密,不建议采用非对称加密算法加密大量的用户数据
- 由于其加密特性,非对称加密算法加密的数据长度有限
使用场景:
- 客户端利用公钥给数据加密,传输给拥有私钥的服务端进行解密。由于只是私钥可以解密该数据,该密文即使在传输过程中被截获也不会有泄露的风险。
- 服务端对于一段明文传输的数据,先用哈希算法产生摘要信息,之后用私钥对于摘要信息进行加密产生一个数字签名。客户端收到这段明文数据和对应数字签名后,可以利用公钥来验证这段明文数据的完整性。
常用的非对称加密的算法有:RSA、ECC、SM2
数字签名
签名就是在信息的后面加一段内容,这些内容是经过哈希后的值,可以证明信息没有被修改。哈希值一般都会加密后再和信息一起发送,以保证这个哈希值不被修改。
数字签名的流程
- 创建数据密钥对
- 一段数据利用哈希算法获得数据摘要,再用明文私钥获得哈希值的签名
- 此后用户可以将这段数据和签名一同分发给任何拥有公钥的人
HTTPS
HTTPS为超文本传输安全协议,是一种以计算机网络安全通信为目的的传输协议,在HTTP下面加入了SSL层,从而具有了保护交换数据隐私以及完整性的功能,还提供对网站服务器身份认证的功能,即安全版的HTTP。
SSL(Security Sockets Layer-安全套接层)
- 为网络通信提供安全及数据完整性的一种安全协议
- 操作系统对外提供的API,SSL 3.0后更名为TLS
- 采用身份验证和数据加密保证网络通信的安全性和数据的完整性
”劫持“ :HTTP抓包的相关协议中,不管是GET请求还是PSOT请求,客户端与服务器之间都没有任何身份认证的过程,数据全部明文传输,“裸奔”在互联网上,所以客户端发出的请求很容易被黑客截获,如果此时黑客冒充服务器,即可以返回任何数据给客户端而不被客户端察觉。
HTTPS的加密方式
HTTPS 采用对称加密和非对称加密相结合的方式,首先使用 SSL/TLS 协议进行加密传输,为了弥补非对称加密的缺点,HTTPS 采用证书来进一步加强非对称加密的安全性,通过非对称加密,客户端和服务端协商好之后进行通信传输的对称密钥,后续的所有信息都通过该对称秘钥进行加密解密,完成整个 HTTPS 的流程。
HTTPS数据传输流程
- 浏览器将支持的加密算法信息发送给服务器
- 服务器选择一套浏览器支持的加密算法,以证书的形式回发浏览器
- 浏览器验证证书合法性,并结合证书公钥加密信息发送给服务器
- 服务器使用私钥解密信息,验证哈希,加密响应消息回发浏览器
- 浏览器解密响应消息,并对消息进行验真,之后进行加密交互数据
HTTP与HTTPS的区别
- HTTPS需要到CA申请证书,HTTP不需要;
- HTTPS密文传输,HTTP明文传输;
- 连接方式不同,HTTPS默认使用443端口,HTTP使用80端口;
- HTTPS = HTTP + 加密 + 认证 + 完整性保护,较HTTP安全;
- HTTP 页面响应比 HTTPS 快,主要因为 HTTPS 除了 TCP 的 3 次握手,还需要经历一个 SSL 协商过程;
Socket
Socket和TCP/IP协议没有必然的联系,只对TCP/IP协议的抽象,是操作系统对外开放的接口。方便程序员更方便的使用TCP/IP协议。
Socket起源于Unix,而Unix遵从一切皆文件的哲学,Socket是一种从打开到读和写再到关闭的这种模式去实现的。服务器和客户端各自维护一个文件,在建立连接打开后,可以向自己的文件写入内容供对方使用,在通信结束时就会关闭文件。
套接字的三种类型
流套接字(SOCK_STREAM):流套接字基于 TCP 传输协议,主要用于提供面向连接、可靠的数据传输服务。由于 TCP 协议的特点,使用流套接字进行通信时能够保证数据无差错、无重复传送,并按顺序接收,通信双方不需要在程序中进行相应的处理。
数据报套接字(SOCK_DGRAM):和流套接字不同,数据报套接字基于 UDP 传输协议,对应于无连接的 UDP 服务应用。该服务并不能保证数据传输的可靠性,也无法保证对端能够顺序接收到数据。此外,通信两端不需建立长时间的连接关系,当 UDP 客户端发送一个数据给服务器后,其可以通过同一个套接字给另一个服务器发送数据。当用 UDP 套接字时,丢包等问题需要在程序中进行处理。
原始套接字(SOCK_RAW):由于流套接字和数据报套接字只能读取 TCP 和 UDP 协议的数据,当需要传送非传输层数据包(例如 Ping 命令时用的 ICMP 协议数据包)或者遇到操作系统无法处理的数据包时,此时就需要建立原始套接字来发送。
Socket通信流程
服务器首先创建socket后,再为socket绑定IP地址和端口号,接着服务器的socket会开始监听端口号的请求,随时准备接收来自客户端的请求,这时候服务器的socket只是处于listen()状态并没有打开;
假设此时客户端创建socket,然后打开socket,并根据服务器的IP地址和端口号尝试去连接服务器的socket;
服务器的socket接收到来自客户端的socket请求后被动打开,开始接收客户端的请求直到客户端返回连接信息,这时服务器的socket进入到阻塞状态accept(),(处于阻塞状态需要一直等到客户端返回连接请求信息后才返回) 同时开始接收下一个客户端的连接请求;
客户端连接成功后,会向服务器发送连接状态信息,服务器接收到连接状态信息后就会将accept()方法返回,提示连接成功。
连接成功之后客户端就可以向socket中写入信息,服务器就能收到并读取相关信息。最后在发送完数据后,客户端就会关闭socket,紧接着服务端也需要关闭socket.
参考资料