HTTP(CS-Notes) 太过爱你忘了你带给我的痛 2021-11-11 13:08 223阅读 0赞 # 1 基础概念 # ## 1.1 URI ## URI 包含 **URL** 和 **URN**。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzg0NDFiMmM0LWRjYTctNGQ2Yi04ZWZiLWYyMmVmY2NhZjMzMS5wbmc][] ## 1.2 请求和响应报文 ## ### 1. 请求报文 ### ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL0hUVFBfUmVxdWVzdE1lc3NhZ2VFeGFtcGxlLnBuZw][] ### 2. 响应报文 ### ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL0hUVFBfUmVzcG9uc2VNZXNzYWdlRXhhbXBsZS5wbmc][] -------------------- # 2 HTTP 方法 # 客户端发送的 **请求报文** 第一行为请求行,包含了方法字段。 ## GET ## > 获取资源 当前网络请求中,绝大部分使用的是 GET 方法。 ## HEAD ## > 获取报文首部 和 GET 方法类似,但是不返回 报文实体主体部分。 主要用于确认 URL 的有效性以及资源更新的日期时间等。 ## POST ## > 传输实体主体 POST 主要用来传输数据,而 GET 主要用来获取资源。 更多 POST 与 GET 的比较请见第九章。 ## PUT ## > 上传文件 由于**自身不带验证机制**,任何人都可以上传文件,因此存在安全性问题。**一般不使用该方法**。 PUT /new.html HTTP/1.1 Host: example.com Content-type: text/html Content-length: 16 <p>New File</p> ## PATCH ## > 对资源进行部分修改 PUT 也可以用于修改资源,但是只能完全替代原始资源;**PATCH 允许部分修改**。 PATCH /file.txt HTTP/1.1 Host: www.example.com Content-Type: application/example If-Match: "e0023aa4e" Content-Length: 100 [description of changes] ## DELETE ## > 删除文件 与 PUT 功能相反,并且同样**不带验证机制**。 DELETE /file.html HTTP/1.1 ## OPTIONS ## > 查询支持的方法 查询 指定的 URL 能够支持的方法。 会返回**`Allow: GET, POST, HEAD, OPTIONS`**这样的内容。 ## CONNECT ## > 要求在与代理服务器通信时建立隧道 使用 **SSL**(**Secure Sockets Layer**,**安全套接层**)和 **TLS**(**Transport Layer Security**,**传输层安全**)**协议** 把通信内容加密后,经网络隧道传输。 CONNECT www.example.com:443 HTTP/1.1 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL2RjMDBmNzBlLWM1YzgtNGQyMC1iYWYxLTJkNzAwMTRhOTdlMy5qcGc][] ## TRACE ## > 追踪路径 服务器 会将通信路径 返回给客户端。 发送请求时,在 Max-Forwards 首部字段中填入数值,每经过一个服务器就会减 1,当数值为 0 时就停止传输。 **通常不会使用 TRACE**,并且它容易受到 **XST 攻击**(**Cross-Site Tracing**,**跨站追踪**)。 -------------------- # 3 HTTP 状态码 # 服务器返回的 **响应报文** 中第一行为 状态行,包含了状态码以及原因短语,用来 告知 客户端 请求的结果。 <table> <thead> <tr> <th>状态码</th> <th>类别</th> <th>含义</th> </tr> </thead> <tbody> <tr> <td>1XX</td> <td>Informational(信息性状态码)</td> <td>接收的请求<strong>正在处理</strong></td> </tr> <tr> <td>2XX</td> <td>Success(成功状态码)</td> <td>请求正常<strong>处理完毕</strong></td> </tr> <tr> <td>3XX</td> <td>Redirection(重定向状态码)</td> <td><strong>需要进行附加操作</strong>以完成请求</td> </tr> <tr> <td>4XX</td> <td>Client Error(客户端错误状态码)</td> <td>服务器<strong>无法处理请求</strong></td> </tr> <tr> <td>5XX</td> <td>Server Error(服务器错误状态码)</td> <td>服务器<strong>处理请求出错</strong></td> </tr> </tbody> </table> ## 1XX 信息 ## * **100 Continue** :表明到目前为止都很正常,客户端可以继续发送请求或者忽略这个响应。 ## 2XX 成功 ## * **200 OK** * **204 No Content** :请求已经成功处理,但是 返回的响应报文不包含实体的主体部分。一般在只需要从客户端往服务器发送信息,而不需要返回数据时使用。 * **206 Partial Content** :表示客户端进行了范围请求,响应报文 包含由 Content-Range 指定范围的实体内容。 ## 3XX 重定向 ## * **301 Moved Permanently** :永久性重定向 * **302 Found** :临时性重定向 * **303 See Other** :和 302 有着相同的功能,但是 **303 明确要求** **客户端**应该采用 GET 方法获取资源。 * 注:虽然 HTTP 协议规定 301、302 状态下 重定向时**不允许**把 POST 方法 改成 GET 方法,**但是**大多数浏览器都会在 301、302 和 303 状态下的重定向把 POST 方法改成 GET 方法。 * **304 Not Modified** :如果请求报文首部包含一些条件,例如:If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since。如果不满足条件,则服务器会返回 304 状态码。 * **307 Temporary Redirect** :临时重定向,与 302 的含义类似,但是 **307 要求** **浏览器**不会把重定向请求的 POST 方法改成 GET 方法。 ## 4XX 客户端错误 ## * **400 Bad Request** :请求报文中存在语法错误。 * **401 Unauthorized** :该状态码表示 发送的请求 需要有认证信息(BASIC 认证、DIGEST 认证)。如果之前已进行过一次请求,则表示用户认证失败。 * **403 Forbidden** :请求被拒绝。 * **404 Not Found** ## 5XX 服务器错误 ## * **500 Internal Server Error** :服务器正在执行请求时 发生错误。 * **503 Service Unavailable** :服务器暂时处于超负载 或 正在进行停机维护,现在无法处理请求。 -------------------- # HTTP 首部 # 有 4 种类型的首部字段:通用首部字段、请求首部字段、响应首部字段和实体首部字段。 各种首部字段及其含义如下(不需要全记,仅供查阅): ## 通用首部字段 ## <table> <thead> <tr> <th>首部字段名</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>Cache-Control</td> <td>控制缓存的行为</td> </tr> <tr> <td>Connection</td> <td>控制不再转发给代理的首部字段、管理持久连接</td> </tr> <tr> <td>Date</td> <td>创建报文的日期时间</td> </tr> <tr> <td>Pragma</td> <td>报文指令</td> </tr> <tr> <td>Trailer</td> <td>报文末端的首部一览</td> </tr> <tr> <td>Transfer-Encoding</td> <td>指定报文主体的传输编码方式</td> </tr> <tr> <td>Upgrade</td> <td>升级为其他协议</td> </tr> <tr> <td>Via</td> <td>代理服务器的相关信息</td> </tr> <tr> <td>Warning</td> <td>错误通知</td> </tr> </tbody> </table> ## 请求首部字段 ## <table> <thead> <tr> <th>首部字段名</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>Accept</td> <td>用户代理可处理的媒体类型</td> </tr> <tr> <td>Accept-Charset</td> <td>优先的字符集</td> </tr> <tr> <td>Accept-Encoding</td> <td>优先的内容编码</td> </tr> <tr> <td>Accept-Language</td> <td>优先的语言(自然语言)</td> </tr> <tr> <td>Authorization</td> <td>Web 认证信息</td> </tr> <tr> <td>Expect</td> <td>期待服务器的特定行为</td> </tr> <tr> <td>From</td> <td>用户的电子邮箱地址</td> </tr> <tr> <td>Host</td> <td>请求资源所在服务器</td> </tr> <tr> <td>If-Match</td> <td>比较实体标记(ETag)</td> </tr> <tr> <td>If-Modified-Since</td> <td>比较资源的更新时间</td> </tr> <tr> <td>If-None-Match</td> <td>比较实体标记(与 If-Match 相反)</td> </tr> <tr> <td>If-Range</td> <td>资源未更新时发送实体 Byte 的范围请求</td> </tr> <tr> <td>If-Unmodified-Since</td> <td>比较资源的更新时间(与 If-Modified-Since 相反)</td> </tr> <tr> <td>Max-Forwards</td> <td>最大传输逐跳数</td> </tr> <tr> <td>Proxy-Authorization</td> <td>代理服务器要求客户端的认证信息</td> </tr> <tr> <td>Range</td> <td>实体的字节范围请求</td> </tr> <tr> <td>Referer</td> <td>对请求中 URI 的原始获取方</td> </tr> <tr> <td>TE</td> <td>传输编码的优先级</td> </tr> <tr> <td>User-Agent</td> <td>HTTP 客户端程序的信息</td> </tr> </tbody> </table> ## 响应首部字段 ## <table> <thead> <tr> <th>首部字段名</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>Accept-Ranges</td> <td>是否接受字节范围请求</td> </tr> <tr> <td>Age</td> <td>推算资源创建经过时间</td> </tr> <tr> <td>ETag</td> <td>资源的匹配信息</td> </tr> <tr> <td>Location</td> <td>令客户端重定向至指定 URI</td> </tr> <tr> <td>Proxy-Authenticate</td> <td>代理服务器对客户端的认证信息</td> </tr> <tr> <td>Retry-After</td> <td>对再次发起请求的时机要求</td> </tr> <tr> <td>Server</td> <td>HTTP 服务器的安装信息</td> </tr> <tr> <td>Vary</td> <td>代理服务器缓存的管理信息</td> </tr> <tr> <td>WWW-Authenticate</td> <td>服务器对客户端的认证信息</td> </tr> </tbody> </table> ## 实体首部字段 ## <table> <thead> <tr> <th>首部字段名</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>Allow</td> <td>资源可支持的 HTTP 方法</td> </tr> <tr> <td>Content-Encoding</td> <td>实体主体适用的编码方式</td> </tr> <tr> <td>Content-Language</td> <td>实体主体的自然语言</td> </tr> <tr> <td>Content-Length</td> <td>实体主体的大小</td> </tr> <tr> <td>Content-Location</td> <td>替代对应资源的 URI</td> </tr> <tr> <td>Content-MD5</td> <td>实体主体的报文摘要</td> </tr> <tr> <td>Content-Range</td> <td>实体主体的位置范围</td> </tr> <tr> <td>Content-Type</td> <td>实体主体的媒体类型</td> </tr> <tr> <td>Expires</td> <td>实体主体过期的日期时间</td> </tr> <tr> <td>Last-Modified</td> <td>资源的最后修改日期时间</td> </tr> </tbody> </table> -------------------- # 5 具体应用 # ## 5.1 连接管理 ## ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL0hUVFAxX3hfQ29ubmVjdGlvbnMucG5n][] ### 1. 短连接与长连接 ### 当浏览器访问一个包含多张图片的 HTML 页面时,除了请求访问的 HTML 页面资源,还会请求图片资源。如果每进行一次 HTTP 通信就要 新建一个 TCP 连接,那么开销会很大。 **长连接****只需要建立一次 TCP 连接,**就能进行**多次 HTTP 通信**。 * 从 HTTP/1.1 开始 **默认是长连接**的,如果要断开连接,需要由客户端 或者 服务器端提出断开,使用**`Connection : close`**; * 在 HTTP/1.1 之前默认是短连接的,如果需要使用长连接,则使用**`Connection : Keep-Alive`**。 ### 2. 流水线 ### **默认情况下**,HTTP 请求是按顺序发出的,**下一个请求** **只有在当前请求 收到响应之后** **才会被发出**。由于受到网络延迟和带宽的限制,在下一个请求 被发送到服务器之前,可能需要等待很长时间(因为要等待当前请求的响应报文发回来,下一个请求才能发送。报文在网络中一来一回要花好久的时间)。 **流水线**是 在**同一条长连接**上 连续发出请求,而**不用等待 响应返回**,这样可以减少延迟。 -------------------- ## 5.2 Cookie ## HTTP 协议是**无状态**的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。**HTTP/1.1** 引入 **Cookie** 来保存状态信息。 **Cookie** 是**服务器** 发送到 **用户浏览器**,并**保存在本地的**一小块数据。它会在 **浏览器**之后 向**同一服务器**再次发起请求时 **被携带上**,用于告知服务端 两个请求 是否来自**同一浏览器**。由于之后**每次请求 都会需要携带 Cookie 数据**,因此会带来额外的性能开销(尤其是在移动环境下)。 Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据 存储到本地,如使用 **Web storage API**(本地存储和会话存储)或 IndexedDB。 ### 1. 用途 ### * 会话状态管理(如用户登录状态、购物车、游戏分数 或其它需要记录的信息) * 个性化设置(如用户自定义设置、主题等) * 浏览器行为跟踪(如跟踪分析用户行为等) ### 2. 创建过程 ### **服务器发送的响应报文 包含 Set-Cookie 首部字段**。**客户端** 得到响应报文后,把 Cookie 内容保存到浏览器中。 > HTTP/1.0 200 OK > Content-type: text/html > Set-Cookie: yummy_cookie=choco > Set-Cookie: tasty_cookie=strawberry > > [page content] **客户端** 之后对**同一个服务器**发送请求时,会**从浏览器中**取出 Cookie 信息 ,并通过 Cookie 请求首部字段 发送给**服务器**。 > GET /sample_page.html HTTP/1.1 > Host: www.example.org > Cookie: yummy_cookie=choco; tasty_cookie=strawberry ### 3. 分类 ### * **会话期 Cookie**:浏览器关闭之后它会被自动删除,也就是说它**仅在会话期内有效**。 * **持久性 Cookie**:指定 过期时间(Expires)或有效期(max-age)之后,就成为了持久性的 Cookie。 > Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; ### 4. 作用域 ### **Domain 标识**指定了 哪些主机可以接受 Cookie。如果不指定,默认为当前文档的主机(不包含子域名)。如果指定了 Domain,则一般包含子域名。例如,如果设置 Domain=mozilla.org,**则** Cookie **也包含在 子域名 中**(如 developer.mozilla.org)。 **Path 标识** 指定了 主机下的哪些路径 可以接受 Cookie(该 URL 路径 必须存在于 请求 URL 中)。以字符 %x2F ("/") 作为路径分隔符,子路径也会被匹配。例如,设置 Path=/docs,则以下地址都会匹配: * /docs * /docs/Web/ * /docs/Web/HTTP ### 5. JavaScript ### 浏览器通过 **`document.cookie` 属性**可创建新的 Cookie,也可通过该属性访问 非 HttpOnly 标记的 Cookie。 document.cookie = "yummy_cookie=choco"; document.cookie = "tasty_cookie=strawberry"; console.log(document.cookie); ### 6. HttpOnly ### **标记为 HttpOnly 的 Cookie** 不能被 JavaScript 脚本调用。**跨站脚本攻击 (XSS)** 常常使用 JavaScript 的 `document.cookie` API 窃取用户的 Cookie 信息。因此**使用 HttpOnly 标记,**可以在一定程度上避免 XSS 攻击。 ### 7. Secure ### **标记为 Secure 的 Cookie** 只能通过 被**HTTPS 协议**加密过的请求 发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。 ### 8. Session ### 除了可以将用户信息 通过 **Cookie** 存储在用户浏览器中,也可以利用 **Session** 存储在服务器端,存储在服务器端的信息更加安全。 Session 可以存储在服务器上的文件、数据库或者内存中。也可以将 **Session** 存储在 Redis 这种内存型数据库中,效率会更高。 使用 Session 维护 用户登录状态的过程如下: * 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中; * 服务器验证该用户名和密码,如果正确则把**用户信息** 存储到 Redis 中,它在 Redis 中的 **Key** 称为 **Session ID**; * 服务器返回的响应报文的 **Set-Cookie 首部字段**包含了这个 Session ID。客户端收到响应报文之后,将该 Cookie 值 存入浏览器中; * 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,**从 Redis 中取出用户信息**,继续之前的业务操作。 应该注意 Session ID 的安全性问题,不能让它被恶意攻击者轻易获取,那么就不能产生一个容易被猜到的 Session ID 值。此外,还需要经常重新生成 Session ID。在对安全性要求极高的场景下,例如转账等操作,除了使用 Session 管理用户状态之外,还需要对用户进行重新验证,比如重新输入密码,或者使用短信验证码等方式。 ### 9. 浏览器禁用 Cookie ### 此时无法使用 Cookie 来保存用户信息,只能使用 Session。除此之外,不能再将 Session ID 存放到 Cookie 中,而是使用 URL 重写技术,将 Session ID 作为 URL 的参数进行传递。 ### 10. Cookie 与 Session 选择 ### * Cookie 只能存储 ASCII 码字符串,而 Session 则可以存储任何类型的数据,因此在考虑数据复杂性时首选 Session; * Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密; * 对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的,因此不建议将所有的用户信息 都存储到 Session 中。 -------------------- ## 5.3 缓存 ## ### 1. 优点 ### * 缓解服务器压力; * 降低 客户端 获取资源的延迟:缓存通常位于内存中,读取缓存的速度更快。并且缓存服务器在地理位置上也有可能比源服务器来得近,例如浏览器缓存。 ### 2. 实现方法 ### * 让代理服务器进行缓存; * 让客户端浏览器进行缓存。 ### 3. Cache-Control ### **HTTP/1.1** 通过 **Cache-Control 首部字段**来控制缓存。 **3.1 禁止进行缓存** **no-store 指令**规定:不能对请求或响应的任何一部分进行缓存。 > Cache-Control: no-store **3.2 强制确认缓存** **no-cache 指令**规定:缓存服务器 需要 先向 源服务器 验证 缓存资源的有效性,只有当缓存资源有效时 缓存服务器才能使用该缓存对客户端的请求进行响应。 > Cache-Control: no-cache **3.3 私有缓存和公共缓存** **private 指令**规定了将资源作为私有缓存,只能被单独用户使用,一般存储在用户浏览器中。 > Cache-Control: private **public 指令**规定了将资源作为公共缓存,可以被多个用户使用,一般存储在代理服务器中。 > Cache-Control: public **3.4 缓存过期机制** **max-age 指令** 出现在**请求报文**,并且缓存资源的缓存时间小于该指令指定的时间,那么就能接受该缓存。 **max-age 指令** 出现在**响应报文**,表示 缓存资源 在缓存服务器中保存的时间。 > Cache-Control: max-age=31536000 **Expires 首部字段** 也可以用于告知缓存服务器 **该资源**什么时候会过期。 > Expires: Wed, 04 Jul 2012 08:26:05 GMT * 在 **HTTP/1.1** 中,会**优先处理 max-age 指令**; * 在 HTTP/1.0 中,max-age 指令 **会被忽略掉**。 ### 4. 缓存验证 ### 需要先了解 **ETag 首部字段**的含义,它是**资源的唯一标识**。 **URL 不能唯一表示资源**,例如 `http://www.google.com/` 有中文和英文两个资源,只有 ETag 才能对这两个资源进行唯一标识。 > ETag: "82e22293907ce725faf67773957acd12" 可以将缓存资源的 ETag 值放入 **If-None-Match 首部**。**服务器**收到该请求后,**判断**缓存资源的 ETag 值 **和** 资源的最新 ETag 值**是否一致**。如果一致 则表示缓存资源有效,返回 **304 Not Modified**。 > If-None-Match: "82e22293907ce725faf67773957acd12" **Last-Modified 首部字段** 也可以用于缓存验证,它包含在源服务器发送的响应报文中,指示 源服务器对资源的**最后修改时间**。但是它是一种**弱校验器**,因为**只能精确到一秒**,所以它通常作为 ETag 的备用方案。如果响应首部字段里含有这个信息,**客户端**可以**在后续的请求中带上 If-Modified-Since** 来验证缓存。服务器只在所请求的资源 在给定的日期时间之后 对内容进行过修改的情况下,才会将资源返回,状态码为 **200 OK**。如果请求的资源从那时起 未经修改,那么返回一个不带有实体主体的 304 Not Modified 响应报文。 > Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT > If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT -------------------- ## 5.4 内容协商 ## 通过内容协商,返回最合适的内容。例如根据浏览器的默认语言选择,返回中文界面还是英文界面。 ### 1. 类型 ### **1.1 服务端驱动型** **客户端**设置特定的 HTTP 首部字段,例如 Accept、Accept-Charset、Accept-Encoding、Accept-Language。**服务器**根据这些字段,返回特定的资源。 它存在以下问题: * **服务器**很难知道客户端浏览器的全部信息; * 客户端提供的信息相当冗长(HTTP/2 协议的首部压缩机制缓解了这个问题),并且存在隐私风险(HTTP 指纹识别技术); * 给定的资源 需要返回 不同的展现形式,共享缓存的效率会降低,而服务器端的实现 会越来越复杂。 **1.2 代理驱动型** 服务器返回 **300 Multiple Choices** 或者 **406 Not Acceptable**,客户端从中选出最合适的那个资源。 ### 2. Vary ### > Vary: Accept-Language 在使用内容协商的情况下,只有当缓存服务器中的缓存满足内容协商条件时,才能使用该缓存,否则应该向源服务器 请求该资源。 例如,一个**客户端**发送了一个包含 Accept-Language 首部字段的请求之后,源服务器返回的响应包含 `Vary: Accept-Language` 内容,**缓存服务器**对这个响应进行缓存之后,在**客户端**下一次访问同一个 URL 资源,并且 Accept-Language 与缓存中的对应的值相同时,才会返回该缓存。 -------------------- ## 5.5 内容编码 ## 内容编码 将实体主体进行压缩,从而减少传输的数据量。 常用的内容编码有:**gzip**、**compress**、**deflate**、**identity**。 **浏览器**发送 Accept-Encoding 首部,其中包含有它所支持的压缩算法,以及各自的优先级。**服务器**则从中选择一种,使用该算法对响应的消息主体进行压缩;并且服务器发送 **Content-Encoding 首部**来告知浏览器,它选择了哪一种算法。由于该内容协商过程是基于编码类型来选择资源的展现形式的,响应报文的 Vary 首部字段**至少要包含 Content-Encoding**。 -------------------- ## 5.6 范围请求 ## 如果网络出现中断,**服务器**只发送了一部分数据,范围请求可以使得 **客户端** **只请求** 服务器未发送的那部分数据,从而避免**服务器**重新发送所有数据。 ### 1. Range ### 在请求报文中添加 Range 首部字段指定请求的范围。 > GET /z4d4kWk.jpg HTTP/1.1 > Host: i.imgur.com > Range: bytes=0-1023 请求成功的话,服务器返回的响应包含 **206 Partial Content 状态码**。 > HTTP/1.1 206 Partial Content > Content-Range: bytes 0-1023/146515 > Content-Length: 1024 > ... > (binary content) ### 2. Accept-Ranges ### 响应首部字段 Accept-Ranges 用于告知客户端:是否能处理范围请求,可以处理使用 bytes,否则使用 none。 > Accept-Ranges: bytes ### 3. 响应状态码 ### * 在请求成功的情况下,**服务器**会返回 **206 Partial Content** 状态码。 * 在请求的范围越界的情况下,**服务器**会返回 **416 Requested Range Not Satisfiable** 状态码。 * 在不支持范围请求的情况下,**服务器**会返回 **200 OK** 状态码。 -------------------- ## 5.7 分块传输编码 ## Chunked Transfer Encoding,可以把数据分割成多块,**让浏览器 逐步显示页面**。 -------------------- ### 5.8 多部分对象集合 ### 一份报文主体内可含有多种类型的实体 同时发送。每个部分之间 用 **boundary 字段**定义的分隔符 进行分隔。每个部分 都可以有首部字段。 例如,**上传 多个表单时,**可以使用如下方式: > Content-Type: multipart/form-data; boundary=AaB03x > > --AaB03x > Content-Disposition: form-data; name="submit-name" > > Larry > --AaB03x > Content-Disposition: form-data; name="files"; filename="file1.txt" > Content-Type: text/plain > > ... contents of file1.txt ... > --AaB03x-- -------------------- ## 5.9 虚拟主机 ## **HTTP/1.1** 使用虚拟主机技术,使得**一台服务器 拥有 多个域名**,并且在逻辑上可以看成多个服务器。 -------------------- ## 5.10 通信数据转发 ## ### 1. 代理 ### **代理服务器** 接受 客户端的请求,并且转发给其它服务器。 > **使用代理的主要目的是:** > > * **缓存** > * **负载均衡** > * **网络访问控制** > * **访问日志记录** 代理服务器分为正向代理和反向代理两种: * 用户察觉得到正向代理的存在。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL2EzMTRiYjc5LTViMTgtNGU2My1hOTc2LTM0NDhiZmZhNmYxYi5wbmc][] * 而反向代理一般位于内部网络中,用户察觉不到。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzJkMDlhODQ3LWI4NTQtNDM5Yy05MTk4LWIyOWM2NTgxMDk0NC5wbmc][] ### 2. 网关 ### 与代理服务器不同的是,**网关服务器** 会将 **HTTP** 转化为**其它协议**进行通信,从而请求 **其它 非 HTTP 服务器的服务**。 ### 3. 隧道 ### 使用 **SSL** 等加密手段,在客户端和服务器之间建立一条安全的通信线路。 -------------------- -------------------- # 6 HTTPS # > **HTTP** 有以下安全性问题: > > * 使用明文进行通信,内容可能会被窃听; > * 不验证通信方的身份,通信方的身份有可能遭遇伪装; > * 无法证明报文的完整性,报文有可能遭篡改。 **HTTPS 并不是新协议**,而是让 **HTTP** 先和 **SSL**(**Secure Sockets Layer**)通信,再由 **SSL** 和 **TCP** 通信,也就是说 **HTTPS 使用了隧道**进行通信。 > 通过使用 **SSL**,**HTTPS**具有了**加密**(防窃听)、**认证**(防伪装)和**完整性保护**(防篡改)。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL3NzbC1vZmZsb2FkaW5nLmpwZw][] ## 6.1 加密 ## ### 1. 对称密钥加密 ### 对称密钥加密(**Symmetric-Key Encryption**),加密和解密**使用同一密钥**。 * 优点:运算速度快; * 缺点:无法安全地 将密钥传输给通信方。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzdmZmZhNGI4LWIzNmQtNDcxZi1hZDBjLWE4OGVlNzYzYmI3Ni5wbmc][] ### 2.非对称密钥加密 ### 非对称密钥加密,又称**公开密钥加密**(**Public-Key Encryption**),加密和解密**使用不同的密钥**。 公开密钥所有人都可以获得,**通信发送方**获得接收方的公开密钥之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。 > **收信人** 告诉所有发信人。我要的信,应该被什么算法加密。(相当于每个发给**收件人**的信件,都用接收方提供的锁锁起来。发信者们,只有同样的锁,没有钥匙。即使报文被第三方截获了,但第三方没有钥匙,也开不了锁)。 > > **收信人** 收到 被算法加密信件时,会使用自己的私钥来从 被公钥加密的信件中解读内容。(**收信人** 拿只有自己知道的钥匙解锁)。 非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥无法被其他人获取,因此**通信发送方**使用其私有密钥进行签名,**通信接收方**使用发送方的公开密钥对签名进行解密,就能判断这个签名是否正确。 * 优点:可以更安全地将公开密钥传输给通信发送方; * 缺点:运算速度慢。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzM5Y2NiMjk5LWVlOTktNGRkMS1iOGI0LTJmOWVjOTQ5NWNiNC5wbmc][] ### 3. HTTPS 采用的加密方式 ### HTTPS 采用**混合的加密机制**,将非对称密钥加密 用于传输 对称密钥,来保证传输过程的安全性。之后使用对称密钥加密进行通信来保证通信过程的效率。(下图中的 **Session Key** 就是**对称密钥**) > 使用 非对称密钥加密 ,来保证 对称密钥传输过程的安全性。 > > 使用对称密钥加密进行通信,来保证 通信过程的效率。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL0hvdy1IVFRQUy1Xb3Jrcy5wbmc][] ## 6.2 认证 ## 通过使用 **证书** ,来对通信方进行认证。 **数字证书认证机构**(CA,**Certificate Authority**)是客户端与服务器双方都可信赖的第三方机构。 服务器的运营人员 向 CA 提出 公开密钥的申请。CA 在判明 提出申请者的身份之后,会**对 已申请的公开密钥 做数字签名**,然后分配这个已签名的公开密钥;并将该公开密钥 放入公开密钥证书后,将密钥和证书绑定在一起。 进行 **HTTPS 通信**时,**服务器**会把**证书** 发送给**客户端**。客户端取得证书中的公开密钥之后,先使用**数字签名**进行验证,如果验证通过,就可以开始通信了。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzIwMTctMDYtMTEtY2EucG5n][] ## 6.3 完整性保护 ## **SSL** 提供报文摘要功能,来进行完整性保护。 **HTTP** 也提供了 MD5 报文摘要功能,但不是安全的。例如报文内容被篡改之后,同时重新计算 MD5 的值,**通信接收方**是无法意识到发生了篡改。 HTTPS 的报文摘要功能之所以安全,是因为它结合了**加密**和**认证**这两个操作。试想一下,加密之后的报文,遭到篡改之后,也很难重新计算报文摘要,因为无法轻易获取明文。 ## 6.4 HTTPS 的缺点 ## * 因为需要进行加密解密等过程,因此**速度会更慢**; * 需要支付**证书授权的高额费用**。 -------------------- -------------------- # 7 HTTP/2.0 # ## 7.1 HTTP/1.x 缺陷 ## HTTP/1.x 实现简单是**以牺牲性能为代价**的: * **客户端**需要使用多个连接,才能实现并发和缩短延迟; * 不会压缩请求和响应首部,从而导致不必要的网络流量; * 不支持有效的资源优先级,致使底层 TCP 连接的利用率低下。 ## 7.2 二进制分帧层 ## **HTTP/2.0** 将**报文**分成 **HEADERS 帧**和 **DATA 帧**,它们都是**二进制格式**的。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzg2ZTZhOTFkLWEyODUtNDQ3YS05MzQ1LWM1NDg0YjhkMGM0Ny5wbmc][] **在通信过程中,只会有一个 TCP 连接存在**,它承载了**任意数量的双向数据流(Stream)**。 * 一个**数据流(Stream)**都有一个唯一标识符和可选的优先级信息,用于承载双向信息。 * **消息(Message)**是 与逻辑请求或响应对应的 **完整的一系列帧**。 * **帧(Frame)**是最小的通信单位,来自不同数据流的帧**可以交错发送**,**然后再根据**每个帧头的数据流标识符**重新组装**。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL2FmMTk4ZGExLTI0ODAtNDA0My1iMDdmLWEzYjkxYTg4YjgxNS5wbmc][] ## 7.3 服务端推送 ## **HTTP/2.0** 在客户端请求一个资源时,**服务器**会把**相关的资源**一起发送给客户端,**客户端**就不需要再次发起请求了。例如客户端请求 **page.html** 页面,服务端就把 **script.js** 和 **style.css** 等与之相关的资源 一起发给客户端。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL2UzZjE2NTdjLTgwZmMtNGRmYS05NjQzLWJmNTFhYmQyMDFjNi5wbmc][] ## 7.4 首部压缩 ## **HTTP/1.1 的首部** 带有大量信息,而且每次都要重复发送。 **HTTP/2.0** 要求客户端和服务器 **同时维护和更新一个包含之前见过的首部字段表**,从而避免了重复传输。 不仅如此,HTTP/2.0 也使用 **Huffman 编码,**对首部字段进行压缩。 ![aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL191NEUwQl91OEY3RC5wbmc][] -------------------- # 8 HTTP/1.1 新特性 # 详细内容请见上文 * 默认是**长连接** * 支持**流水线** * 支持**同时打开多个 TCP 连接** * 支持**虚拟主机** * 新增**状态码 100** * 支持**分块传输编码** * 新增**缓存处理指令 max-age** # 9 GET 和 POST 比较 # ## 9.1 作用 ## GET 用于获取资源,而 POST 用于传输实体主体。 ## 9.2 参数 ## GET 和 POST 的请求都能使用额外的参数,但是 **GET 的参数**是以查询字符串出现在 URL 中,而 **POST 的参数**存储在实体主体中。不能因为 POST 参数存储在实体主体中就认为它的安全性更高,因为照样可以通过一些抓包工具(Fiddler)查看。 因为 **URL 只支持 ASCII 码**,因此 **GET 的参数中**如果存在中文等字符 就需要先进行编码。例如 **`中文`**会转换为 **`%E4%B8%AD%E6%96%87`**,而**空格**会转换为**`%20`**。 POST 参数支持标准字符集。 GET /test/demo_form.asp?name1=value1&name2=value2 HTTP/1.1 POST /test/demo_form.asp HTTP/1.1 Host: w3schools.com name1=value1&name2=value2 ## 9.3 安全 ## **安全的 HTTP 方法** 不会改变服务器状态,也就是说它只是可读的。 GET 方法是安全的,而 POST 却不是,因为 POST 的目的是传送实体主体内容,这个内容可能是用户上传的表单数据,上传成功之后,服务器可能把这个数据存储到数据库中,因此状态也就发生了改变。 **安全的方法**除了 **GET** 之外还有:**HEAD**、**OPTIONS**。 **不安全的方法**除了 **POST** 之外还有 **PUT**、**DELETE**。 ## 9.4 幂等性 ## 幂等的 HTTP 方法,**同样的请求**被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。换句话说就是,幂等方法不应该具有副作用(统计用途除外)。 所有的安全方法也都是幂等的。 在正确实现的条件下,**GET**,**HEAD**,**PUT** 和 **DELETE** 等方法都是**幂等的**,而 POST 方法不是。 **GET** /pageX **HTTP/1.1** 是幂等的,**连续调用多次,客户端接收到的结果都是一样的**: GET /pageX HTTP/1.1 GET /pageX HTTP/1.1 GET /pageX HTTP/1.1 GET /pageX HTTP/1.1 **POST** /add\_row **HTTP/1.1** 不是幂等的,**如果调用多次,就会增加多行记录**: POST /add_row HTTP/1.1 -> Adds a 1nd row POST /add_row HTTP/1.1 -> Adds a 2nd row POST /add_row HTTP/1.1 -> Adds a 3rd row **DELETE** /idX/delete **HTTP/1.1** 是幂等的,即使不同的请求接收到的状态码不一样: DELETE /idX/delete HTTP/1.1 -> Returns 200 if idX exists DELETE /idX/delete HTTP/1.1 -> Returns 404 as it just got deleted DELETE /idX/delete HTTP/1.1 -> Returns 404 ## 9.5 可缓存 ## 如果要 **对响应 进行缓存**,需要满足以下条件: * 请求报文的 HTTP 方法本身 是可缓存的,包括 **GET** 和 **HEAD**,但是 **PUT** 和 **DELETE 不可缓存**,**POST** 在多数情况下**不可缓存的**。 * 响应报文的状态码是可缓存的,包括:200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501。 * 响应报文的 Cache-Control 首部字段 没有指定 不进行缓存。 ## XMLHttpRequest ## 为了阐述 POST 和 GET 的另一个区别,需要先了解 XMLHttpRequest: > **XMLHttpRequest** 是一个 API,它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个**通过 URL 来获取数据**的简单方式,**并且不会使整个页面刷新**。这使得网页只更新一部分页面,而不会打扰到用户。XMLHttpRequest 在 **AJAX** 中被大量使用。 * 在使用 XMLHttpRequest 的 **POST 方法**时,**浏览器**会**先发送 Header 再发送 Data**。但并不是所有浏览器会这么做,例如火狐就不会。 * 而 **GET 方法 Header 和 Data 会一起发送。** -------------------- # 参考资料 # * 上野宣. 图解 HTTP\[M\]. 人民邮电出版社, 2014. * [MDN : HTTP][MDN _ HTTP] * [HTTP/2 简介][HTTP_2] * [htmlspecialchars][] * [Difference between file URI and URL in java][] * [How to Fix SQL Injection Using Java PreparedStatement & CallableStatement][How to Fix SQL Injection Using Java PreparedStatement _ CallableStatement] * [浅谈 HTTP 中 Get 与 Post 的区别][HTTP _ Get _ Post] * [Are http:// and www really necessary?][Are http_ and www really necessary] * [HTTP (HyperText Transfer Protocol)][HTTP _HyperText Transfer Protocol] * [Web-VPN: Secure Proxies with SPDY & Chrome][Web-VPN_ Secure Proxies with SPDY _ Chrome] * [File:HTTP persistent connection.svg][File_HTTP persistent connection.svg] * [Proxy server][] * [What Is This HTTPS/SSL Thing And Why Should You Care?][What Is This HTTPS_SSL Thing And Why Should You Care] * [What is SSL Offloading?][What is SSL Offloading] * [Sun Directory Server Enterprise Edition 7.0 Reference - Key Encryption][] * [An Introduction to Mutual SSL Authentication][] * [The Difference Between URLs and URIs][] * [Cookie 与 Session 的区别][Cookie _ Session] * [COOKIE 和 SESSION 有什么区别][COOKIE _ SESSION] * [Cookie/Session 的机制与安全][Cookie_Session] * [HTTPS 证书原理][HTTPS] * [What is the difference between a URI, a URL and a URN?][What is the difference between a URI_ a URL and a URN] * [XMLHttpRequest][] * [XMLHttpRequest (XHR) Uses Multiple Packets for HTTP POST?][XMLHttpRequest _XHR_ Uses Multiple Packets for HTTP POST] * [Symmetric vs. Asymmetric Encryption – What are differences?][Symmetric vs. Asymmetric Encryption _ What are differences] * [Web 性能优化与 HTTP/2][Web _ HTTP_2] * [HTTP/2 简介][HTTP_2] [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzg0NDFiMmM0LWRjYTctNGQ2Yi04ZWZiLWYyMmVmY2NhZjMzMS5wbmc]: /images/20211109/a0bf55863046438883410fcc0f010103.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL0hUVFBfUmVxdWVzdE1lc3NhZ2VFeGFtcGxlLnBuZw]: /images/20211109/56e2c8c239f14e13b023079c4f3fec25.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL0hUVFBfUmVzcG9uc2VNZXNzYWdlRXhhbXBsZS5wbmc]: /images/20211109/f240884988ab45cda4b030ec519516b8.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL2RjMDBmNzBlLWM1YzgtNGQyMC1iYWYxLTJkNzAwMTRhOTdlMy5qcGc]: /images/20211109/798715da2ff3491faaab2cbb0a1b6d22.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL0hUVFAxX3hfQ29ubmVjdGlvbnMucG5n]: /images/20211109/c86db8725a2a4179a11443a1155213d4.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL2EzMTRiYjc5LTViMTgtNGU2My1hOTc2LTM0NDhiZmZhNmYxYi5wbmc]: /images/20211109/eba175d67eca4237b76ce5fcd1a4072b.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzJkMDlhODQ3LWI4NTQtNDM5Yy05MTk4LWIyOWM2NTgxMDk0NC5wbmc]: /images/20211109/c8e4c3b944c84f2d80050c28115eed99.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL3NzbC1vZmZsb2FkaW5nLmpwZw]: /images/20211109/82d1064c2d9d439dbc2c161f6638945b.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzdmZmZhNGI4LWIzNmQtNDcxZi1hZDBjLWE4OGVlNzYzYmI3Ni5wbmc]: /images/20211109/7f41013fe4254002a544e05bb1b03806.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzM5Y2NiMjk5LWVlOTktNGRkMS1iOGI0LTJmOWVjOTQ5NWNiNC5wbmc]: /images/20211109/2d7f0977467f45849e1b55c910422809.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL0hvdy1IVFRQUy1Xb3Jrcy5wbmc]: /images/20211109/963bb354b35849c8a3c1d86a8e2c892e.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzIwMTctMDYtMTEtY2EucG5n]: /images/20211109/ce8f043679e04dba9a4792975624ce89.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tLzg2ZTZhOTFkLWEyODUtNDQ3YS05MzQ1LWM1NDg0YjhkMGM0Ny5wbmc]: /images/20211109/a9ff5e5d253242719065f073b004e79b.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL2FmMTk4ZGExLTI0ODAtNDA0My1iMDdmLWEzYjkxYTg4YjgxNS5wbmc]: /images/20211109/89a048eec18048b38dc15b7325e52604.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL2UzZjE2NTdjLTgwZmMtNGRmYS05NjQzLWJmNTFhYmQyMDFjNi5wbmc]: /images/20211109/e6b222c4173445e79ef7af4caee86b3e.png [aHR0cHM6Ly9jcy1ub3Rlcy0xMjU2MTA5Nzk2LmNvcy5hcC1ndWFuZ3pob3UubXlxY2xvdWQuY29tL191NEUwQl91OEY3RC5wbmc]: /images/20211109/27ca9acf12904d69aacae3589d657822.png [MDN _ HTTP]: https://developer.mozilla.org/en-US/docs/Web/HTTP [HTTP_2]: https://developers.google.com/web/fundamentals/performance/http2/?hl=zh-cn [htmlspecialchars]: http://php.net/manual/zh/function.htmlspecialchars.php [Difference between file URI and URL in java]: http://java2db.com/java-io/how-to-get-and-the-difference-between-file-uri-and-url-in-java [How to Fix SQL Injection Using Java PreparedStatement _ CallableStatement]: https://software-security.sans.org/developer-how-to/fix-sql-injection-in-java-using-prepared-callable-statement [HTTP _ Get _ Post]: https://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html [Are http_ and www really necessary]: https://www.webdancers.com/are-http-and-www-necesary/ [HTTP _HyperText Transfer Protocol]: https://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html [Web-VPN_ Secure Proxies with SPDY _ Chrome]: https://www.igvita.com/2011/12/01/web-vpn-secure-proxies-with-spdy-chrome/ [File_HTTP persistent connection.svg]: http://en.wikipedia.org/wiki/File:HTTP_persistent_connection.svg [Proxy server]: https://en.wikipedia.org/wiki/Proxy_server [What Is This HTTPS_SSL Thing And Why Should You Care]: https://www.x-cart.com/blog/what-is-https-and-ssl.html [What is SSL Offloading]: https://securebox.comodo.com/ssl-sniffing/ssl-offloading/ [Sun Directory Server Enterprise Edition 7.0 Reference - Key Encryption]: https://docs.oracle.com/cd/E19424-01/820-4811/6ng8i26bn/index.html [An Introduction to Mutual SSL Authentication]: https://www.codeproject.com/Articles/326574/An-Introduction-to-Mutual-SSL-Authentication [The Difference Between URLs and URIs]: https://danielmiessler.com/study/url-uri/ [Cookie _ Session]: https://juejin.im/entry/5766c29d6be3ff006a31b84e#comment [COOKIE _ SESSION]: https://www.zhihu.com/question/19786827 [Cookie_Session]: https://harttle.land/2015/08/10/cookie-session.html [HTTPS]: https://shijianan.com/2017/06/11/https/ [What is the difference between a URI_ a URL and a URN]: https://stackoverflow.com/questions/176264/what-is-the-difference-between-a-uri-a-url-and-a-urn [XMLHttpRequest]: https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest [XMLHttpRequest _XHR_ Uses Multiple Packets for HTTP POST]: https://blog.josephscott.org/2009/08/27/xmlhttprequest-xhr-uses-multiple-packets-for-http-post/ [Symmetric vs. Asymmetric Encryption _ What are differences]: https://www.ssl2buy.com/wiki/symmetric-vs-asymmetric-encryption-what-are-differences [Web _ HTTP_2]: https://www.kancloud.cn/digest/web-performance-http2
还没有评论,来说两句吧...