推荐 最新
三千米的偷感

如何发送这样一个http请求?

问题如题: 如何发送这样一个http请求? https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250101/1277c49ee4fa149c4a55ed3334eb75d6.png 尝试: 1.我使用hutool工具的form方法时并没有找到设置content-type的参数。 2.查看请求报文 https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250101/b17cc9b80a89635eae9f88ca5cf9c07a.png 3.发现表单中的部分其实是请求体body,按照格式构造一个相似的字符串作为body调用接口,但是不行,可以看出字符串的高亮和表单时并不一样,而且content-type也不一样。 https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250101/255bcbe554cf0795909231b199c2ce43.png 4.后端接口,主要是需要提供一个上传文件,并且可以携带复制参数(参数中有map)的接口 https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250101/8188fe6073d4e28a3b79bb454d068e2b.png https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250101/451dfdca3eda1b19698a5b587a80aed1.png 5.目前调用方也是使用Java发送这样的http请求,不过目前确实才疏学浅,真的不会,最差就只能换种方式了。

16
1
0
浏览量368
云卿山手

前端如何向后端发送符合restful风格的url?

最近刚刚接触到restful风格,即将查增删改分别用get、put、delete、post方式发送 Java后端,对前端不太了解,比较好奇前端如何向后端发送上述四种请求?

15
1
0
浏览量419
爱喝奶茶的波波

【HTTP完全注解】我绝对要让你看懂HTTP报文🫵

HTTP报文格式HTTP报文是简单的、面向行的字符序列,它承载了HTTP客户端发送请求和服务器返回响应的所有信息,其格式至HTTP/1.0首次定义以来一直沿用至今。在HTTP/2之前,报文在传输过程中都是使用纯文本,而不是二进制,而HTTP又是使用明文传输,因此非常容易就能窃取HTTP报文中的内容。在 HTTP/2 中这些问题得到了改善,报文被嵌入到了一个新的二进制结构——帧中,虽然报文被嵌入到了新的结构中,但每条报文的语义依旧不变,因此用之前的报文格式来理解 HTTP/2 报文仍旧有效。HTTP报文有请求、响应两种类型,它们都由起始行、消息头与消息体构成:· 报文的第一行被称为起始行,起始行是必须存在的,它包含了请求/响应的基本信息· 报文的第二行至空白行被称为消息头,消息头有些是可选的,有些则是必须的,它包含了一系列的key:value键值对(key不区分大小写),用来描述请求或响应的附加信息· 报文的空白行后一行至最后一行被称为消息体,消息体是可选的,它用来携带请求或响应需要上传/响应的具体内容在请求报文中起始行、消息头与消息体又被称为请求行、请求头以及请求体。在响应报文中起始行、消息头与消息体又被称为响应行、响应头以及响应体。目前HTTP的起始行和消息头仍是使用ASCII编码,而消息体则是根据消息头中的内容协商来决定具体编码方式。起始行报文中的第一行被称为起始行,它是必须存在的,包含了请求/响应的基本信息。起始行在请求报文中被称为请求行,在响应报文中又被称为响应行。请求行与响应行有很大的差别:· 请求行由Method(请求方法)、Path(请求资源路径,通常是一个 URL)以及HTTP/Version(HTTP版本)组成,它们使用空格分隔,以此区别· 响应行由HTTP/Version(HTTP版本)、Code(状态码)以及Message(返回消息)组成,它们也使用空格分隔,以此区别。MethodHTTP 定义了9个请求方法,以表明要对给定资源执行的操作,每个HTTP请求报文都必须使用一个请求方法来告诉服务器应该执行什么样的操作。请求方法操作GETGET 方法用于请求获取指定资源的信息,GET 请求应该只被用于获取数据。HEADHEAD请求与GET请求类似,但是服务器在响应中只返回响应头部信息,而不返回实际的资源内容。HEAD请求常用于获取资源的元数据,如资源的大小、修改时间等,而不需要获取实际的资源内容,以减少不必要的数据传输。POSTPOST 方法用于向服务器提交数据,POST请求通常会对服务器状态进行修改。PUTPUT 方法用于向服务器上传或更新指定资源的内容,PUT请求通常用于更新已存在的资源,如果资源不存在,则可以创建一个新资源。DELETEDELETE 方法用于请求删除服务器上指定的资源。PATCHPATCH 方法用于对资源进行部分修改。OPTIONSOPTIONS方法用于获取服务器支持的请求方法和资源的通信选项,当发送一个OPTIONS请求时,服务器会返回一个包含允许的请求方法、支持的头部字段等信息的响应。TRACETRACE请求用于追踪请求-响应的传输路径。当发送一个TRACE请求时,服务器会原样返回请求中的数据,这样客户端就可以查看中间代理服务器对请求的修改情况,用于诊断和调试网络传输问题。CONNECTCONNECT请求用于在客户端和服务器之间建立隧道连接,以此进行加密通信或代理服务器的连接。请求方法可以被分为安全/不安全的方法、幂等/不幂等的方法以及可被缓存/不可被缓存的方法。幂等的请求方法幂等的请求方法指的是同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。 在正确实现的条件下, GET , HEAD、PUT、DELETE、OPTIONS以及TRACE等方法都是幂等的方法。其他方法不幂等的原因如下:· CONNECT方法因为它涉及建立网络连接,而连接的状态可能会因多次执行而不同,所以它并不是幂等的方法。· POST用于向资源提交数据,多次执行相同的POST请求通常会导致资源状态的改变,因为每次请求可能会创建新的资源或者对现有资源进行修改。但是,具体是否幂等取决于服务器的实现,有些服务器可以对相同的POST请求进行幂等处理。· PATCH方法用于对资源进行局部更新,多次执行相同的PATCH请求通常会产生相同的结果,因为它们只是更新资源的一部分。但是,具体是否幂等取决于服务器的实现,因为某些情况下,多次执行相同的PATCH请求可能会导致不同的结果,例如,如果同时有其他并发请求影响了资源的状态。是否幂等请求方法幂等GET、HEAD、OPTIONS、PUT、DELETE、TRACE不幂等PATCH、CONNECT、POST安全的请求方法安全的请求方法指这些方法不会修改服务器的数据以及改变服务器的状态,也就是说,这是一个对服务器只读操作的方法。不难发现在正确实现的条件下,GET、HEAD 、 OPTIONS、TRACE都是对服务器只读操作的方法,因此它们是安全的方法。所有安全的方法都是幂等的,但并非所有幂等方法都是安全的,例如,PUT 和 DELETE 都是幂等的,但不是安全的。是否安全请求方法安全GET、HEAD、OPTIONS、TRACE不安全POST、PATCH、PUT、DELETE、CONNECT可被缓存的请求方法HTTP协议定义了一些请求方法,其中一些方法通常可以被缓存。 可被缓存的请求方法是那些在满足特定条件下,可以被缓存代理服务器(如HTTP缓存)缓存的方法。以下是常见的能否被缓存的HTTP请求方法:· GET、HEAD和OPTIONS方法: GET、HEAD和OPTIONS方法通常被认为是可缓存的,因为它们是幂等且安全的,而且不会改变服务器状态。这意味着代理服务器可以缓存它们的响应,以提高性能并减轻服务器负载。· POST和PATCH方法:POST和PATCH方法的响应通常不会被缓存 ,因为它们通常用于向服务器提交数据,可能会改变服务器状态。然而,如果响应中指定了有效期(例如,通过Cache-Control头部)并设置了Content-Location头部,那么它们的响应可以被缓存。这种情况下,缓存代理服务器可以将响应缓存,并在之后的请求中使用。但这种情况下的缓存行为在实际应用中相对较少见,并且有些浏览器并不支持(例如Firefox 就不支持它Firefox bug 109553),因此通常不鼓励缓存POST请求的响应。· PUT和DELETE方法: PUT 和 DELETE 方法的响应通常不会被缓存,即使设置了有效期(通过Cache-Control头部)和Content-Location标头。这是因为这两个请求方法通常用于对资源进行修改或删除,可能会改变服务器的状态,因此响应不适合被缓存。· CONNECT 方法:CONNECT 方法的响应通常不会被缓存 ,即使设置了有效期(通过Cache-Control头部)和Content-Location标头。CONNECT 方法用于建立网络连接,通常用于代理服务器。由于 CONNECT 方法的目的是在客户端和目标服务器之间建立连接,而不是获取资源,所以 CONNECT 方法的响应通常不会被缓存。代理服务器通常不会缓存 CONNECT 方法的响应,因为它们不包含可被缓存的资源数据。· TRACE 方法:TRACE 方法的响应通常不会被缓存 ,即使设置了有效期(通过Cache-Control头部)和Content-Location标头。TRACE 方法用于在目标服务器上执行一个诊断测试,它返回由服务器收到的请求的副本。由于 TRACE 方法的主要目的是用于诊断和调试,而不是对服务器上的资源进行修改,因此 TRACE 方法的响应通常不会被缓存。代理服务器通常不会缓存 TRACE方法的响应,因为这些响应只包含请求的副本,不包含可被缓存的资源数据。能否缓存请求方法可被缓存GET、HEAD、OPTIONS可被缓存,但不鼓励且支持少POST、PATCH不可被缓存PUT、DELETE、CONNECT、TRACEPathPath请求资源路径用来表示要请求的资源的网络位置,Path有多种形式:它可以是一个相对URL、也可以是一个绝对URL、也可以仅由一个星号(*)组成。使用什么形式通常以请求方法、请求的环境为以及请求的格式来决定。Path的形式:相对URL: 这是最常见的形式,除了CONNECT方法都可以使用。/ /background.png /test.html?query=alibaba /anypage.html绝对URL: 主要在使用 GET 方法连接到代理时使用。https://wangjunliang.com/HTTP-Explanation/index.html https://wangjunliang.com/HTML-Guide/index.html包含端口的绝对URL: 在使用 CONNECT 建立 HTTP 隧道时才使用。 https://wangjunliang.com:80 一个星号: 配合 OPTIONS 方法使用,代表整个服务器。*HTTP/VersionHTTP/Version表明了客户端请求使用的HTTP协议版本,并期望服务器相同的协议版本响应。目前有HTTP/0.9、HTTP/1.0、HTTP/1.1、HTTP/2.0以及HTTP/3.0五种取值,随着HTTP不断发展后续也会有更多的版本。Code与MessageCode状态码是服务器返回的响应报文响应行中一个三位数字代码,用于表示服务器处理请求的结果状态。它们提供了关于请求是否成功、出现错误的类型以及如何处理请求的信息。HTTP响应状态码由三个数字组成,分别表示响应的类别:· 1xx:信息性状态码,表示服务器接收到请求并继续处理。· 2xx:成功状态码,表示服务器成功处理了请求。· 3xx:重定向状态码,表示需要进一步操作以完成请求。· 4xx:客户端错误状态码,表示客户端发送的请求有错误。· 5xx:服务器错误状态码,表示服务器在处理请求时发生了错误。Message返回消息是服务器返回的响应报文响应行中一个可选的文本描述,返回消息提供了对状态码的进一步解释,使客户端能够更好地理解服务器处理请求的结果。通常称为"Reason-Phrase",它紧跟在状态码后面,以便更清楚地说明状态码的含义。信息性状态码:1xx状态码返回消息作用100Continue这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续请求,如果已经完成,则忽略它。101Switching Protocols该代码是响应客户端的 Upgrade请求头发送的,指明服务器即将切换的协议。102Processing该代码是一个临时的状态码,用于指示服务器已经接收到请求并且正在处理,但尚未完成处理。这个状态码通常用于长时间运行的请求或者需要进行大量计算的请求。103Early Hints此状态代码主要用于与Link消息头一起使用,以允许用户代理在服务器准备响应阶段时开始预加载preloading资源。当服务器收到客户端的请求后,如果服务器能够提前获取到一些与请求相关的资源或者其他信息,它可以使用103状态码来发送这些信息的响应头部给客户端。这样,客户端在接收到完整的响应之前,就可以开始预加载或处理这些额外的信息,从而提高页面加载速度和用户体验。该状态码仍处于实验阶段。成功状态码:2xx状态码返回消息作用200OK请求成功并已正确处理返回201Create请求成功,并因此创建了一个新的资源。这通常是在 POST 请求,或是某些 PUT 请求之后返回的响应。202Accepted表示请求已被接受,但处理尚未完成。通常情况下,服务器会在响应中包含一个描述性的消息或链接,以便客户端可以进一步跟踪请求的处理进度。这通常用在异步操作或批量操作的场景中203Non-Authoritative Information表示服务器已成功处理请求,但返回的信息可能来自于另一个源。通常用于代理服务器的场景,表示代理服务器已经接收到请求并成功处理,但返回的响应内容是从其他服务器获取的,这种情况下,响应中会包含一个描述性的消息或链接,指示客户端可以从其他源获取更详细的信息。204No Content表示请求成功处理,但没有返回内容。205Reset Content表示请求成功处理,要求客户端重置(Reset)当前页面。206Partial Content表示服务器成功处理了部分GET请求,只返回了请求范围内的部分内容。通常用于对资源进行分段下载以及断点续传的场景重定向状态码:3xx状态码返回消息作用300Multiple Choice请求拥有多个可能的响应,用户代理或者用户应当从中选择一个。服务器在响应中会包含一个Location头部字段,其中列出了多个可供选择的资源的URL 。 客户端可以根据自己的需求选择其中一个URL进行进一步的请求。需要注意的是,300状态码并不会自动重定向到其中的某个URL,而是提供了多个选择供客户端选择。301Moved Permanently请求资源的 URL 已永久更改,在响应中给出了新的 URL。当服务器返回301状态码时,客户端会被告知该资源已经永久移动,并且会在响应的Location头部字段中提供新的URL。客户端收到301响应后, 会使用相同的请求方法(一些浏览器可能将POST请求自动转换为GET请求)自动重定向到新的URL,以便获取所请求的资源。302Found请求资源的 URL 临时移动到了一个不同的URL,在响应中给出了新的 URL。当服务器返回302状态码时 ,客户端会被告知该资源已经临时移动,并且会在响应的Location头部字段中提供新的URL。与301状态码不同,302状态码表示所请求的资源只是临时移动,而不是永久性的移动。客户端收到302响应后,会使用相同的请求方式(一些浏览器可能会将将POST请求自动转换为GET请求)自动重定向到新的URL303See Other表示请求的资源可以在另一个URL上找到,并且客户端应该使用GET方法去获取该资源。当服务器返回303状态码时,客户端会被告知所请求的资源可以在另一个URL上找到,并且在响应的Location头部字段中提供新的URL。与302状态码类似,客户端会自动重定向到新的URL,但是在重定向时会使用GET方法。304Not Modified用于缓存的目的,表示所请求的资源在客户端缓存中仍然有效,并且可以直接使用缓存的副本。当客户端发送一个GET请求时,服务器会检查该请求中的If-Modified-Since或If-None-Match头部字段,这些字段包含了之前获取该资源时服务器返回的Last-Modified或ETag值。如果服务器判断该资源自上次请求以来没有发生变化,就会返回304状态码,告知客户端可以使用缓存的副本。307Temporary Redirect请求的资源的 URL 临时移动到了另一个URL,在响应中给出了新的URL。与302状态码类似,当服务器返回307状态码时,客户端会被告知所请求的资源临时移动到了另一个URL上,并且在响应的Location头部字段中提供新的URL。客户端会自动重定向到新的URL,但在重定向时会保持原始的请求方法(解决了302一些浏览器会将POST转换为GET的问题)。308Permanent Redirect请求资源的 URL 已永久更改,在响应中给出了新的 URL。当服务器返回308状态码时,客户端会被告知该资源已经永久移动,并且会在响应的Location头部字段中提供新的URL。客户端会自动重定向到新的URL,但在重定向时会保持原始的请求方法(解决了301一些浏览器会将POST转换为GET的问题)。客户端错误状态码:4xx状态码返回消息作用400Bad Request由于被认为是客户端错误(例如,错误的请求语法、无效的请求消息帧或欺骗性的请求路由),服务器无法或不会处理请求。401Unauthorized表示请求需要用户进行身份验证,但是发送请求的客户端未提供有效的凭据,或者根本没有提供任何凭据。402Payment Required此响应代码保留供将来使用。创建此代码的最初目的是将其用于数字支付系统,但是此状态代码很少使用,并且不存在标准约定。403Forbidden客户端没有访问内容的权限;也就是说,它是未经授权的,因此服务器拒绝提供请求的资源。与401 Unauthorized不同,服务器知道客户端的身份。404Not Found服务器找不到请求的资源。405Method Not Allowed服务器知道请求方法,但目标资源不支持该方法。406Not Acceptable表示服务器无法根据客户端发送的请求中的Accept头部字段,提供与客户端可接受的响应内容格式相匹配的响应。407Proxy Authentication Required类似于 401 Unauthorized 但是认证需要由代理完成。408Request Timeout此响应由一些服务器在空闲连接上发送,即使客户端之前没有任何请求。这意味着服务器想关闭这个未使用的连接。由于一些浏览器,如 Chrome、Firefox 27+ 或 IE9,使用 HTTP 预连接机制来加速冲浪,所以这种响应被使用得更多。还要注意的是,有些服务器只是关闭了连接而没有发送此消息。409Conflict表示服务器在处理请求时发现了冲突,无法完成请求。在进行资源更新或修改操作时,如果服务器检测到当前资源状态与请求中的条件不符合,就会返回409状态码。410Gone当请求的内容已从服务器中永久删除且没有转发地址时,将发送此响应,客户端需要删除缓存和指向资源的链接411Length Required表示服务器要求在请求中包含有效的Content-Length头字段,用于指定请求正文的长度。412Precondition Failed表示服务器在处理请求时,发现请求中包含的某些前提条件不满足。当使用条件请求头字段如If-Match或If-Unmodified-Since时,服务器会比较请求头中的条件与资源的当前状态。如果条件不匹配或资源在指定时间之后被修改过,则服务器会返回412状态码。当使用条件请求头字段如If-None-Match或If-Modified-Since时,服务器会比较请求头中的条件与资源的当前状态。如果条件匹配或资源在指定时间之后未被修改过,则服务器会返回412状态码。413Payload Too Large表示请求实体(负载)的大小超过了服务器设定的限制。如果请求负载超过了服务器定义的限制,服务器可能会选择关闭与客户端的连接,以避免处理过大的请求负载。服务器也可能返回重试信息,在响应中包含一个Retry-After标头字段,指示客户端在多长时间后可以重试请求。这允许客户端知道何时重新发送较小的请求414URI Too Long客户端请求的 URI 比服务器愿意接收的长度长。415Unsupported Media Type服务器不支持请求数据的媒体格式,因此服务器拒绝请求。416Range Not Satisfiable表示服务器无法满足请求中 Range 标头字段指定的范围。该范围可能无效或超出了目标资源数据的大小。417Expectation Failed表示服务器无法满足请求中的Expect请求头字段指定的预期条件418I'm a teapot服务端拒绝用茶壶煮咖啡。笑话,典故来源茶壶冲泡咖啡421Misdirected Request表示服务器无法处理请求,因为请求被发送到了错误的资源。425Too Early表示服务器拒绝处理请求,因为请求的时间过早。该状态码通常与WebRTC(Web实时通信)相关,用于指示客户端在协议协商之前发送了请求。WebRTC是一种用于实时音视频通信的开放标准,它涉及到协议协商和建立连接的过程。在进行协议协商之前,客户端不应该发送任何请求。该状态码处于实验阶段。426Upgrade Required服务器拒绝使用当前协议执行请求,但在客户端升级到其他协议后可能愿意这样做。 服务端发送带有Upgrade 字段的 426 响应 来表明它所需的协议。428Precondition Required表示服务器要求客户端在发送请求之前满足某些先决条件。在收到428状态码时,客户端应该检查响应的头部信息,特别是Precondition-Required头部字段。该字段通常会指定客户端需要满足的先决条件,例如提供正确的If-Match或If-None-Match头部字段,或者提供适当的验证令牌。429Too Many Requests用户在给定的时间内发送了太多请求("限制请求速率")431Request Header Fields Too Large服务器不愿意处理请求,因为其头字段太大。在减小请求头字段的大小后,可以重新提交请求。451Unavailable For Legal Reasons请求了无法合法提供的资源,例如政府审查的网页。服务器错误状态码:5xx状态码返回消息作用500Internal Server Error表示服务器内部错误。当服务器在处理请求时遇到了意外错误或异常情况,无法完成请求时,会返回500状态码给客户端。501Not Implemented表示服务器不支持客户端所请求的功能或方法。当客户端发送的请求方法是服务器不支持的,或者服务器无法满足请求所需的功能时,会返回501状态码。502Bad Gateway表示作为代理服务器的网关从上游服务器(通常是应用服务器或另一个代理服务器)接收到无效的响应。这可能是由于上游服务器出现故障、网络连接问题或配置错误等原因导致的。简单来说,502错误意味着代理服务器无法正确地转发请求并获得有效的响应。503Service Unavailable表示服务器当前无法处理请求,通常是由于服务器过载或维护导致的。这是一个临时错误,表示服务器暂时无法提供请求的服务。这个响应应该用于临时条件,如果可能的话,响应标头 Retry-After 字段应该包含恢复服务之前的估计时间。网站管理员还必须注意与此响应一起发送的与缓存相关的标头,因为这些临时条件响应通常不应被缓存。504Gateway Timeout表示代理服务器在尝试转发请求时,未能及时从上游服务器接收到响应。这通常是由于上游服务器处理时间过长、连接超时或网络问题导致的。简单来说,504错误意味着代理服务器等待上游服务器响应的时间超过了预设的超时时间。505HTTP Version Not Supported表示服务器不支持请求中使用的 HTTP 版本。506Variant Also Negotiates表示服务器有多个可供选择的表示形式(变体)可用于响应客户端请求时,服务器可以使用内容协商机制来确定最适合客户端的表示形式。然而,如果服务器无法确定最佳的变体,或者服务器拒绝进行协商,就会返回506状态码。510Not Extended表示服务器需要对请求进行进一步扩展才能完成请求。当服务器收到一个请求,但需要额外的扩展来满足请求时,可以返回510状态码。这通常发生在服务器要求客户端提供更多信息或使用特定的扩展头部字段时。510状态码的出现是为了以后的HTTP协议扩展预留的,以便在需要时可以定义新的扩展状态码。在实际应用中,510状态码的使用相对较少,因为大多数常见的HTTP请求可以通过现有的状态码来处理。511Network Authentication Required表示客户端需要进行身份验证才能获得网络访问权限。消息头报文的第二行至空白行被称为消息头,它包含了一系列的key:value键值对(key不区分大小写),用来进一步描述请求或消息体,有些消息头是可选的,有些则是必须的。消息头在请求报文中被称为请求头,在响应报文中又被称为响应头,请求头与响应头有些可以共用,有些则只能专用,为此它们有以下分类:· 请求与响应都可使用的key被称为通用标头· 请求报文专用的key称为请求标头· 响应报文专用的key称为响应标头· 用于标识消息体相关内容的key被称为实体标头消息体报文的空白行后一行至最后一行被称为消息体,它用来携带请求或响应需要上传/响应的具体内容,消息体是可选的。 不是所有的请求都消息体:例如获取资源的请求,像 GET、HEAD、DELETE 和 OPTIONS,通常它们不需要主体,同样的也不是所有的响应都有消息体。消息体在请求报文中被称为请求体,在响应报文中又被称为响应体 。请求体与响应体都可以分为两类:· 单一资源(Single-resource)主体,由一个单文件组成。该类型的主体由两个标头定义:Content-Type 和 Content-Length。· 多资源(Multiple-resource)主体,由多部分主体组成,每一部分包含不同的信息位。通常是和HTML 表单连系在一起。总结请求报文响应报文差别起始行名称:请求行 由method(方法)、path(请求资源地址)以及http/version(http版本)组成名称:响应行 由http/version(http版本)、code(状态码)以及message(消息)组成完全不同消息头请求头 由一系列的key:value键值对组成响应头 由一系列的key:value键值对组成请求与响应都可使用的被称为通用标头 请求报文专用称为请求标头 响应报文专用称为响应标头 消息体专用被称为实体标头消息体请求体响应体需要上传的内容/需要响应的内容,它们都可分为单一或多资源主体

0
0
0
浏览量2039
爱喝奶茶的波波

【HTTP完全注解】揭开Authorization神秘的面纱

AuthorizationAuthorization是HTTP 提供一个用于权限控制和认证的通用框架,可能有不少小伙伴会感到疑惑"Cookie不就可以做权限控制和认证吗? ",确实如此! Cookie确实是在单个系统内认证用户身份、保持会话状态的有效方式,但如果涉及到多个系统、多个域名或多个应用程序之间认证、授权呢? 使用Cookie的话该如何办呢?是不是想想都头皮发麻呢?为解决这个问题, HTTP急需一种更通用、更灵活的身份验证和授权机制,使跨系统和跨域的身份验证和授权管理更容易,这对于现代应用程序中的多样化环境非常重要,就这样Authorization诞生了!Authorization是一种通用的、标准化的权限控制和认证的通用框架,它能够使跨系统和跨域的身份验证和授权管理更容易,使不同应用程序之间能够更轻松地实现单点登录(SSO)、用户身份验证和授权控制等。Authorization的运行方式Authorization仅是一个通用的认证框架,它并没有强制规定具体的使用方式,而是只提供了一种结构化的方式来管理身份验证和访问控制。它具体的身份验证方案和授权流程可以根据不同的需求和协议而有所不同,但大体的流程都如下图所示:第一步客户端请求授权: 客户端请求获得访问资源的授权,通常请求授权可以是账户密码登录/私秘钥等。第二步服务端返回授权码/令牌: 服务器收到客户端的授权请求后会验证其身份的有效性,如果有效则会给相应用户授权,并发送相应的授权码或令牌。第三步客户端携带令牌请求内容: 客户端在请求头Authorization中携带服务器返回的授权码/令牌发起请求。第四步服务端携验证令牌: 资源服务器接收到客户端请求,验证令牌的有效性和权限。这可能涉及验证签名、检查令牌的有效期和授权范围等。如果令牌有效且授权被授予,资源服务器允许客户端访问受保护的资源。常见的认证授权方案上文介绍了Authorization仅是一个通用的认证授权框架,具体的身份验证方案和授权流程根据不同的协议和方案而有所不同并且对于一些特殊认证方案浏览器还有一些默认行为,因此为了更好的使用Authorization,我们应该进一步了解目前使用较为广泛且常见的认证方案与规范。Basic认证Basic认证方案是在 RFC 7617 中规定的,被称为基本身份认证,是一种用于HTTP的简单认证方案。该方案通过在HTTP请求中发送用户名和密码来进行身份验证。Basic认证的工作流程如下:客户端发送一个请求到服务器。如果服务器需要认证,它会返回一个401未授权的响应,同时在响应头中包含一个WWW-Authenticate字段,该字段值为Basic realm="xxx",Basic表明请求该资源需要进行Basic认证,其中"xxx"是服务器对资源的描述。客户端在接收到401响应后,会提示用户输入用户名和密码。然后,客户端将用户名和密码拼接成一个字符串,格式为"username",并对这个字符串进行Base64编码。客户端再次发送相同的请求,但这次在请求头中包含一个Authorization字段,该字段值为Basic后接上一步得到的Base64编码字符串。服务器接收到请求后,解码Authorization字段的值,验证用户名和密码。如果验证通过,服务器就会处理请求并返回响应。如果验证失败,服务器会再次返回401响应。Digest认证Digest认证方案是在 RFC 7616 中规定的,它是一种用于HTTP的认证方案,也被称为摘要认证,是基本认证(Basic Authentication)的一个改进版本,它提供了比基本认证更好的安全性。摘要认证的工作流程如下:客户端发送一个请求到服务器。如果服务器需要认证,它会返回一个401未授权的响应,同时在响应头中包含一个WWW-Authenticate字段,该字段值包含了认证方式(Digest)、一个随机生成的nonce值(nonce)、域名(realm)等信息。客户端在接收到401响应后,会提示用户输入用户名和密码。待用户输入完成,客户端会使用服务器返回的nonce值、URL与用户名、密码相结合然后通过 MD5 加密生成哈希密钥也叫响应(response)值。客户端再次发送相同的请求,但这次在请求头中包含一个Authorization字段,该字段值包含了认证方法(Digest)、用户名(username)、域名(realm)、nonce值(none)、响应值(responese)等信息。服务器收到请求后,可以使用username查询到相应用户的密码,然后使用同样的方式生成响应值,最后与客户端的响应值比对,如果服务器的响应值与客户端的响应值一致,服务器就会处理请求并返回响应。Bearer认证Bearer认证方案是在 RFC 6750 中规定的,它是一种用于HTTP的认证方案,也被称为Token(令牌)认证,它是基于OAuth2.0认证协议的认证方案。该方案使用令牌(token)授权,令牌(token)就像你持有的一张人民币一样,只要你持有它,你就可以使用它,而不像银行卡需要输入账户密码,正因这个特性,它被广泛使用于跨系统和跨域的身份验证和授权中。Bearer认证的工作流程如下: 客户端发送一个请求到服务器。如果服务器需要请求第三方服务器资源,并且需要认证,此时它会返回一个401未授权的响应,同时返回一个第三方服务认证授权的地址。客户端收到相应后会重定向到第三方服务认证授权的地址,待用户填写相应信息确认授权后,授权请求发送到第三方服务器。第三方服务器收到授权请求后,判断认证信息是否正确,如果认证信息正确,服务器会生成一个Bearer令牌,并将其发送回客户端。这个令牌是一个长字符串,它代表了用户的身份。客户端收到响应后,将令牌取出并存储起来,通常是在本地存储或者cookie中,存储过程需要开发人员自行操作。客户端携带令牌Authorization: Bearer <token>,再次发出请求,携带令牌需要开发人员自行操作。服务器收到令牌后会使用该令牌向第三方服务器继续请求资源。第三方服务器收到请求后,会判断令牌是否有效,如果令牌验证成功,服务器就会处理请求并返回响应。JWT认证JWT(JSON Web Token)认证与Bearer认证的原理是一样的,并且其运行流程也并无差异,他们的关键差别仅在于:令牌类型:Bearer认证使用的令牌通常是一个随机生成的字符串,它本身不包含任何用户信息。而JWT是一种特殊的令牌,它是一个编码后的JSON对象,可以包含一些用户信息和其他元数据。状态:Bearer认证通常是状态性的,这意味着服务器需要存储令牌信息以便验证。而JWT是无状态的,因为JWT本身就包含了所有需要验证的信息,服务器不需要存储任何关于JWT的信息。使用方式:在使用方式上,JWT和Bearer认证都很相似。它们都是在HTTP请求的头部字段中发送的,格式通常是Authorization: Bearer <token>。这里的<token>可以是一个Bearer令牌,也可以是一个JWT。安全性:JWT可以使用数字签名或者加密来保证其安全性。而Bearer令牌的安全性主要依赖于HTTPS来防止令牌在传输过程中被窃取。API密钥认证API密钥认证(API Key Authentication)是一种用于保护和控制对Web服务或API资源的访问的常见方式。它基于在每个请求中包含一个唯一的API密钥,以便服务器可以验证请求的合法性。这种认证方式通常用于对第三方开发者、应用程序或用户授予对API的有限访问权限。API密钥认证的工作流程如下:生成API密钥:API提供者会生成一个唯一的API密钥,并将其分发给授权的开发者或应用程序包含API密钥:在进行API请求时,开发者或应用程序需要在请求中包含他们的API密钥。这通常是通过在HTTP请求的头部、查询参数或请求体中添加密钥来实现的。 服务器验证:API服务器收到请求后,会提取其中的API密钥,并与存储的有效密钥进行比对。如果密钥有效且请求符合授权要求,服务器将允许请求继续处理;否则,服务器将返回相应的错误信息。访问控制:一旦API密钥被验证通过,服务器可以根据密钥对应的权限级别,控制对API资源的访问权限。这可以包括限制每个密钥的请求速率、限制对特定资源的访问等。双因素认证双因素认证(Two-Factor Authentication, 2FA)是一种身份验证方式,要求用户在登录时提供两种不同类型的身份验证信息,通常是"Something you know"(你所知道的)和"Something you have"(你所拥有的)。这种方式比单一密码更安全,因为即使密码泄露,仍需要第二种身份验证信息才能完成登录。双因素认证的工作流程如下:用户尝试登录:用户在登录时输入其用户名和密码。第一因素验证:系统验证用户名和密码的正确性。第二因素验证:如果第一因素验证通过,系统会要求用户提供第二种身份验证信息。这通常是通过手机短信、手机应用程序生成的动态验证码、硬件安全密钥(如YubiKey)或生物识别信息(如指纹或面部识别)来实现的。访问控制:一旦第二因素验证成功,用户将被授予访问权限。其他一些认证方式 OpenID Connect: 基于OAuth 2.0的身份认证协议,用于实现单点登录和获取用户身份信息。 SAML (Security Assertion Markup Language) : 用于单点登录和跨域身份验证的XML标准协议。 Kerberos: 一种网络身份验证协议,用于提供强化的网络安全。 LDAP (Lightweight Directory Access Protocol) Authentication: 用于与目录服务(如Active Directory)通信以进行用户身份验证。 Biometric Authentication: 使用生物识别技术,如指纹、面部识别、虹膜识别等进行身份验证。 Smart Card Authentication: 使用智能卡进行身份验证,通常在高度安全的环境中使用。相关的标头从前面的内容我们可以知道,Authorization的运行主要依赖于WWW-Authenticate响应标头以及 Authorization请求标头,下面我们就详细介绍下两个标头的内容。WWW-Authenticate响应标头响应标头WWW-Authenticate 定义了获取特定资源的访问权限的认证方法。 服务器将以 401 Unauthorized去响应访问受保护资源的请求,该响应必须包含至少一个 WWW-Authenticate 标头和一个质询,以指示客户端使用哪些身份验证方案访问资源(以及每个特定方案的任意额外的数据)。一个 WWW-Authenticate 标头中允许多个质询,并且一个响应中允许多个 WWW-Authenticate 标头。参数<auth-scheme>    用于指定访问该资源需要进行的身份验证方案。一些更常见的身份验证方案是(不区分大小写):Basic、Digest、Negotiate 和 AWS4-HMAC-SHA256。realm="<string>" 可选    用于指定一段描述信息除了上述的参数外,该标头对于不同的身份验证方案也有一些不同的参数:Basic认证charset="UTF-8" 可选    当提交用户名和密码时,告诉客户端服务器的首选编码方案,仅允许值“UTF-8”。Digest认证domain="<URI> <URI> <URI>...." 可选    以空格分隔的 URI 前缀列表,定义了可以使用身份验证信息的所有位置。如果未指定此关键字,则可以在 web 根目录的任意位置使用身份验证信息。nonce="<string>"    一串由服务器生成随机字符串,用于加密用户账户与密码,nonce 值对客户端是不透明的。opaque ="<string>"    一串由服务器生成随机字符串。它的作用是在客户端发送下一次请求时,服务器可以验证客户端的身份。opaque 的值会在服务器收到客户端发送的认证信息后,随后的响应中被包含,客户端需要将这个值在后续的请求中原封不动地发送回服务器。这样做的目的是为了防止重放攻击(replay attack)。攻击者可能会尝试重复发送之前捕获到的认证信息,以此来冒充合法用户。通过在每次响应中更新 opaque 的值,服务器可以确保每个认证信息只能用于一次,从而增加了安全性。stale="<bool>" 可选    指示客户端之前的请求因 nonce 太旧了(过期)而被拒绝。如果为 true,则可以使用新的 nonce 加密相同用户名/密码重试请求。如果它是任意其他的值,那么用户名/密码无效,并且必须向用户重新请求。algorithm=<algorithm> 可选    指定加密算法。有效值是:"MD5"(如果未指定,则是默认)、"SHA-256"、"SHA-512"、"MD5-sess"、"SHA-256-sess"、"SHA-512-sess"。qop="<string>"    带引号的字符串,表示服务器支持的保护程度,取值如下:"auth"(身份验证)、"auth-int"(有完整保护的身份验证)。charset="UTF-8" 可选    当提交用户名和密码时,告诉客户端服务器的首选编码方案,仅允许值“UTF-8”。userhash=<bool> 可选    服务器可能指定为 "true",以指示它支持用户名哈希(默认是 "false")。示例WWW-Authenticate: Basic realm="Access to the staging site", charset="UTF-8" WWW-Authenticate: Digest   realm="http-auth@example.org",   qop="auth, auth-int",   algorithm=SHA-256,   nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",   opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS" WWW-Authenticate: Digest   realm="http-auth@example.org",   qop="auth, auth-int",   algorithm=MD5,   nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",   opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"Authenticate请求标头请求标头Authorization 携带经过正确处理的服务器所需要的用户凭证。 客户端在接收 WWW-Authenticate 标头之后,用户代理应该从WWW-Authenticate提供的身份验证方案中选择它支持的最安全的身份验证方案,并提示用户提供凭据,然后重新请求资源,这个新的请求会使用 Authorization 请求标头携带经过相应处理的用户提供的凭证。参数用于指定访问该资源需要进行的身份验证方案。一些更常见的身份验证方案是(不区分大小写):Basic、Digest、Negotiate 和 AWS4-HMAC-SHA256。除了上述的参数外,该标头对于不同的身份验证方案也有一些不同的参数:Basic认证<credentials>    用户提供的凭证,例如账户密码等,并根据指定的方案编码。Digest认证response="<string>"    一串字符串,也被称为响应值,通过将用户名、密码、realm、qop、nc 等值进行结合然后使用nonce加密后的值username="<string>"    一串字符串,指定用户名,可以是纯文本,也可以是十六进制表示的哈希编码。username*="<string>"    与username相同,如果用户名包含字段中不允许的字符(RFC5987 中定义的扩展符号格式化的用户名)或userhash 设置为 "false" 时,则不可使用username,而是使用username*uri="<string>"    一串字符串,指定有效的请求 URIrealm="<string>"    请求的用户名/密码的 realm(同样,应该与所请求资源中对应的 WWW-Authenticate响应中的值一致)。opaque="<string>"    一串由服务器生成随机字符串,为防止重放攻击(同样,应该与所请求资源中对应的 WWW-Authenticate响应中的值一样)。nonce="<string>"    一串由服务器生成随机字符串,用于加密用户账户与密码(同样,应该与所请求资源中对应的 WWW-Authenticate响应中的值一样)。algorithm=<algorithm>    指定加密算法,必须是所请求资源的 WWW-Authenticate响应中支持的算法。qop=<string>    表示服务器支持的保护程度。必须与在 WWW-Authenticate响应中,为被请求的资源指定的集合中的一个值匹配。cnonce="<string>" 可选    客户端生成的随机字符串,这样可以防止攻击者通过简单地重放先前的认证信息来欺骗服务器,并且对特定 nonce 的已知明文攻击,通过在每次认证中使用不同的 cnonce,可以增加攻击者破解认证信息的难度。nc=<number> 可选    一个数字,它是客户端发送的一个计数器,用于防止重放攻击。每当客户端发送一个新的请求时,它会增加这个计数器的值。服务器会检查这个计数器的值,以确保它是递增的,这样可以防止攻击者重复使用相同的认证信息。userhash=<bool> 可选    服务器可能指定为 "true",以指示它支持用户名哈希(默认是 "false")。示例 Authorization: Digest username="Mufasa",   realm="http-auth@example.org",   uri="/dir/index.html",   algorithm=MD5,   nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",   nc=00000001,   cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ",   qop=auth,   response="8ca523f5e9506fed4657c9700eebdbec",   opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"     Authorization: Digest username="Mufasa",   realm="http-auth@example.org",   uri="/dir/index.html",   algorithm=SHA-256,   nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",   nc=00000001,   cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ",   qop=auth,   response="753927fa0e85d155564e2e272a28d1802ca10daf449       6794697cf8db5856cb6c1",   opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"

0
0
0
浏览量2031
爱喝奶茶的波波

【HTTP完全注释】爆肝万字!让你全面了解HTTP发展史!!!

HTTP的历史​超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是万维网(World Wide Web)的基础协议。自蒂姆·伯纳斯-李 (Tim BernersLee)博士和他的团队在 1989-1991 年间创造出它以来,HTTP 已经发生了太多的变化,在保持协议简单性的同时,不断扩展其灵活性。如今,HTTP 已经从一个只在实验室之间交换文档的早期协议进化到了可以传输图片,高分辨率视频和 3D 效果的现代复杂互联网协议。HTTP的诞生​1989 年 3 月欧洲核子研究组织(CERN)的蒂姆·伯纳斯-李 (Tim BernersLee)博士提出了一种能让远隔两地的研究者们共享知识的设想。 最初设想的基本理念是:借助多文档之间相互关联形成的超文本(HyperText),连成可相互参阅的 WWW(World Wide Web,万维网)。蒂姆最初的提议。图片来源:欧洲核子研究中心到 1990 年 10 月,Tim 编写了三项基本技术来实现设想,这些技术仍然是当今网络的基础(您可能已经在网络浏览器的某些部分上看到过这些技术):HTML(HyperText Markup Language):超文本标记语言,作为编写文档的语言。HTTP(HyperText Transfer Protocol):超文本传输协议,作为传递文档的协议。URL(Uniform Resource Locator):统一资源标识符,一种唯一的“地址”,用于标识文档在网络上的位置。此外 Tim 还编写了第一个网页编辑器/浏览器(“WorldWideWeb.app”)和第一个 Web 服务器(“httpd”)。至此 Tim 初步完成了他的设想的所有技术实现,且第一批服务器已经在 1991 年初在 CERN 以外的地方运行了,1991 年 8 月 16 日,Tim Berners-Lee 在公开的超文本新闻组上发表的文章被视为是万维网公共项目的开始。对于HTTP而言, 在应用的早期阶段它是非常简单的,后来它也被称为 HTTP/0.9,有时也叫做单行hang(one-line)协议。HTTP/0.9——单行协议(1991)​最初版本的 HTTP 协议并没有版本号,后来它的版本号被定位在 0.9 以区分后来的版本。HTTP/0.9于 1991 年提出。它是有史以来最简单的协议;它的请求由单行指令构成(因此也称为单行协议),以唯一可用方法 GET 开头,其后跟目标资源的路径(一旦连接到服务器,协议、服务器、端口号这些都不是必须的)。GET /index.html响应也极其简单的:只包含HTML文档本身。<HTML> 这是一个非常简单的 HTML 页面 </HTML>跟后来的版本不同,HTTP/0.9 的响应内容并不包含 HTTP 头。这意味着只有 HTML 文件可以传送,无法传输其他类型的文件。也没有状态码或错误代码。一旦出现问题,一个特殊的包含问题描述信息的 HTML 文件将被发回,供人们查看。特性​它是 ASCII 协议,请求/响应都是由ASCII字符组成字符串。它在TCP/IP 链路上运行。请求以回车符 (CRLF) 终止。响应只包含HTML文档。文档传输完成后,TCP连接将终止。缺陷​只支持GET请求:  HTTP/0.9仅支持GET方法,意味着只能用于获取资源,不能用于其他类型的请求,如POST、PUT、DELETE等。这导致在处理复杂的应用逻辑和实现数据更新等操作时,HTTP/0.9显得非常有限。只能传输HTML:  HTTP/0.9的响应只能包含HTML文档,无法处理其他类型的数据,如JSON、XML、图像等。这限制了其在处理现代Web应用程序中的数据传输和交互能力。无法进行内容协商:  HTTP/0.9没有头部信息,无法携带元数据,如Content-Type、Content-Length等,这使得它无法识别并正确解析其他响应内容。没有状态码或错误代码:  也是由于HTTP/0.9没有头部信息,无法携带元数据,因此响应成功与失败都是返回HTML文档,这使得浏览器不能知晓请求执行成功或失败,并相应调整行为。不支持持久连接:  在HTTP/0.9中,每次请求都会建立一个新的TCP连接,请求完成后立即关闭连接。这导致在处理大量请求时,频繁地建立和关闭连接会带来较大的开销,影响性能。安全性问题:  HTTP/0.9没有提供任何加密和安全机制,所有的数据都是明文传输。这使得数据容易受到窃听和篡改,缺乏对隐私和数据完整性的保护。只能传输英文文本数据:  HTTP/0.9默认采用的字符集是ASCII字符集,这意味着HTTP只能传输英文文本数据,无法支持其他语言的文本数据,比如包含非英文字符的文本(如中文、日文、俄文等)。正如你们所看到的,HTTP/0.9仅适用于简单的、仅需要获取HTML文档的场景。新兴 Web 所需功能及其在公共 Web 上的用例不断增长,很快就强化了 HTTP 0.9 的许多缺陷:我们需要一个协议,该协议不仅可以服务于超文本文档,还可以提供有关请求和响应的更丰富的元数据。很快,HTTP 的下一个版本(即 HTTP/1.0)被推出,它解决了HTTP/0.9的缺陷,并提供更多强大的功能和性能优化。HTTP/1.0——构建可扩展性(1996)​1996 年 5 月,HTTP 工作组 (HTTP-WG) 发布了 RFC 1945,文档 RFC 1945 定义了 HTTP/1.0,但它是狭义的,并不是官方标准。HTTP/1.0 通过定义了HTTP请求/响应的结构,加入许多头部信息,现在可以处理其他响应格式,即图像、视频文件、纯文本或任何其他内容类型。它添加了更多方法(即 POST 和 HEAD)、添加了状态代码来标识响应、引入了字符集、类型、授权、缓存、内容编码等内容。以下为 HTTP/1.0 的请求示例:GET / HTTP/1.0 Host: cs.fyi User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) Accept: */*以下为 HTTP/1.0 的响应示例:HTTP/1.0 200 OK Content-Type: text/plain Content-Length: 137582 Expires: Thu, 05 Dec 1997 16:00:00 GMT Last-Modified: Wed, 5 August 1996 15:55:28 GMT Server: Apache 0.84 (response body) (connection closed)HTTP/1.0 的请求与响应现在看起来也是非常熟悉的,因为它首次定义了请求/响应的格式我们沿用至今,并且由于加入头信息,使得内容协商变得容易起来,这也极大的丰富了它的扩展性,虽然请求和响应标头仍保留为 ASCII 编码,但响应正文可以是任何类型,即图像、视频、HTML、纯文本或任何其他内容类型。因此,现在服务器不仅仅只能向客户端发送HTML文档,还可以发送其他任何内容类型;推出后不久,HTTP 中的“超文本”一词就变得用词不当。HMTP 或超媒体传输协议可能更有意义,但我想,我们终生都坚持这个名字。特性​定义了请求/响应格式:  HTTP/1.0将请求/响应格式划分为了三个部分——起始行、头部信息、消息体,这个格式一直沿用至今。加入了状态码和状态描述:  在响应的起始行中加入了状态代码和状态的描述信息,提供了关于请求处理结果的信息,以便客户端和服务器能够进行适当的处理和决策。加入了内容协商:  虽然在HTTP/1.0中起始行与头部信息都保留为 ASCII 编码,但它通过加入了Content-Type、Content-Length、Transfer-Encoding等头部属性,可以对不同类型的文件在消息体中进行不同的编码。也就是说起始行、头部信息传输仍是ASCII编码,而消息体则会根据头部属性让客户端/服务器进行内容协商,进行不同的编码方式。可以传输任何文件:  由于HTTP/1.0加入了内容协商的机制,使得只要客户端/服务器协商一致,HTTP/1.0就可以传输任何形式的文件。新增POST、HEAD请求:  POST请求方法允许客户端向服务器提交数据,而HEAD请求方法允许客户端获取资源的元数据。这些新增的请求方法丰富了HTTP协议的能力,使得客户端和服务器能够进行更多样化的交互和处理。不再只是传输英文文本数据:  HTTP/1.0引入字符集(Character Set),解决了其他国家语言文本数据的字符编码问题,并确保文本数据能够以正确的方式被处理和显示。初步引入缓存概念:  HTTP/1.0引入了头部字段如Expires和Last-Modified,用于控制缓存的行为,以及头部字段如If-Modified-Since和If-None-Match,用于条件性请求。初步引入持久链接:  HTTP/1.0引入一个名为 Connection: keep-alive 的新标头,来保持请求建立起来的TCP连接,以供后续请求继续使用该链接完成请求。初步引入代理支持:  HTTP/1.0引入了Proxy-Connection头部字段来指示代理服务器是否应保持持久连接,并引入了Via头部字段,用于标识请求经过的代理服务器链。缺陷​持久链接未得到广泛支持,默认仍为短连接:  HTTP/1.0 的尝试通过引入一个名为 Connection: keep-alive 的新标头来克服短连接问题,但它仍然没有得到广泛的支持,问题仍然存在。请求阻塞:  在HTTP/1.0中,每个请求都需要按照顺序进行,即必须等待前一个请求的响应返回后才能发送下一个请求。如果前一个请求很耗时,会导致后续请求被阻塞,影响并发性能。无状态:  HTTP是一种无状态协议,即服务器不维护有关客户端的信息,当客户端需要记录状态时,必须发送一些记录状态的冗余数据,从而导致带宽使用量增加。缺乏压缩支持:  HTTP/1.0没有内置的数据压缩机制,因此在传输大量文本数据时,没有有效地压缩数据,增加了网络传输的开销。安全性问题:  HTTP/1.0没有提供任何加密和安全机制,所有的数据都是明文传输。这使得数据容易受到窃听和篡改,缺乏对隐私和数据完整性的保护。实现混乱:  由于HTTP/1.0并不是官方标准,许多浏览器厂商并没有按照HTTP/1.0的指导实现HTTP,导致在实际运用中混乱不堪。可以看到对于HTTP/0.9人们诟病的是它的文件类型支持不够丰富,由于它的文件类型支持不丰富,所有通常只是请求HTML文档,往往发送一次请求就能获取到完整的内容。而在HTTP/1.0丰富了文件类型后,一次请求不再能获取到全部内容,并且请求的内容也从较小的HTML文档发展到了图片、音频、视频等较大的文件,此时HTTP的性能问题也被暴露出来。此外,由于各个浏览器相互竞争,各自为战,并且HTTP/1.0并不是官方标准,只是一些指导意见。这导致各个厂商对于HTTP都有各自的实现方式,导致在实际运用中混乱不堪。由于上述原因,人们迫切需要优化HTTP性能,制定一份标准化HTTP协议!HTTP/1.1——标准化的协议(1997)​HTTP/1.0 多种不同的实现方式在实际运用中显得有些混乱。自 1995 年开始,即 HTTP/1.0 文档发布的下一年,就开始修订 HTTP 的第一个标准化版本。 在 1997 年 1 月HTTP1.1 标准以 RFC 2068 文件发布,后续 HTTP/1.1 协议进行过两次修订,分别是RFC 2616 发布于 1999 年 6 月,以及 RFC 7230-RFC 7235 发布于 2014 年 6 月。HTTP/1.1 标准消除了早期版本中大量歧义内容,并引入了许多关于性能优化的措施:持久链接、管道化技术、支持范围请求和部分响应、分块传输机制、明确缓存控制机制、增加压缩技术、增强内容协商机制、增加客户端cookie等。除了改进HTTP性能方面HTTP/1.1还新增状态码、引入了基本认证和摘要认证,提供更强大的用户认证机制,确保更安全的通信、 引入了 Host 头字段,该字段允许在同一个物理服务器上托管多个域名。这使得虚拟主机能够通过在 Host 头中指定域名来区分不同的网站、并且它还新增了许多请求方法,极大丰富了请求类型。以下为HTTP/1.1的请求示例GET /zh-CN/docs/Glossary/Simple_header HTTP/1.1 Host: developer.mozilla.org User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Referer: https://developer.mozilla.org/zh-CN/docs/Glossary/Simple_header以下为HTTP/1.1的响应示例200 OK Connection: Keep-Alive Content-Encoding: gzip Content-Type: text/html; charset=utf-8 Date: Wed, 20 Jul 2016 10:55:30 GMT Etag: "547fa7e369ef56031dd3bff2ace9fc0832eb251a" Keep-Alive: timeout=5, max=1000 Last-Modified: Tue, 19 Jul 2016 00:59:33 GMT Server: Apache Transfer-Encoding: chunked Vary: Cookie, Accept-Encoding我们可以看到在请求/响应格式上HTTP/1.1与HTTP/1.0并无差异,这是因为HTTP/1.1沿用了HTTP/1.0的请求/响应格式。特性​持久化连接:  在HTTP/1.0中持久连接默认为关闭,并没有得到广泛应用,而在HTTP/1.1中连接默认情况下不会关闭,而是保持打开状态,从而允许多个顺序请求。要关闭连接,请求头 Connection: close 必须可用。客户端通常在最后一个请求中发送此标头以安全地关闭连接。管道化技术:  HTTP/1.1引入了管道化技术,以解决请求阻塞问题,客户端可以在同一连接上向服务器发送多个请求,而无需等待服务器的响应,并且服务器必须按照接收请求的顺序发送响应。新增客户端Cookie:  由于HTTP是无状态协议,当客户端需要记录状态时,必须发送一些记录状态的冗余数据,从而导致带宽使用量增加。HTTP/1.1引入了客户端cookie以解决该问题,通过在浏览器中设置cookie,服务器可以跟踪用户会话状态,实现用户身份认证,个性化用户体验等。新增Gzip、Deflate等压缩技术:  在HTTP/1.1中,服务器可以使用Gzip、Deflate等压缩算法来压缩HTTP响应的实体主体部分(如HTML、CSS、JavaScript等),然后在响应头中使用"Content-Encoding"字段来指示客户端该响应已经被压缩以及压缩的算法。客户端收到压缩的响应后,会自动解压缩以获取原始内容。引入了基本认证和摘要认证机制:  在HTTP/1.1中,可以通过基本认证和摘要认证机制,在请求头中传递用户名和密码等凭据进行用户身份验证。引入了范围请求和部分响应机制:  HTTP/1.1引入了范围请求和部分响应的功能,通过在HTTP请求头中使用"Range"字段指定所需的资源范围,而服务器在响应头中使用"206 Partial Content"状态码表明返回的是部分响应,并通过"Content-Range"字段指示返回内容的字节范围。这使得客户端可以请求大文件的特定部分,例如断点续传的情况下,从而避免重新下载整个文件。此外,范围请求还能让客户端只获取媒体资源的特定片段,优化数据传输并提升用户体验。引入了分块传输机制:  HTTP/1.1引入了分块传输(Chunked Transfer Encoding)机制,用于在动态内容传输时,服务器无法提前确定整个内容的长度的情况下,逐块发送内容。在分块传输中,服务器将响应拆分为一系列块,每个块都有一个独立的大小,并使用"Transfer-Encoding: chunked"请求头来通知客户端有关分块传输的信息。客户端接收到该头信息后,知道响应将以分块的形式传输,它可以按照指定的块大小逐块接收内容,直到接收到一个长度为零的块,表示传输已完成。这种机制适用于动态生成内容、流式传输以及服务器长时间运行的响应等场景,提供了更灵活和高效的数据传输方式。明确缓存机制:  HTTP/1.1在HTTP/1.0的基础上进一步明确了缓存机制,服务器可以通过设置响应头字段来控制缓存行为,例如使用"Cache-Control"头字段来指定缓存策略,如"max-age"用于设置资源的最大缓存时间,"no-cache"用于要求客户端验证资源的有效性等。同时,服务器也可以在响应头中添加"Expires"头字段,设置资源的过期时间,以便客户端在接收到资源后在过期时间之前可以直接使用缓存的副本。另外,HTTP/1.1还支持"Last-Modified"和"If-Modified-Since"头字段,以及"ETag"和"If-None-Match"头字段,用于在客户端缓存资源后,再次请求时验证资源是否已经发生变化,如果未变化,服务器返回304 Not Modified状态码,让客户端使用缓存的资源,从而避免重复传输。通过这些头字段的灵活组合使用,HTTP/1.1的缓存机制实现了更高效、可控的缓存管理,优化了Web应用程序的性能和用户体验。增强内容协商机制:  HTTP/1.1增加了Accept-Language、Accept-Encoding和Accept-Charset等头字段,允许客户端明确指定其首选语言、内容编码方式和字符集,让服务器能够更好地提供适配客户端需求的内容。此外,HTTP/1.1还引入了Vary头字段,用于标明服务器响应可能因客户端请求头的不同而变化,这样确保代理服务器能够存储和提供正确的缓存内容。这些改进使得HTTP/1.1的内容协商机制更加强大和智能,提高了资源传输的效率和用户体验。添加了新的 HTTP 方法:  HTTP/1.1新增了 PUT、PATCH、OPTIONS、DELETE方法。新增了Host 头字段:  TTP/1.1 引入了 Host 头字段,该字段允许在同一个物理服务器上托管多个域名。这使得虚拟主机能够通过在 Host 头中指定域名来区分不同的网站。新增了状态码缺陷​线头阻塞(Head-of-Line Blocking):  HTTP/1.1在同一连接上使用持久连接,但由于串行发送请求和响应,如果一个请求或响应的处理时间较长,那么后续的请求和响应将被阻塞,为此它引入了管道化技术(pipelining)试图解决该问题,但它并没有完全解决这个问题,因为即使在客户端请求选择某一管道并被异步发送出去,但在服务器如果该请求前面存在缓慢或繁重的请求,那么该请求就会被阻塞。这种情况也被称为线头阻塞无法处理较多的并发请求:  由于头阻塞问题和单个连接的限制,HTTP/1.1在处理较多的并发请求时表现较差。浏览器限制了同时与同一域名建立的连接数,从而限制了并发请求的数量。未能被充分利用的TCP:  HTTP 1.1很难榨干TCP协议所能提供的所有性能。HTTP客户端和浏览器必须要另辟蹊径的去找到新的解决方案来降低页面载入时间。明文传输:  HTTP/1.1默认是明文传输,数据在网络上传输时不加密,可能被窃听或篡改。这会导致安全隐患,尤其是对于敏感信息的传输。头部冗余:  HTTP/1.1的请求和响应头部会携带一些冗余的信息,导致了较大的头部开销,特别是对于小的资源请求。没有对头字段进行压缩:  HTTP/1.1没有对头字段进行压缩,尽管HTTP响应的主体可以使用Gzip等压缩算法,但头字段仍然是明文传输,可能在一些情况下浪费带宽。请求-响应模式:  HTTP/1.1使用请求-响应模式,每个请求需要等待响应后才能继续。这种模式对于实时性要求较高的应用场景,如实时通信和流媒体,效率较低。缺乏推送功能:  HTTP/1.1缺乏服务器主动向客户端推送资源的机制。客户端只能通过不断发送请求来获取资源,这导致了一定的延迟和额外的开销。超过 25 年的逐步扩展​从HTTP/1.1协议发布至今,HTTP/1.1协议已稳定使用超过25年,目前大部分网站仍是基于HTTP/1.1来运行的。这期间HTTP/1.1也做了多次扩展与修改,并发展不同的应用模式,以弥补之前的缺陷以及满足日益进步的需求。HTTP 用于安全传输​在1994年,网景通信公司(Netscape Communications Corporation)为了解决当时互联网上数据传输的安全问题,发布了第一个安全套接字层(Secure Sockets Layer,SSL)协议。SSL协议使用了加密技术,对HTTP的数据进行加密传输,保护数据的安全性。在SSL协议的基础上,网景通信公司将安全传输的功能整合到HTTP协议中,形成了HTTPS协议。HTTPS使用了SSL/TLS(Transport Layer Security)协议来加密HTTP传输过程中的数据,使得网站和用户之间的通信不再以明文传输,变得安全。HTTP 用于复杂应用​在 2000 年,一种新的使用 HTTP 的模式被设计出来:具象状态传输(representational state transfer) (或者说 REST)。由 API 发起的操作不再通过新的 HTTP 方法传达,而只能通过使用基本的 HTTP / 1.1 方法访问特定的 URI。这允许任何 Web 应用程序通过提供 API 以允许查看和修改其数据,而无需更新浏览器或服务器。所有需要的内容都被嵌入到由网站通过标准 HTTP/1.1 提供的文件中。REST 模型的缺点在于每个网站都定义了自己的非标准 RESTful API,并对其进行了全面的控制。RESTful API 在 2010 年变得非常流行。自 2005 年以来,可用于 Web 页面的 API 大大增加,其中几个 API 为特定目的扩展了 HTTP 协议,大部分是新的特定 HTTP 头:Server-sent events,服务器可以偶尔推送消息到浏览器。WebSocket,一个新协议,可以通过升级现有 HTTP 协议来建立。SPDY——Google的尝试(2009)​这些年来,网页愈渐变得的复杂,甚至演变成了独有的应用,可见媒体的播放量,增进交互的脚本大小也增加了许多。 如果仔细观察当前的一些网站所需要下载的资源的话,会发现一个非常明显的趋势—— 近年来加载网站首页需要的下载的数据量在逐渐增加,平均每个页面为了完成显示与渲染所需要下载的资源数已经超过了100个。HTTP/1.1 链接需要请求以正确的顺序发送,理论上可以用一些并行的链接(尤其是 5 到 8 个),带来的成本和复杂性堪忧。比如,HTTP 管线化(pipelining)就成为了 Web 开发的负担。HTTP 1.1很难榨干TCP协议所能提供的所有性能。HTTP客户端和浏览器必须要另辟蹊径的去找到新的解决方案来降低页面载入时间。与此同时,人们也尝试去用新的协议来替代TCP,但结果证明这也非常困难。无奈之下,我们只能尝试同时改进TCP协议本身和基于TCP的上层协议。在 2010 年早期,谷歌通过实践了一个实验性的 SPDY 协议,想要以此来解决当前HTTP存在的问题。SPDY 的功能包括多路复用、压缩、优先级、安全性等。本节不打算详细介绍 SPDY,因为我们在下一节中深入了解 HTTP/2 的本质时,您就会明白了,HTTP/2 主要是受到 SPDY 的启发。在2015年,Google决定将SPDY协议与HTTP合并,并基于SPDY的特点推出了HTTP/2。通过将SPDY融入HTTP/2,Google希望避免存在两个竞争的标准,统一标准有利于更好地推动Web协议的发展。同时,Google宣布SPDY协议被废弃,不再继续作为一个独立的协议存在,HTTP/2成为了SPDY的继任者,并继续在未来发展和推广。HTTP/2——更优异的性能(2015)​由于HTTP/1.1发展年限久远,用户数量庞大,因此对于HTTP/1.1的升级需要制定非常严格的边界与观念,这也给小组成员的创新带来了一些许限制。升级的边界与观念​必须保持早期HTTP的标准范式:  由于HTTP/1.1使用年限久远,用户数量庞大,使用该协议的网站太多了,如果改动过大且费力,这肯定会阻碍HTTP/2.0发展。因此HTTP/2.0必须保留所有现有的接口、内容、URI格式和结构, 不需要站点和应用做出改变,拥有一个最新的服务器和新点的浏览器即可升级HTTP/2.0。提供HTTP1到http2服务器的代理:  HTTP1的服务器和客户端仍然会长期存在,所以我们必须提供HTTP/1到http2服务器的代理,并且这种代理能够将http2的功能一对一的映射到HTTP 1.1的客户端。不再使用小版本号:  服务器和客户端都必须确定自己是否完整兼容http2或者彻底不兼容。如果将来该协议需要被扩充或者变更,那么新的协议将会是http3,而不是http 2.x。降低协议对延迟的敏感修复HTTP/1.1中pipelining和head of line blocking的问题防止主机需求更高的连接数量在确认好升级边界与观念后,HTTP/2协议规范(RFC 7540)于2015年5月发表,HTTP/2解决了HTTP/1中存在的一大堆缺点,其中相当一部分对于开发者来说非常麻烦,在HTTP/2出现前,开发者要用许多种变通方法来解决。在HTTP/2.0中HTTP从一个ASCII协议变为一个二进制协议,其主要特性是多路复用(multiplexing),它可以通过同一个TCP连接发送多个逻辑数据流。复用使得很多事情变得更快更好,它带来更好的拥塞控制、更充分的带宽利用、更长久的TCP连接————这些都比以前更好了,链路能更容易实现全速传输,标头压缩技术也减少了带宽的用量。采用HTTP/2后,浏览器对每个主机一般只需要 一个 TCP连接,而不是以前常见的 六个 连接。事实上,HTTP/2使用的连接聚合(connection coalescing)和“去分片”(desharding)技术还可以进一步缩减连接数。HTTP/2还解决了HTTP的队头拥塞(head of line blocking)问题,客户端必须等待一个请求完成才能发送下一个请求的日子过去了。以下为HTTP/2 的请求示例GET /zh-CN/docs/Glossary/Simple_header HTTP/2 Host: developer.mozilla.org User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Referer: https://developer.mozilla.org/zh-CN/docs/Glossary/Simple_header以下为HTTP/2 的响应示例200 OK Connection: Keep-Alive Content-Encoding: gzip Content-Type: text/html; charset=utf-8 Date: Wed, 20 Jul 2016 10:55:30 GMT Etag: "547fa7e369ef56031dd3bff2ace9fc0832eb251a" Keep-Alive: timeout=5, max=1000 Last-Modified: Tue, 19 Jul 2016 00:59:33 GMT Server: Apache Transfer-Encoding: chunked Vary: Cookie, Accept-Encoding大家可以惊奇的发现,除了版本号,HTTP/2.0与HTTP/1.1在内容与格式上几乎没有任何差别!这得益于早期标准制定者对HTTP/1.1升级边界与观念的思考,这让标准制定者几乎保留了HTTP/1.1内容与形式上的所有标准,从修改HTTP底层技术来解决HTTP/1.1中的缺点。也正因如此,HTTP/2.0不需 Web 开发者做什么,不需要站点和应用做出改变,随着陈旧的浏览器和服务器的更新,站点自然就会升级到HTTP/2.0而不会带来任何问题,并且还能在数据传输上节省了可观的成本和支出,这使得该协议在互联网和万维网上得到广泛的实现和部署,HTTP/2.0取得了巨大的成功。特性​HTTP/2.0是一个二进制协议:  在HTTP/2.0中,HTTP不再是ASCII协议,而是二进制协议。作为一个二进制协议,它更容易解析,但与 HTTP/1.x 不同的是,它不再被人眼读取。HTTP/2 的主要构建块是帧和流,每个 HTTP/2 请求和响应都被赋予一个唯一的流 ID,并且它被分成帧。帧不过是二进制数据,帧的集合称为流。每个帧都有一个流 ID,用于标识它所属的流,并且每个帧都有一个公共标头(Type, Length, Flags, Stream Identifie)和帧有效负载,规范中一共定义了10种不同的帧,其中最基础的两种分别对应于HTTP 1.1的DATA和HEADERS。此外,流 ID 是唯一的,客户端发起的任何请求流ID都使用奇数,而来自服务器的响应流ID则都是偶数。多路复用:  由于 HTTP/2 现在是二进制协议,并且正如我上面所说,它使用帧和流来进行请求和响应,因此一旦打开 TCP 连接,所有流都会通过同一连接异步发送,而无需打开任何其他连接。反过来,服务器以相同的异步方式响应,即响应没有顺序,客户端使用分配的流 ID 来识别特定数据包所属的流。流的多路复用解决了 HTTP/1.x 中存在的线头阻塞问题,即客户端不必等待正在花费时间的请求,其他请求仍将得到处理。流优先级(Stream Prioritization):  HTTP/2允许对请求/响应进行优先级排序,每个流都包含一个优先级(也就是“权重”),它被用来告诉对客户端哪个流更重要。当资源有限的时候,服务器会根据优先级来选择应该先发送哪些流。借助于借助于PRIORITY帧,客户端同样可以告知服务器当前的流依赖于其他哪个流,该功能让客户端能建立一个优先级“树”,所有“子流”会依赖于“父流”的传输完成情况。优先级和依赖关系可以在传输过程中被动态的改变。这样当用户滚动一个全是图片的页面的时候,浏览器就能够指定哪个图片拥有更高的优先级。或者是在你切换标签页的时候,浏览器可以提升新切换到页面所包含流的优先级。优先级的引入确保重要资源的优先加载,提高了页面加载速度和用户体验。头部压缩:  HTTP是一种无状态的协议。简而言之,这意味着每个请求必须要携带服务器需要的所有细节,而不是让服务器保存住之前请求的元数据,这导致许多请求和响应头部会携带一些冗余的一摸一样的信息,增大了标头大小,致使带宽使用和延迟增加。为了克服这个问题,HTTP/2使用HPACK算法对头部信息进行压缩,减少了头部大小,从而降低了传输的数据量,提高了效率。服务器推送:  HTTP/2的服务器推送功能允许服务器在客户端请求前主动推送资源。服务器可以通过发送一个名为PUSH_PROMISE的特殊帧,通知客户端即将推送的资源。这个PUSH_PROMISE帧与导致推送发生的流相关联,并包含服务器将要推送的资源的流ID。通过服务器推送,服务器可以在客户端请求之前主动将客户端可能需要的资源发送到客户端缓存中,从而避免了客户端额外的请求,减少了延迟。这种特性在某些情况下可以提高页面加载速度和性能,尤其是对于一些预加载资源或常用资源,可以减少客户端请求的往返次数,优化了Web应用的性能和用户体验。中断连接不再断开连接: HTTP/1.1协议有一个缺点:当一个含有确切值的Content-Length的HTTP消息被送出之后,你就很难中断它了。当然,通常你可以断开整个TCP链接(但也不总是可以这样),但这样导致的代价就是需要通过三次握手来重新建立一个新的TCP连接。在http2里面,我们可以通过发送RST_STREAM帧来实现这种需求,它是一种特殊的帧类型,用于中止某些流,即客户端可以发送此帧让服务器知道我不需要此流了。客户端可以使用 RST_STREAM 并停止接收特定流,同时连接不会被关闭其他流仍会正常运行。可靠性和安全性:  HTTP/2支持数据的流量控制和优先级设置,保障了数据的可靠传输。此外,HTTP/2要求使用TLS协议进行加密通信,提高了数据的安全性。兼容性:  HTTP/2通过与HTTP/1.1的兼容性保证,使得现有的Web应用可以逐渐迁移到HTTP/2,而不需要进行大规模的更改。HTTP/3——基于 QUIC 的 HTTP(2022)​HTTP 的下一个主要版本,HTTP/3 有这与 HTTP 早期版本的相同语义,但在传输层部分使用 QUIC (en-US) 而不是 TCP。到2022年10月,26% 的网站正在使用 HTTP/3。QUIC 旨在为 HTTP 连接设计更低的延迟。类似于 HTTP/2,它是一个多路复用协议,但是 HTTP/2 通过单个 TCP 连接运行,所以在 TCP 层处理的数据包丢失检测和重传可以阻止所有流。QUIC 通过 UDP 运行多个流,并为每个流独立实现数据包丢失检测和重传,因此如果发生错误,只有该数据包中包含数据的流才会被阻止。RFC 9114 定义的 HTTP/3 被大多数主流浏览器所支持,包括 Chromium(及其他的变体,例如 Chrome 和 Edge)和 Firefox。(更多HTTP3的内容会随着发展逐步更新)

0
0
0
浏览量2030
爱喝奶茶的波波

【HTTP完全注解】拯救不安全的HTTP — HTTPS

拯救不安全的HTTP — HTTPSWeb早期的使用场景都是学校之前传输学术论文,在当时Web几乎就是一个学术网络。由于使用人群单一,使用人数少,相对信任程度很高,因此当时人们并不觉得HTTP使用明文传输有什么不妥。但随着Web的极速发展,社会上越来越多商业、政府组织机构使用这一新生技术来完成自己的业务,HTTP也开始承载着越来越多重要的、私人的信息发往各地。此时HTTP的安全隐患被逐一暴露出来:通信使用明文传输,内容可轻易窃听获取HTTP协议无法加密数据,所有通信数据都在网络中明文“裸奔”,通过网络的嗅探设备及一些技术手段,就可轻易窃听并还原HTTP报文内容。这些个人、重要且隐私的信息就像是被装进了透明信封中,无论信被发往何处, 路过的人总能窥见一二。试想,你周末在咖啡店喝咖啡,连着咖啡店的WI-FI,你使用着银行的网页付款,不幸的是银行网页使用的是HTTP,你的银行账户密码被HTTP以纯文本明文的方式发送了出去,此时任何人都可以通过这个咖啡店的WI-FI拦截到你这个HTTP请求,而HTTP又是纯文本明文,因此他人不费吹灰之力就可以获得你的银行账户密码。无法证明报文的完整性,内容可遭篡改HTTP协议无法证明通信的报文完整性,因此,在请求或响应到达接收方这段时间内,即使请求或响应的内容遭到篡改,也没有办法获悉。也就是说,HTTP协议没有任何办法确认,发出的请求和接收到的响应是前后相同的,没有被篡改的。也就是说我通过一定技术手段拦截获取到了"老王转账给张三200元"的HTTP请求,由于HTTP无法证明报文的完整性,因此我可以将获取到的请求篡改为"老王转账给我30000元",通信双方都不会发现内容已被篡改。不验证通信方的身份,可伪装身份HTTP协议中的请求和响应不会对通信方进行身份验证。也就是说,在请求或响应到达接收方这段时间内,请求或响应被拦截伪造之后再次发出,通信双方也无法知晓。此处请勿与Cookie、token等业务层的身份验证混淆,即使你业务层做了身份验证携带了认证参数,但由于在HTTP协议通信时不存在确认通信方的处理步骤,这也意味着一些代理/中转服务器仍可以携带同样且正确的认证参数,然后篡改请求内容后再次发出,由于携带了正确的认证参数,此时业务代码也无法辨识真伪。我们根据上述所有HTTP安全隐患,就可以轻易发起一次MitM中间人攻击(Man-in-the-Middle Attack,简称MitM攻击)我们通过公共WI-FI以及一定技术手段拦截获取到了一个HTTP转账请求,由于HTTP使用明文传输我们轻易知道了这笔转账的具体信息以及相关参数,我们将这笔转账的接收方改为我自己并且将转账金额变大之后再次发出,由于HTTP无法证明报文的完整性且不验证通信方的身份,因此我们即使篡改了请求内容并再次发出通信双方也感知发现的。因为上述HTTP种种安全隐患,人们对一个加密传输层的需求开始愈发高涨,于是乎HTTPS诞生了!HTTPSHTTPS(Hypertext Transfer Protocol Secure,超文本传输协议安全)是基于HTTP协议的安全版本,它通过在HTTP上建立SSL(Secure Sockets Layer)或TLS(Transport Layer Security)加密层,使得HTTP通信具备身份验证、信息加密和完整性校验的功能,以解决HTTP中的种种安全问题。HTTPS工作流程TCP三次握手由于HTTPS仍是建立在TCP的基础上的,因此建立会话仍是需要进行TCP三次握手的。当然,HTTPS也可以使用已有的TCP连接,直接直接进行TLS/SSL三次握手,而不需要进行TCP三次握手。TLS/SSL首次握手:ClientHello(明文传输)一旦TCP连接建立,客户端会以明文的方式发送TLS/SSL的ClientHello消息,该消息包含一下信息:支持的TLS/SSL版本支持的加密套件列表,包括密码学算法和密钥交换算法的组合支持的压缩方法可选的TLS扩展,如Server Name Indication (SNI) 等ClientHello消息主要用于通知服务器客户端包含了哪些支持的TLS版本号、密码套件列表(包括加密算法和密钥交换算法)、支持的压缩方法等信息。服务器会根据这些信息来选择合适的加密算法和密钥交换方式,以确保通信的机密性和完整性。虽然ClientHello消息是明文传输,但由于ClientHello消息传输的都是一些连接协商内容,它不重要且不隐私,因此即使被中间人监听也不影响,中间人篡改其中内容也没必要,因为篡改其中内容并没有价值,并且篡改内容只可能会导致客户端/服务器协商失败断开连接。TLS/SSL二次握手:ServerHello(明文传输)服务器接收到客户端发来的ClientHellow 消息后,会从客户端支持的TLS/SSL版本选择一个,这通常是客户端支持的最高版本,从客户端提供的加密套件列表中选择一个合适的套件,该套件包括加密算法、密钥交换算法等。在选择完成后会向客户端返回一个ServerHello消息,该消息也是明文传输,包含以下内容:建立通信的参数: 包括选择的TLS 版本号、加密套件等信息数字证书: 这个证书包含服务器的公钥、域名、证书有效期等相关的信息,客户端可以使用该证书来验证服务器的身份。证书链: 服务器通常会返回一个证书链,包括服务器证书和中间CA证书。这个证书链允许客户端验证服务器证书的有效性,并建立信任链。数字证书数字证书就像一个许可证,需要向第三方权威机构(证书颁发机构,Certificate Authority简称CA)申请,以许可该站点能够使用HTTPS,数字证书包含了域名(允许哪个站点使用HTTPS)、有效期(允许使用的时间段),服务器公钥(传输的信息使用该公钥加密后,只能使用服务器的私钥才能解密)、颁发者信息等等内容。此时大家可能会有疑问“使用明文传输数字证书,不是很容易被中间人拦截篡改吗?”数字证书时难以篡改的,这是为什么呢?答案就是数字签名。数字签名是证书颁发机构(CA)的私钥基于证书的内容创建的,包括证书的公钥、域名、颁发者信息、有效期等等。只有持有相应私钥的证书颁发机构才能有效地签署证书,个人通常是无法获得的。拿到数字证书的客户端会根据CA证书的公钥来验证证书的数字签名是否合法,由于数字签名是基于CA证书密钥与内容创建的,因此篡改其内容都会导致证书验证不合法。并且CA证书的公钥存储受到系统或浏览器的保护,以防止未经授权的更改。直接修改证书会导致客户端验证证书不合法,如果想要获取到CA证书的私钥,或是替换掉客户端的公钥也是极其困难的,替换整个数字证书更不可行,因为请求域名都不一样,因此想要篡改数字证书时极其困难的。为什么数字证书难以篡改数字证书的数字签名是证书颁发机构(CA)的私钥基于证书的内容创建的,包括证书的公钥、域名、颁发者信息、有效期等等。只有持有相应私钥的证书颁发机构才能有效地签署证书,个人通常是无法获得私钥的,因此想要通过获取私钥自行签署数字签名也是不可行的。客户端拿到数字证书会根据CA证书的公钥来解密数字签名,解析失败或解析后内容与证书内容不同,证明证书已被篡改,由于CA证书公钥存放在受保护的地方,因此想要通过修改存储在客户端的CA证书公钥来通过验证也是极其困难的。替换整个数字证书更不可行,因为解析完成数字签名后,客户端会发现数字证书的域名怎么与请求域名不一样证书链在现实中并不是由一个证书颁发机构颁发所有证书的,而是设立了一个根证书颁发机构,然后设立了若干层中间证书颁发机构,由上一级颁发机构去颁发验证下一级证书颁发机构的数字证书,直到服务器证书。证书链就是从根证书,然后经过的若干中间证书,最后到服务器证书这一条链路。为啥要这么多中间证书颁发机构呢?直接使用根证书颁发机构颁发所有证书不可以吗?使用多个中间证书颁发机构(Intermediate CAs)的主要原因是安全性和管理的考虑。虽然理论上可以只使用根证书颁发机构(Root CA)颁发所有证书,但多级证书颁发机构体系更加灵活安全。它允许根证书颁发机构将部分权威委托给中间证书颁发机构,从而使中间机构可以颁发证书,同时根机构仍然保持根源信任。这种灵活性允许更好地管理证书颁发和吊销,以及适应组织的复杂结构,有助于隔离风险。如果中间证书颁发机构的私钥被泄漏或被滥用,只需吊销中间机构的证书,而不必吊销根证书颁发机构的证书。为什么服务器要给客户端发送证书链?由于服务器证书是经过若干层中间证书,最终才到达根证书生成的,如果仅发送服务器仅发送服务器证书给客户端,客户端是无法知晓颁发给服务器证书的上层机构是谁,因此无法验证服务器证书的数字签名。服务器发送证书链給客户端,客户端就可以从服务器证书逐级验证中间证书,最终到达根证书。由于根证书公钥是绝对受信任的,因此逐级往下所有数字签名验证成功的证书都是受信任的,最终就形成了从服务器证书到CA根证书的信任链。TLS/SSL三次握手:发送会话密钥(非对称加密,利用服务器公钥)客户端在接收到服务器发送的数字证书后会根据上述验证数字证书/证书链的方式验证数字证书。验证失败则会直接报错然后断开连接,如果验证成功,则会先拿到服务器公钥,生成一个伪随机数,然后根据这个随机数生成会话密钥,最终利用服务器公钥对会话密钥进行非对称加密,最后将加密后的会话密钥发送给服务端。由于非对称加密只能使用服务器私钥解密,因此中间人即使拦截到了经过公钥加密的密文,由于没有私钥也无法解密,因此也无法获得会话密钥,所以经过上述握手,客户端服务端双方都可以确认会话密钥是绝对安全的。服务器接收到加密的会话密钥后会使用其私钥进行解密,然后拿到会话私钥,至此就完成了TSL/SSL三次握手,并进入会话阶段。会话阶段:发送响应内容(对称加密,利用会话密钥) 服务器拿到密钥后,TSL/SSL的三次握手就完成了并进入会话阶段。经过上述握手过程,客户端服务端双方都可以确认会话密钥是绝对安全的,因此在会话阶段双方通信内容就可以使用会话密钥进行对称加密。为什么TSL/SSL握手阶段使用非对称加密,而会话阶段使用对称加密?虽然非对称加密在某些方面非常强大,但它也有一些限制和性能方面的不足,这些限制使得在通信中不适合全部使用非对称加密。· 性能问题:非对称加密算法(如RSA或ECC)比对称加密算法(如AES)更复杂,因此在加密和解密数据时需要更多的计算资源和时间。这对于大量的数据传输或高流量的网络来说可能是一个性能瓶颈。· 密钥管理:非对称密钥对(公钥和私钥)的管理相对复杂。在一个大型网络中,管理数以千计的密钥对会变得非常困难。对称加密只需要一个密钥,因此更容易管理。· 前向保密性:非对称加密通常不提供前向保密性(Forward Secrecy),这意味着如果私钥被泄露,攻击者可以解密以前拦截的加密数据。而对称加密的前向保密性可以更好地防止这种情况。· 密钥长度:为了提供相同级别的安全性,非对称密钥通常需要更长的密钥长度,这会增加数据传输的开销。对称加密在某些情况下是非常高效和快速的,但它也有一些限制,这些限制使得不适合全部使用对称加密:· 密钥分发问题:对称加密需要双方共享相同的密钥,这就引入了密钥分发的问题。如果双方在通信之前没有共享密钥,那么他们需要一个安全的方式来传输密钥。这个过程可能容易受到中间人攻击或者其他安全问题的影响。· 缺乏身份验证:对称加密本身并不提供身份验证机制,这意味着在通信开始之前,没有办法确定通信的另一方是否真的是合法的目标。这使得对称加密容易受到伪装攻击的影响。· 前向保密性:对称加密通常不提供前向保密性,这意味着如果密钥被泄露,攻击者可以解密以前拦截的加密数据。· 密钥轮换:在对称加密中,密钥的轮换和管理可能会更复杂,特别是在大型系统中。如果密钥不定期轮换,或者如果密钥丢失或泄露,整个通信系统的安全性可能会受到威胁。因此,通常情况下,加密方案会采用混合加密的方法,结合对称加密和非对称加密的优点。在通信开始时,使用非对称加密来安全地协商共享的对称密钥,然后在通信会话中使用对称加密来保护实际的数据传输。这种混合加密方法能够同时提供安全性和性能,解决了对称加密和非对称加密各自的限制。HTTPS也不绝对安全HTTPS确实提供了一定程度的安全性,但它并非绝对安全,仍然存在一些潜在的风险和攻击向量会话密钥泄露 :在HTTPS握手过程中,客户端和服务器会交换用于加密通信的会话密钥。如果会话密钥泄露或恶意方能够通过一定手段获取这个会话密钥,他们就可以解密通信内容。客户端发送会话密钥服务端通常不验证客户端身份 : 这是一种称为单向认证的模式,其中服务器验证自己的身份,但不要求客户端提供证书或其他身份验证信息。虽然这在许多互联网应用中很常见,但它确实意味着恶意客户端可以连接到服务器,而服务器难以验证客户端的真实身份。证书链中任何一个节点被污染或私钥泄露,包括服务器私钥 :证书链是用于验证服务器身份的关键组成部分。如果证书链中的任何一个证书受到污染或者私钥泄露,攻击者可能会冒充合法的服务器进行中间人攻击,这会损害通信的机密性和完整性。客户端证书链中任何一个节点公钥被污染替换 : 类似于服务器证书链,客户端证书链中的污染或替换也可能导致安全问题。这通常涉及到客户端的身份验证,如果恶意方能够替换客户端证书链中的公钥,他们可能会冒充合法客户端与服务器通信。· 没有妥善处理HTTP到HTTPS的重定向 :如果一个网站接受 HTTP 的请求,然后重定向到 HTTPS,用户可能在开始重定向前,通过没有加密的方式与服务器通信,比如,用户输入 http://foo.com 或者仅是输入 foo.com。这样为中间人攻击创造了机会。可以利用重定向将用户引导至恶意站点,而不是原始站的安全版本。HTTP重定向HTTPS的安全隐患如果一个网站接受 HTTP 的请求,然后重定向到 HTTPS,用户可能在开始重定向前,通过没有加密的方式与服务器通信,比如,用户输入 http://foo.com 或者仅是输入 foo.com。这样为中间人攻击创造了机会。可以利用重定向将用户引导至恶意站点,而不是原始站的安全版本。你登录到一个免费 Wi-Fi 热点,然后开始浏览网站,访问你的网上银行,查看你的支出,并且支付一些订单。很不幸,你接入的 Wi-Fi 实际上是黑客的笔记本热点,他们拦截了你原始的 HTTP 请求,然后重定向到一个与你银行网站一模一样的钓鱼网站。现在,你的隐私数据暴露给黑客了。为解决这一问题,HTTP推出了HSTS(HTTP Strict Transport Security Preload,安全的预加载),它通过设置HTTP响应标头中的Strict-Transport-Security字段,要求浏览器在与特定网站通信时强制使用HTTPS连接,从而减少中间人攻击的风险。Strict-Transport-Security响应标头HTTP Strict-Transport-Security(通常简称为 HSTS)响应标头用来通知浏览器应该只通过 HTTPS 访问该站点,并且以后使用 HTTP 访问该站点都应自动重定向到 HTTPS。参数max-age=< expire-time >    只能使用 HTTPS 访问该站点的有效期(以秒为单位)includeSubDomains 可选    如果这个参数存在,那么代表此规则也适用于该网站的所有子域名preload 可选 非标准    如果该参数存在,意味着该站点希望并且可以申请加入到google提供的HSTS预加载列表站点示例// 该域名会自动使用 HTTPS,有效期(max-age)为一年。 Strict-Transport-Security: max-age=31536000 // 该域名与其所有子域名会自动使用 HTTPS,有效期(max-age)为一年。 Strict-Transport-Security: max-age=31536000; includeSubDomains // 该域名与其所有子域名会自动使用 HTTPS,有效期(max-age)为一年。 // 且该站点希望并且可以申请加入到google提供的HSTS预加载列表站点 Strict-Transport-Security: max-age=<expire-time>; includeSubDomains; preload浏览器是如何处理的你的网站第一次通过 HTTPS 请求,服务器响应 Strict-Transport-Security 标头,浏览器记录下这些信息,然后后面尝试访问这个网站的请求都会自动把 HTTP 替换为 HTTPS。当 Strict-Transport-Security 标头设置的过期时间到了,后面通过 HTTP 的访问恢复到正常模式,不会再自动重定向到 HTTPS。每次浏览器接收到 Strict-Transport-Security 标头,它都会更新这个网站的过期时间,所以网站可以刷新这些信息,防止过期发生。如果有禁用 Strict-Transport-Security 的需求,将 max-age 设置为 0(通过 https 连接)将立即使 Strict-Transport-Security 标头失效,从而可以通过 http 访问。预加载 HSTS从上述危险提示中我们知道Strict-Transport-Security 标头在HTTP中是无效的,因此用户第一次并且使用HTTP访问站点时,同样可能遭受中间人攻击,被引导至钓鱼网站。为解决这个问题,Google维护着一个HSTS 预加载列表,当你的响应中Strict-Transport-Security 标头包含了preload参数,你就可以向Google提供的HSTS预加载列表站点提交你的域名,以申请加入HSTS预加载列表中浏览器厂商会定期更新他们的HSTS预加载列表,并将符合条件的网站添加到列表中。一旦网站被包括在HSTS预加载列表中,浏览器将自动应用HSTS策略,即使用户首次以HTTP链接方式访问该网站。总结HTTP与HTTPS的区别HTTPHTTPS明文传输加密传输不进行身份验证进行身份验证无法验证报文完整性报文完整性保护一般使用80端口一般使用443端口......HTTPS的工作流程并非绝对安全的HTTPS· 会话密钥泄露 :在HTTPS握手过程中,客户端和服务器会交换用于加密通信的会话密钥。如果会话密钥泄露或恶意方能够通过一定手段获取这个会话密钥,他们就可以解密通信内容。· 客户端发送会话密钥服务端通常不验证客户端身份 : 这是一种称为单向认证的模式,其中服务器验证自己的身份,但不要求客户端提供证书或其他身份验证信息。虽然这在许多互联网应用中很常见,但它确实意味着恶意客户端可以连接到服务器,而服务器难以验证客户端的真实身份。· 证书链中任何一个节点被污染或私钥泄露,包括服务器私钥 :证书链是用于验证服务器身份的关键组成部分。如果证书链中的任何一个证书受到污染或者私钥泄露,攻击者可能会冒充合法的服务器进行中间人攻击,这会损害通信的机密性和完整性。· 客户端证书链中任何一个节点公钥被污染替换 : 类似于服务器证书链,客户端证书链中的污染或替换也可能导致安全问题。这通常涉及到客户端的身份验证,如果恶意方能够替换客户端证书链中的公钥,他们可能会冒充合法客户端与服务器通信。· 没有妥善处理HTTP到HTTPS的重定向 :如果一个网站接受 HTTP 的请求,然后重定向到 HTTPS,用户可能在开始重定向前,通过没有加密的方式与服务器通信,比如,用户输入 http://foo.com 或者仅是输入 foo.com。这样为中间人攻击创造了机会。可以利用重定向将用户引导至恶意站点,而不是原始站的安全版本。

0
0
0
浏览量1805
爱喝奶茶的波波

【HTTP完全注解】长连接与短连接

长连接与短连接HTTP/0.9HTTP 的第一个文档版本是HTTP/0.9,于 1991 年提出。它是有史以来最简单的协议;有且只有一个名为 GET 的方法。如果客户端必须访问服务器上的某个网页,它会发出如下简单的请求GET /index.html服务器会收到请求,用 HTML 作为响应进行回复,一旦内容传输完毕,连接就会关闭,服务器的响应如下所示(response body) (connection closed)可以见得,当时的HTTP协议非常简单,并且通常它只需要发出一次请求就可获得所有的内容,当时的网络条件完全能满足此时HTTP协议的需求,因此人们并不在意发出的请求是否应该保持TCP网络连接,所以当时并未规定HTTP协议是否应该保持TCP网络连接。HTTP/1.01996 年,HTTP 的下一个版本即 HTTP/1.0 比原始版本有了很大改进。与仅为 HTML 响应设计的 HTTP/0.9 不同,HTTP/1.0 现在可以处理其他响应格式,即图像、视频文件、纯文本或任何其他内容类型。它添加了更多方法(即 POST 和 HEAD),更改了请求/响应格式,将 HTTP 标头添加到请求和响应中,添加了状态代码以识别响应,引入了字符集支持,多部分类型,授权、缓存、内容编码等。以下是示例 HTTP/1.0 请求的样子:GET / HTTP/1.0 Host: cs.fyi User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) Accept: */*以下是示例 HTTP/1.0 响应的样子:HTTP/1.0 200 OK Content-Type: text/plain Content-Length: 137582 Expires: Thu, 05 Dec 1997 16:00:00 GMT Last-Modified: Wed, 5 August 1996 15:55:28 GMT Server: Apache 0.84 ​ (response body) (connection closed)相较于HTTP/0.9,可以看到HTTP/1.0可以处理并且响应除了HTML以外的其他类型的请求,如图像、视频、HTML、纯文本等。也是由于加入了很多其他类型的内容,如今不再能够发出一次请求就可获得所有的内容,通常获取完整内容需要发送几次甚至十几次请求才能获得,比如您访问的网页有 10 个图像、5 个样式表和 5 个 javascript 文件,当您需要获取网页完整且正确的内容时,需要发出总共 20 个请求。由于HTTP/1.0与HTTP/0.9一样,每次请求它就必须打开一个新的 TCP 连接,并且在满足该单个请求后,连接将关闭。对于任何下一个要求,它都必须建立在新的连接上。因此上述网页将会发起一系列 20 个独立的连接,并且服务器只能根据这些独立的连接一个接一个地处理提供响应。我们都知道每打开一个 TCP 连接都是相当耗费资源的操作,客户端和服务器端之间需要交换很多次消息,并且其中的网络延迟和带宽都会对这个过程造成巨幅的影响,从而导致整个一系列的请求变慢,对性能造成了影响。 为了解决这个问题 HTTP/1.0 的实现试图通过引入一个名为 Connection: keep-alive 的新标头来解决这个问题,但是,最终它仍然没有得到广泛支持,问题仍然存在。HTTP/1.1在 HTTP/1.0 仅推出 3 年后,下一个版本即 HTTP/1.1 于 1999 年发布,在 HTTP/1.0 中,每个连接只有一个请求,并且连接在请求完成后立即关闭,这导致了严重的性能损失和延迟问题。HTTP/1.1 引入了持久连接,即默认情况下连接不会关闭(Connection:keep-alive),而是保持打开状态,允许多个顺序请求。要关闭连接,请求头Connection: close必须可用。客户端通常在最后一个请求中发送此标头以安全关闭连接。当然持久连接不全然都是好处,它也有自身的缺点,在空闲状态,它还是会消耗服务器资源,而且在重负载时,还有可能遭受 DoS 攻击。此外,HTTP/1.1还引入了HTTP pipelining(HTTP管道化)技术,默认情况下,HTTP请求是按顺序发出的。下一个请求只有在当前请求收到响应过后才会被发出。由于会受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间。HTTP pipelining其实就是把多个HTTP请求放到一个TCP连接中一一发送,只不过在之前的协议中,下一个请求需要等到当前请求响应后发送,而HTTP pipelining则是在发送过程中不需要等待服务器对前一个请求的响应就可以发送下一个请求,这样可以避免连接延迟。想法确实很美好,但由于线头阻塞问题即使到了今天,大部分桌面浏览器仍然会选择默认关闭HTTP pipelining这一功能。至此,HTTP/1.1初步完成了对网络链接的优化:短连接、长连接、HTTP管道化。短连接、长连接、HTTP管道化网络连接标头特点缺点短连接Connection: closeHTTP 最早期的和 HTTP/1.0 的值, 每次请求它就必须打开一个新的 TCP 连接,并且在满足该单个请 求后,连接将关闭。对于任何下一 个请求,它都必须建立在新的连接上。每次 TCP 连接都是相当耗费资源的, 极大影响了请求的响应速度长链接Connection: keep-aliveHTTP/1.1请求的默认值,每次请求 它会保持TCP连接一定时间,后续 对同一服务器的请求它将使用该 连接完成,无需重新建立连接在空闲状态,它还是会消耗服务器 资源,而且在重负载时,还有可能 遭受 DoS 攻击管道化无同一条长连接上发出连续的请求, 而不用等待应答返回线头阻塞相关标头Connection 请求标头Connection 控制网络连接在当前请求完成后是否仍然保持连接状态。 如果发送的值是 keep-alive,它会保持连接去完成后续对同一服务器的请求;如果发送值是close,它每发起一个请求时都会创建一个新的网络连接,并在收到应答时立即关闭。参数该请求标头并无其他参数取值close    短连接:不保持网络连接,它每发起一个请求时都会创建一个新的网络连接,并在收到应答时立即关闭。 这是 HTTP/1.0 请求的默认值keep-alive    长连接:保持网络连接,它会保持连接去完成后续对同一服务器的请求,这是 HTTP/1.1请求的默认值示例Connection: keep-alive Connection: closeKeep-Alive 请求标头当请求头Connection为keep-alive时(请求保持连接去完成后续对同一服务器的请求),可通过设置Keep-Alive请求头来指定空闲的连接需要保持的最小时长以及该连接可以发送的最大请求数量。参数timeout=<number>    指定了一个空闲连接需要保持打开状态的最小时长(以秒为单位)。需要注意的是,如果没有在传输层设置 keep-alive TCP message 的话,大于 TCP 层面的超时设置会被忽略。max=<number>    在连接关闭之前,在此连接可以发送的请求的最大值。在非管道连接中,除了 0 以外,这个值是被忽略的,因为需要在紧跟着的响应中发送新一次的请求。HTTP 管道连接则可以用它来限制管道的使用示例Keep-Alive: timeout=5, max=1000线头阻塞(Head-of-line blocking)HTTP pipelining将多个HTTP请求放到一个TCP连接中一一发送,而在发送过程中不需要等待服务器对前一个请求的响应;只不过,客户端还是要按照发送请求的顺序来接收响应。但不管怎么处理,服务器是要按照顺序处理请求的,如果前一个请求非常耗时,那么后续的请求都会受到影响,这就是所谓的线头阻塞(head-of-line blocking)。当然,你可以在选择队伍时候就做好功课,去排一个你认为最快的队伍,或者甚至另起一个新的队伍(译者注:即新建一个TCP连接)。但不管怎么样,你总归得先选择一个队伍,而且一旦选定之后,就不能更换队伍。但是,另起新队伍会导致资源耗费和性能损失(译者注:新建 TCP 连接的开销非常大)。这种另起新队伍的方式只在新队伍数量很少的情况下有作用,因此它并不具备可扩展性。(译者注:这段话意思是说,靠大量新建连接是不能有效解决延迟问题的,即HTTP pipelining并不能彻底解决head-of-line blocking问题。)所以针对此问题并没有完美的解决方案。这就是为什么即使到了今天,大部分桌面浏览器仍然会选择默认关闭HTTP pipelining这一功能的原因。那些年,克服延迟之道再困难的问题也有解决的方案,但这些方案却良莠不齐。SpritingSpriting是一种将很多较小的图片合并成一张大图,再用JavaScript或者CSS将小图重新“切割”出来的技术。网站可以利用这一技巧来达到提速的目的——在HTTP 1.1里,下载一张大图比下载100张小图快得多。但是当某些页面只需要显示其中一两张小图时,这种缓存整张大图的方案就显得过于臃肿。同时,当缓存被清除的时候的时候,Spriting会导致所有小图片被同时删除,而不能选择保留其中最常用的几个。内联(Inlining)Inlining是另外一种防止发送很多小图请求的技巧,它将图片的原始数据嵌入在CSS文件里面的URL里。而这种方案的优缺点跟Spriting很类似。.icon1 { background: url(data:image/png;base64,<data>) no-repeat; } .icon2 { background: url(data:image/png;base64,<data>) no-repeat; }拼接(Concatenation)大型网站往往会包含大量的JavaScript文件。开发人员可以利用一些前端工具将这些文件合并为一个大的文件,从而让浏览器能只花费一个请求就将其下载完,而不是发无数请求去分别下载那些琐碎的JavaScript文件。但凡事往往有利有弊,如果某页面只需要其中一小部分代码,它也必须下载完整的那份;而文件中一个小小的改动也会造成大量数据的被重新下载。这种方案也给开发者造成了很大的不便。分片(Sharding)最后一个我要说的性能优化技术叫做“Sharding”。顾名思义,Sharding就是把你的服务分散在尽可能多的主机上。这种方案乍一听比较奇怪,但是实际上在这背后却蕴藏了它独辟蹊径的道理!最初的HTTP 1.1规范提到一个客户端最多只能对同一主机建立两个TCP连接。因此,为了不和规范冲突,一些聪明的网站使用了新的主机名,这样的话,用户就能和网站建立更多的连接,从而降低载入时间。后来,两个连接的限制被取消了,现在的客户端可以轻松地和每个主机建立6-8个连接。但由于连接的上限依然存在,所以网站还是会用这种技术来提升连接的数量。而随着资源个数的提升(上面章节的图例),网站会需要更多的连接来保证HTTP协议的效率,从而提升载入速度。在现今的网站上,使用50甚至100个连接来打开一个页面已经并不罕见。根据httparchive.org的最新记录显示,在Top 30万个URL中平均使用40(!)个TCP连接来显示页面,而且这个数字仍然在缓慢的增长中。另外一个将图片或者其他资源分发到不同主机的理由是可以不使用cookies,毕竟现今cookies的大小已经非常可观了。无cookies的图片服务器往往意味着更小的HTTP请求以及更好的性能!下面的图片展示了访问一个瑞典著名网站的时产生的数据包,请注意这些请求是如何被分发到不同主机的。HTTP/2HTTP/2是专为降低内容传输延迟而设计,我们可以看下改善核心:降低协议对延迟的敏感修复pipelining和head of line blocking的问题防止主机需求更高的连接数量保留所有现有的接口,内容,URI格式和结构由IETF的HTTPbis工作组来制定二进制协议HTTP/2 倾向于通过使其成为二进制协议来解决 HTTP/1.x 中存在的延迟增加的问题。作为一个二进制协议,它更容易解析,但与 HTTP/1.x 不同的是,它不再被人眼读取。HTTP/2 的主要构建块是帧和流。帧与流HTTP 消息现在由一个或多个帧组成。有一个用于元数据的 HEADERS 帧和用于有效负载的 DATA 帧,并且存在几种其他类型的帧(HEADERS、DATA、RST_STREAM、SETTINGS、PRIORITY 等)。每个 HTTP/2 请求和响应都被赋予一个唯一的流 ID,并且它被分成帧。帧不过是二进制数据。帧的集合称为流。每个帧都有一个流 ID,用于标识它所属的流,并且每个帧都有一个公共标头。此外,除了流 ID 是唯一的,值得一提的是,客户端发起的任何请求都使用奇数,而来自服务器的响应具有偶数流 ID。中断连接HTTP 1.1的有一个缺点是:当一个含有确切值的Content-Length的HTTP消息被送出之后,你就很难中断它了。当然,通常你可以断开整个TCP链接(但也不总是可以这样),但这样导致的代价就是需要通过三次握手来重新建立一个新的TCP连接。在http2里面,我们可以通过发送RST_STREAM帧来实现这种需求,它是一种特殊的帧类型,用于中止某些流,即客户端可以发送此帧让服务器知道我不需要此流了。客户端可以使用 RST_STREAM 并停止接收特定流,同时连接不会被关闭其他流仍会正常运行。优先级每个流都包含一个优先级(也就是“权重”),它被用来告诉对端哪个流更重要。当资源有限的时候,服务器会根据优先级来选择应该先发送哪些流。借助于PRIORITY帧,客户端同样可以告知服务器当前的流依赖于其他哪个流。该功能让客户端能建立一个优先级“树”,所有“子流”会依赖于“父流”的传输完成情况。优先级和依赖关系可以在传输过程中被动态的改变。这样当用户滚动一个全是图片的页面的时候,浏览器就能够指定哪个图片拥有更高的优先级。或者是在你切换标签页的时候,浏览器可以提升新切换到页面所包含流的优先级。多路复用由于 HTTP/2 现在是二进制协议,并且正如我上面所说,它使用帧和流来进行请求和响应,因此一旦打开 TCP 连接,所有流都会通过同一连接异步发送,而无需打开任何其他连接。反过来,服务器以相同的异步方式响应,即响应没有顺序,客户端使用分配的流 ID 来识别特定数据包所属的流。流的多路复用解决了 HTTP/1.x 中存在的线头阻塞问题,即客户端不必等待正在花费时间的请求,其他请求仍将得到处理。头压缩HTTP是一种无状态的协议。简而言之,这意味着每个请求必须要携带服务器需要的所有细节,而不是让服务器保存住之前请求的元数据。因为http2并没有改变这个范式,所以它也以同样原理工作。这也保证了HTTP可重复性。当一个客户端从同一服务器请求了大量资源(例如页面的图片)的时候,所有这些请求看起来几乎都是一致的,而这些大量一致的东西则正好值得被压缩。

0
0
0
浏览量1740
绝对勇士

【HTTP协议基础知识分享1】HTTP“请求-响应”模式及常见的HTTP方法

一、 HTTP简介HTTP的定义和作用HTTP(Hypertext Transfer Protocol)是一种用于传输超文本的应用层协议。它是在Web上进行数据通信的基础,允许将超文本文档从Web服务器传输到本地浏览器。HTTP是一个无状态的协议,意味着每个请求都是独立的,服务器不会保留关于之前请求的任何信息。HTTP协议的作用包括但不限于:•在客户端和服务器之间传输网页、图片、视频等资源•支持各种不同类型的内容,例如HTML、CSS、JavaScript等•实现网页的超链接功能,使得用户可以通过点击链接访问其他页面•支持Web表单,用于向服务器提交数据HTTP的发展历史HTTP协议最初由蒂姆·伯纳斯-李(Tim Berners-Lee)在1989年创建,是为了支持他设计的全球信息系统(World Wide Web)而开发的。最早的版本是0.9,之后发展到1.0和1.1版本。HTTP/1.1是目前使用最广泛的版本,它引入了许多新特性,例如持久连接、管道化、虚拟主机等,以提高性能和减少延迟。在今天的互联网世界中,HTTP已经成为万维网的基础协议之一,为人们浏览网页、传输数据提供了重要支持。随着互联网的不断发展,HTTP协议也在不断演进,以满足更加复杂和多样化的网络应用需求。二、 HTTP请求和响应请求-响应模式HTTP协议采用了请求-响应模式,客户端向服务器发送一个HTTP请求,服务器接收并处理该请求后,返回一个HTTP响应。这种模式是HTTP通信的基础,通过它实现了客户端和服务器之间的数据交换。请求和响应的组成结构请求结构•请求行:包括请求方法(GET、POST等)、请求的URL和协议版本•头部:包含了一些关于客户端和请求的信息,比如User-Agent(用户代理)、Host(主机)、Accept(可接受的媒体类型)等•请求体:可选的部分,包含了客户端传输给服务器的数据,比如表单数据或上传的文件响应结构•状态行:包括协议版本、状态码和相应状态消息•头部:包含了一些关于服务器和响应的信息,比如Server(服务器软件信息)、Content-Type(内容类型)、Content-Length(内容长度)等•消息体:包含了服务器返回给客户端的数据,比如HTML页面、图片、视频等让我们概括这种模式就是HTTP请求和响应的结构都很清晰明了,这个模式里面每个部分都有特定的作用,正是因为这种结构化的设计使得HTTP协议具有较好的灵活性和扩展性,能够很好地适应不同类型的内容和多样化的网络应用需求。三、 HTTP方法常见的HTTP方法HTTP定义了多种不同的请求方法,其中常见的包括:•GET:从服务器获取资源,通常用于请求页面或图片等静态内容•POST:向服务器提交数据,通常用于提交表单或上传文件•PUT:将资源上传到指定URI,如果已存在则进行更新,如果不存在则创建•DELETE:删除指定URI的资源•HEAD:与GET类似,但只返回响应头部,不包含实际内容•OPTIONS:用于获取目标资源支持的通信选项•PATCH:对资源进行部分修改HTTP方法的作用不同的HTTP方法具有不同的作用,它们使得HTTP协议能够支持各种不同类型的操作和数据交互。其中,GET用于获取资源,POST用于提交数据,PUT用于更新资源,DELETE用于删除资源,而HEAD则常用于获取资源的元信息而不获取实际内容。这些方法的存在丰富了HTTP协议的功能,使得它可以满足各种不同场景下的需求。RESTful架构中的HTTP方法在RESTful架构中,HTTP方法被赋予了更加具体的语义,比如GET用于获取资源,POST用于新建资源,PUT用于更新资源,DELETE用于删除资源。这种基于HTTP方法的RESTful设计风格使得API的设计更加直观和符合标准化,也更容易被理解和使用。综上所述,HTTP方法是HTTP协议的重要组成部分,不同方法的存在丰富了协议的功能,并且在RESTful架构中扮演着关键的角色,帮助实现了资源的操作和管理。总结到这里我们今天关于HTTP协议基础部分知识分享就结束啦~在下一节我会为大家继续介绍另一部分:HTTP的状态码以及URL基础知识点

0
0
0
浏览量2037
爱喝奶茶的波波

【HTTP完全注解】又跨域了?一文解释清楚跨源资源共享(cors)

又跨域了?一文解释清楚跨源资源共享(cors)为确保在Web浏览器中来自不同源的网页或脚本不能随意访问和操纵其他源的资源和数据,保障网站只能在受信任的环境中访问和共享数据,HTTP引入了同源策略(Same Origin Policy,简称SOP)。同源策略的出现极大的增强了Web的安全性并有效的防止了CSRF攻击,但也随之带来了许多开发上的问题与麻烦,特别是当我们需要在与不同源(不同域名、不同协议、不同端口)的资源进行通信和访问时尤为明显,比如下面这个例子:wangjunliang.com需要请求访问wangawang.com的内容,由于同源机制的存在, XMLHttpRequest(XHR)或 Fetch API是不允许发起跨域的请求的,当然我们可以通过代理或Jsonp的方式来解决,但每次搭建代理过于麻烦并且维护成本很大,而Jsonp呢?则是存在很多潜在的安全风险,容易被攻击者利用。综上所述,HTTP急需引入一种安全的、高效的、标准化的跨源访问机制,于是乎跨源资源共享(Cross Origin Resource Sharing,简称CORS) 机制则诞生了跨源资源共享跨域资源共享(Cross-Origin Resource Sharing,CORS)是一种网络安全机制,用于在Web应用中控制跨域请求的访问权限,允许 Web 对不同源的服务器进行跨源资源访问,并使跨源数据传输得以安全进行CORS机制通过一系列的请求标头来表明该跨域请求的来源、方法以及所携带请求头部(这些请求标头无需自己配置,由浏览器自动携带),服务端接收请求后通过这些请求标头来判断是否允许这些源访问加载自己的资源,并返回一系列的响应标头告知相关信息。 由于CORS机制的相关请求标头都是浏览器自动携带的,因此CORS机制的配置通常发生在服务端而不是客户端,服务端需要通过适当配置 HTTP 响应标头来允许或拒绝跨域请求CORS相关请求标头CORS机制的相关请求标头都是浏览器自动携带的,无须手动设置Origin请求标头Origin表示了请求的来源(协议、主机、端口)参数该请求标头并无其他参数取值null    请求的来源是“隐私敏感”的,或者是 HTML 规范定义的不透明来源< scheme>://< hostname>    请求的协议+源站的域名或 IP 地址< scheme>://< hostname>:< port>    请求的协议+源站的域名或IP地址+端口号(缺省为服务器的默认端口)示例Origin: https://wangjunliang.com Origin: https://wangjunliang.com:80Access-Control-Request-Method请求标头Access-Control-Request-Method 表示真正的请求会采用的请求方法,该请求标头出现于 preflight request(预检请求)中,因为预检请求所使用的方法总是OPTIONS ,与实际请求所使用的方法不一样,所以使用该请求头通知服务器在真正的请求中会采用哪种HTTP 方法参数    该请求标头并无其他参数取值<method>    一种HTTP的请求方法,如:GET、POST或DELETE等,表示真正的请求会采用的请求方法示例Access-Control-Request-Method:GET Access-Control-Request-Method: POSTAccess-Control-Request-Headers请求标头Access-Control-Request-Headers 表示真正的请求会携带的请求标头,该请求标头出现于 preflight request(预检请求)中,因为预检请求所使用的方法总是 OPTIONS,与实际请求所携带的请求标头不一样,所以使用该请求头通知服务器在真正的请求中会携带哪些请求标头参数    该请求标头并无其他参数取值[<header-name>,<header-name>,<header-name>...]    一系列HTTP请求标头,以逗号分隔,表示真正的请求会携带的请求标头示例Access-Control-Request-Headers: X-PINGOTHER, Content-Type Access-Control-Request-Headers: X-ADC, Content-TypeCORS相关响应标头CORS机制主要通过服务端适当配置 HTTP 响应标头来允许或拒绝跨域请求Access-Control-Allow-Origin响应标头Access-Control-Allow-Origin 响应标头指定了该资源能否被给定的来源(Origin请求标头)的请求访问参数    该响应标头并无其他参数取值*    允许任意来源的请求访问资源(当使用*来响应包含凭据的请求会导致错误)<scheme>://<hostname>:<port>    指定一个来源(只能指定一个),协议+源站的域名或IP地址+端口号(缺省为服务器的默认端口)。仅允许该来源的请求访问资源null    仅允许来源为null的请求访问资源示例Access-Control-Allow-Origin: * Access-Control-Allow-Origin: https://wangjunliang.comAccess-Control-Allow-Methods响应标头Access-Control-Allow-Methods表示客户端所要访问的资源允许使用的请求方法参数    该响应标头并无其他参数取值*    当请求没有携带凭据(请求没有Cookie或认证信息),允许所有请求方法访问资源;当请求带有凭据时,会被简单地当作值“*”,没有特殊的语义[<method>,<method>,<method>...]    一系列HTTP请求方法,以逗号分隔,表示访问的资源允许使用的请求方法示例Access-Control-Allow-Methods: * Access-Control-Allow-Methods: POST, GET, OPTIONSAccess-Control-Allow-Headers响应标头Access-Control-Allow-Headers表示客户端所要访问的资源允许使用的请求标头,CORS 安全列表的标头无需特意列出,它始终被支持参数    该响应标头并无其他参数取值*    当请求没有携带凭据(请求没有Cookie或认证信息),允许携带任何请求标头的请求访问资源;当请求带有凭据时,会被简单地当作值“*”,没有特殊的语义[<header-name>,<header-name>,<header-name>...]    一系列HTTP请求标头,以逗号分隔,表示访问的资源允许使用的请求标头示例Access-Control-Allow-Headers: * Access-Control-Allow-Headers: X-Custom-Header, Upgrade-Insecure-RequestsAccess-Control-Max-Age响应标头Access-Control-Max-Age 表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers提供的信息)可以被缓存多久。 该标头仅能控制 preflight request (预检请求)的响应的缓存时间,对于简单的跨源请求的缓存策略通常由HTTP缓存头部(如Cache-Control、Expires等)来控制参数    该响应标头并无其他参数取值<seconds>    返回结果可以被缓存的最长时间(秒)。 在 Firefox 中,上限是 24 小时 (即 86400 秒)。 在 Chromium v76 之前, 上限是 10 分钟(即 600 秒)。 从 Chromium v76 开始,上限是 2 小时(即 7200 秒)。 Chromium 同时规定了一个默认值 5 秒。 如果值为 -1,表示禁用缓存,则每次请求前都需要使用 OPTIONS 预检请求。示例Access-Control-Max-Age: 60 //1分钟 Access-Control-Max-Age: 600 //10分钟Access-Control-Expose-Headers响应标头Access-Control-Expose-Headers 允许服务器指示那些响应标头可以暴露给浏览器中运行的脚本,以响应跨源请求。在跨源访问时,XMLHttpRequest 对象的 getResponseHeader() 方法只能拿到CORS 安全列表的响应标头,如:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma等,如果想要让客户端可以访问到其他的标头,服务器必须将它们在 Access-Control-Expose-Headers 里面列出来参数    该响应标头并无其他参数取值*    当请求没有携带凭据(请求没有Cookie或认证信息),浏览器中运行的脚本允许访问所有响应标头;当请求带有凭据,会被简单地当作值“*”,没有特殊的语义[<header-name>,<header-name>,<header-name>...]    一系列HTTP响应标头,以逗号分隔,表示哪些响应标头可以暴露给浏览器中运行的脚本示例Access-Control-Expose-Headers: Content-Encoding Access-Control-Expose-Headers: Content-Encoding, Kuma-RevisionAccess-Control-Allow-Credentials响应标头Access-Control-Allow-Credentials 表示客户端所要访问的资源是否允许使用credentials(认证信息,如:cookie等),参数    该响应标头并无其他参数取值true    这个头的唯一有效值(区分大小写)。如果不需要 credentials,相比将其设为 false,请直接忽视这个头。示例Access-Control-Allow-Credentials: true复杂请求与简单请求由于同源策略对于XHR/Fetch API的约束为:请求可以发送到不同来源的服务器,服务端能够接收并处理,只是前端无法读取返回数据。因此我们必须对可能对服务器数据产生副作用的 HTTP 请求方法采取必要的验证手段,不然任何修改数据的跨源攻击都能被发送到服务器并且被正确处理,而攻击者仅仅是不能够得到请求返回内容而已。对此CORS将请求分为了简单请求与复杂请求,对于简单请求而言,只要满足CORS相关规则即可进行跨域访问;但对于复杂请求而言,浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨源请求,服务器确认允许之后,才发起实际的 HTTP 请求。简单请求满足所有下述条件,则该请求可视为简单请求:使用以下方法之一:    GET、HEAD、POST仅使用了浏览器自动设置的标头、 Fetch 规范中定义为禁用标头名称的标头以及CORS安全的标头字段集合中的标头,例如:    Accept、Accept-Language、Content-Language、Content-Type、RangeContent-Type仅限于下列三者之一:    text/plain、multipart/form-data、application/x-www-form-urlencoded如果请求是使用 XMLHttpRequest 对象发出的,在返回的 XMLHttpRequest.upload 对象属性上没有注册任何事件监听器;也就是说,给定一个 XMLHttpRequest 实例 xhr,没有调用 xhr.upload.addEventListener(),以监听该上传请求请求中没有使用 ReadableStream对象对于简单请求而言,只要满足CORS相关标头即可进行跨域访问假如站点 wangjunliang.com 的网页想要访问 wangawang.com 的资源,并发起的是简单请求,此时请求只要满足了服务端相关CORS的响应标头配置,请求则能正常访问资源,以下为客户端与服务器端交互示例客户端wangjunliang.com 向服务端 wangawang.com 发起了一个跨源请求,由于该请求满足简单请求的条件,因此浏览器将发起一个简单请求,并且该请求还携带了Cookie信息。由于服务端允许该源访问并且允许携带Cookie信息,因此服务器会正常处理并响应请求内容,其中响应头中Access-control-Allow-Origin包含了允许访问该资源的源列表,Access-Control-Allow-Credentials为true表示允许携带Cookie等身份认证头。复杂请求当请求不满足简单请求的条件时,则为复杂请求。与简单请求不同,对于复杂请求浏览器会首先使用 OPTIONS方法自动发起一个预检请求到服务器,以获知服务器是否允许该实际请求。 由于同源策略对于XHR/Fetch API的约束为:请求可以发送到不同来源的服务器,服务端能够接收并处理,只是前端无法读取返回数据。因此我们必须对可能对服务器数据产生副作用的 HTTP 请求方法进行"预检“,避免跨域请求对服务器的数据产生未预期的影响。以下是一个需要执行预检的跨源访问例子:客户端wangjunliang.com 向服务端 wangawang.com 发起了一个跨源请求,由于该请求需要携带两个自定义的标头(X-PINGOTHER 与 Content-Type),因此该请求是一个复杂请求,浏览器将首先发起一个预检请求。预检请求将自动携带标头字段 Access-Control-Request-Method 告知服务器,实际请求将使用 POST 方法、标头字段Access-Control-Request-Headers 告知服务器,实际请求将携带两个自定义请求标头字段:X-PINGOTHER 与 Content-Type。服务器据此决定,该实际请求是否被允许如果服务器允许该请求,就会如上图所示返回相应的响应内容:    . Access-Control-Allow-Origin: https://wangjunliang.com表示允许wangjunliang.com访问该资源    .Access-Control-Allow-Methods 表示允许客户端使用 POST 和 GET 方法发起请求    .Access-Control-Allow-Headers 表示允许请求中携带字段 X-PINGOTHER 与 Content-Type标头    .Access-Control-Max-Age 给定了该预检请求可供缓存的时间长短,单位为秒,默认值是 5 秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。以上例子中,该响应的有效时间为 86400 秒,也就是 24 小时。请注意,浏览器自身维护了一个最大有效时间,如果该标头字段的值超过了最大有效时间,将不会生效最后预检请求完成之后,客户端发送实际请求,服务端根据请求处理响应即完成需要注意的地方当携带了Cookie等认证信息的跨源请求,响应标头Access-Control-Allow-Origin、Access-Control-Allow-methods、Access-Control-Allow-heders、Access-Control-Expose-Headers都不能为*当简单请求携带了Cookie等认证信息,如果响应中缺失 Access-Control-Allow-Credentials: true响应标头,则响应内容会被忽略,不会提供给 web ;如果存在该响应标头,则必须携带Cookie等认证信息。当复杂请求的预检响应中缺失 Access-Control-Allow-Credentials: true响应标头,实际请求则不能携带Cookie等认证信息,如果存在,实际请求则必须携带Cookie等认证信息携带Authorization请求标头会把简单请求变为复杂请求

0
0
0
浏览量1726
绝对勇士

从 xhr 到$.ajax、fetch 轻松开启异步通信的新境界

引言在前端Web开发里,AJAX(异步JavaScript和XML)就像一支法宝,让你的网页可以在不刷新的情况下与服务器悄悄聊天,无需重新刷新页面,也可以实现网页与服务器之间进行无缝通信。而这三招:XMLHttpRequest、jQuery中的$.ajax,以及现代的Fetch API,它们就像是三种神奇的武功,各自有各自的绝学。今天让我们探讨这三种不同的AJAX实现方式,一起来领略AJAX的魅力!一、XMLHttpRequestXMLHttpRequest对象是AJAX的基础,自其诞生以来就一直是不可或缺的组成部分。它就像是AJAX的老祖宗,像是用一把古老的键盘敲出来的代码,悠久而又经典。const btn = document.getElementById('btn'); btn.addEventListener('click', () => { let xhr = new XMLHttpRequest(); xhr.open('GET', 'http://example.com/api/data', true); xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { let result = JSON.parse(xhr.responseText); console.log(result); } }; xhr.send(); });我们上面这段代码的功能简单来说就是通过XHR(XMLHttpRequest)方法实现向后端提供的URL拿取数据,当我们点击按钮时,就会发出请求实现AJAX从服务器异步获取歌曲信息并更新页面内容。让我们来对这些代码解释一下:解释:1.按钮触发事件: 通过JavaScript获取按钮元素,添加点击事件监听器。2.AJAX请求配置: 当我们用老式的XMLHttpRequest对象配置GET请求,指定服务器URL为 http://192.168.31.45:3000/top/song?type=7 ,感觉就像是在用古董手机进行日常通讯。3.异步处理: 设置回调函数,onreadystatechange监听XMLHttpRequest对象状态的变化,就像是你此刻守在手机旁等待消息的回复,确保在请求完成且成功时进行处理。状态码4表示通信完毕,200是服务器说“好的,拿走不谢”。4.处理服务器响应: 最后解析从服务器返回的JSON数据,然后遍历歌曲信息,创建列表项并将获取到的信息内容添加到页面中。注意: 由于可能涉及跨域请求,所以我们需要确保服务器正确配置CORS,以允许跨域资源的访问。二、jQuery的$.ajax虽然我们上面用XHR完成了要求,但是这些代码写起来也太痛苦了。欸,这个时候我们就需要提到jQuery的的$.ajax了,它就像是轻量化的XHR,大大改善了代码的可读性。const btn = document.getElementById('btn'); btn.addEventListener('click', () => { $.ajax({ url: 'http://example.com/api/data', method: 'GET', dataType: 'json', success: function (res) { console.log(res); }, error: function (xhr, status, error) { console.error('Error:', xhr, status, error); } }); });解释: 我们使用$.ajax时,需要配置相应的参数:url: 设置请求的URL,这里我们要访问的URL是example.com/api/datamethod: 指定HTTP请求方法,GET ——表示发送一个获取数据的请求。dataType: 指定期望从服务器接收的数据类型,我们这里是json,希望服务器返回JSON格式的数据。success: 定义请求成功时的回调函数。当请求成功完成时,服务器的响应将传递给这个函数,并且我们在函数内部可以处理这个响应。error: 定义请求失败时的回调函数。如果请求无法完成,或者服务器返回一个错误状态码,这个函数将被调用,你可以在函数内部处理错误信息。我们可以看到当我们使用了jQuery库大大简化了AJAX请求的过程,但是在此之前不要忘记引入我们jQuery库哦~三、Fetch API讲了两种以实现AJAX的方式,那么现代的Fetch API就像是AJAX的新晋小生,简单直接,不需要太多花里胡哨,请看下列代码。const btn = document.getElementById('btn'); btn.addEventListener('click', () => { fetch('http://example.com/api/data') .then(data => data.json()) .then(res => { console.log(res); }) .catch(error => { console.error('Error:', error); }); });解释:在fetch api这个方法里面我们同样需要配置参数,但不多,简单粗暴。fetch(url): 使用Fetch API发起GET请求到指定的URL。 Fetch API就是一群新潮的年轻人,你不是异步吗,那我就用Promise搞定一切,拒绝冗杂和花里胡哨,像是在拍独立电影一样。.then(data => data.json()): 使用.then()处理Promise,将响应体解析为JSON格式。Fetch API返回的是一个Promise,其中data是表示响应的Response对象。.then(res => { console.log(res); }): 处理JSON解析后的数据。在这个例子中,将解析后的数据打印到控制台。这些.then()的链式调用就像是一场流畅的对白,如果期间出现了小插曲,不行就.catch()。.catch(error => { console.error('Error:', error); }): 处理任何可能的错误。如果请求失败或JSON解析出错,将捕获到的错误打印到控制台。看完这段代码,不知你是否有种赏心悦目,神清气爽地感觉。相较于传统的XHR方式,我们通过使用现代的Promise和Fetch API,更换成了更简洁和方便的方式来处理异步网络请求。结语掌握这三招AJAX神功,你就像是一位不羁的武林少年,可以在网页的江湖里畅快自如地舞动。不同的招式适合不同的场景,所以,别拘泥于一招,放开心扉,开始你的AJAX江湖之旅吧!少年,愿你的代码逍遥自在,BUG永远躲不过你的剑!

0
0
0
浏览量2061