HTTP 协议在日常网络应用中随处可见,我们在任何时候网上冲浪都会看到 HTTP 协议或 HTTPS 协议的身影。既然其普遍存在,那么就要对它们有一个较为全面的了解!本篇从 HTTP 入手,最后对 HTTPS 进行学习记录。
引
HTTP 协议通常承载于 TCP 协议之上,有时也会承载于 TLS 或 SSL 协议层之上,这时就成了 HTTPS 协议!HTTP 的默认端口号是 80、HTTPS 的默认端口号是 443。
图片出自——《图解HTTP》
HTTP 协议是一个无状态协议,并且采用”客户端请求、服务器应答”模式,这也就意味着服务器无法主动向客户端推送消息、更不能向客户端发起请求!
正文
简述 HTTP 工作流程
- HTTP 开始工作,首先客户端与服务器需要在经历 TCP 三次握手后建立连接。
- 建立连接之后,客户端发送一个请求(request)给服务器。
- 服务器收到请求后开始处理,给予客户端一个响应(response)。(不一定是成功)
- 客户端接收到响应后处理渲染后告诉用户,最后断开连接。
四步中的有任何一步出现错误,错误信息都将返回到客户端。
短连接和长连接?
短连接:每次请求都建立一个 TCP 连接,请求完成后结束连接,新的请求再建立 TCP 连接,缺点很明显就是开销很大。
长连接:发起一个请求之后,建立 TCP 连接,这条客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,但是他有一个保持时间,一般可以在服务器软件中设定这个时间。使用长连接需要客户端和服务端都支持长连接。
不难看出 HTTP 协议的长连接和短连接,实质上就是 TCP 协议的长连接和短连接。
从 HTTP/1.1 开始默认使用长连接,会在响应头加入 Connection:Keep-Alive
字段标识,如果需要断开连接,需要由客户端或者服务器提出断开,使用 Connection:close
字段。
请求和响应
请求(request)总体从上向下包括:请求首行(请求方法、URL、协议版本)、请求头(属性是key:value形式、属性一条一行)、空行、请求体(请求数据)
响应(response)总体从上向下包括:响应首行(协议版本、状态码和状态描述)、响应头(属性是key:value形式、属性一条一行)、空行、响应体(响应数据)
请求方法:
HTTP 1.0 定义三种请求方法:GET、POST、HEAD
HTTP 1.1 又增加了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECT
方法 | 简述 | |
---|---|---|
1 | GET | 请求指定的页面信息,并返回实体主体。当前网络请求中,绝大部分使用的是 GET 方法。在 RESTful 风格中常用作查询。 |
2 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头、确认 URL 的有效性以及资源更新的日期等等。。 |
3 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。在 RESTful 风格中常用作添加。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题。在 RESTful 风格中常用作更新,但是只能完全替代原始资源。 |
5 | DELETE | 请求服务器删除指定的资源,并且同样不带验证机制。在 RESTful 风格中常用作删除。 |
6 | CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。使用 SSL(安全套接字) 和 TLS(传输层安全) 协议把通信内容加密后经网络隧道传输。 |
7 | OPTIONS | 允许客户端查看服务器的性能,查询指定的 URL 能够支持的方法,会返回形如 Allow: GET, POST, HEAD, OPTIONS 这样的内容。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。服务器会将通信路径返回给客户端,发送请求时,可以在 Max-Forwards 字段填入数值,每经过一个服务器就 -1 ,当数值为 0 就停止传输。但是 TRACE 容易受到 XST 攻击(跨站追踪)。 |
9 | PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 。在 RESTful 风格中常用作资源更新,允许部分更新。 |
GET 和 POST 方法的区别?
- 在客户端 GET 方法通过 URL 提交数据,所以只支持 ASCII 码,所以 GET 参数中如果出现中文需要先进行编码,而 POST 方法提交数据在报文中,支持多种标准字符集。
- GET 方法提交的数据大小浏览器有限制,Post 没有。
- GET 方法时幂等的,同样的请求被执行多次效果是一样的,服务器状态也是一样的(统计功能除外),POST 方法是非幂等的。
- GET 请求可以被浏览器主动缓存,而 POST 不会,除非手动设置。
- GET 请求发送一个数据包 header 和 data一起发送出去,POST 请求先发送 header ,服务器响应 100 Continue,浏览器再发送 data。
HTTP 首部字段
不需要牢记,只是作为字典进行查阅。
通用首部字段
首部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Connection | 控制不再转发给代理的首部字段、管理持久连接 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息 |
Warning | 错误通知 |
请求首部字段
首部字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码 |
Accept-Language | 优先的语言(自然语言) |
Authorization | Web 认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag) |
If-Modified-Since | 比较资源的更新时间 |
If-None-Match | 比较实体标记(与 If-Match 相反) |
If-Range | 资源未更新时发送实体 Byte 的范围请求 |
If-Unmodified-Since | 比较资源的更新时间(与 If-Modified-Since 相反) |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中 URI 的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP 客户端程序的信息 |
响应首部
首部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定 URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP 服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
实体首部字段
首部字段名 | 说明 |
---|---|
Allow | 资源可支持的 HTTP 方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小 |
Content-Location | 替代对应资源的 URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
响应状态码
状态码 | 说明 |
---|---|
100 Continue | 服务器收到请求,请求者可以继续发送请求或忽略这个响应 |
200 OK | 请求正常处理完成 |
201 Created | 已创建了新资源 |
202 Accepted | 服务器已接受并处理请求,但还未处理完毕 |
204 No Content | 请求已经处理成功,但是返回的响应报文 |
300 Redirection | 重定向 |
301 Moved Permanently | 永久性重定向,返回信息会包含新的 URL ,之后的请求都应使用新的 URL |
302 Found | 临时性重定向,之后的请求应该继续使用原本的 URL |
400 Bad Request | 客户端请求错误 |
401 Unauthorized | 请求未授权,需要身份认证 |
403 Forbidden | 服务器拒绝执行此请求 |
404 Not Found | 服务器无法找到请求资源 |
405 Method Not Allowed | 请求方法不允许 |
500 Internal Server Failed | 服务器内部错误 |
501 Not Implemented | 服务器不支持请求的功能 |
502 Bad Gateway | 网关错误,从上游服务器收到了一个无效响应 |
503 Service Unavailable | 服务器超载或者宕机 |
504 Gateway Timeout | 网关超时 |
505 HTTP Version not supported | 服务器不支持请求的HTTP协议版本 |
Cookie 和 Session 的选择
- Cookie 只能存储 ASCII 码字符串,Session 可以存储任何类型的数据,因此考虑数据复杂性时首选 Session。
- Cookie 存储在客户端,容易被查看和窃取后发生 Cookie 欺骗,而 Session 存储在服务器,因此考虑数据安全性时首选 Session。
- Session 会在服务器存活一段时间,如果是大流量网站,Session 进行存储的开销非常大,因此考虑减轻服务器性能压力时可以选择 Cookie。
- 很多浏览器对 Cookie 的大小和数量都存在限制,而 Session 不会被浏览器限制。
当客户端禁用了 Cookie ,此时无法用 Cookie 保存信息,只能使用 Session;而且 SessionID 也无法存放在 Cookie 中,针对这点一般可以采用 URL 重写,将 SessionID 作为 URL 的参数进行传递、或者在页面中使用一个隐藏表单,用于传输 SessionID。
HTTPS
说好的 HTTP 和 HTTPS ,怎么所有篇幅都是在说 HTTP?
其实不然,HTTPS 并非什么新的协议,而是让 HTTP 先和 SSL(安全套接字) 通信,再由 SSL 和 TCP 完成通信,也就是说 HTTPS 是使用了 SSL 手段加密的隧道进行通信的 HTTP 协议!
SSL 位于 HTTP 和 TCP 之间的协议,其内部有 TLS握手协议、TLS记录协议,HTTPS 依然经由 HTTP进行通信,但是利用 TLS 来保证安全。在 osi 七层结构中,SSL 处于会话层、HTTP 处于应用层,在 TCP/IP 结构和五层结构中 SSL 和 HTTP 同属于应用层。
通过使用 SSL ,HTTPS 具有了加密隧道(防窃听)、认证(防伪造)、完整性保护(防篡改)的安全特效特性。
SSL:安全套接字,1994年网景公司设计,1995年发布了 3.0 版本。
TLS:传输层安全性协议,IETF 在 SSL3.0 的基础上设计的协议。
下面使用 TLS 进行表述。
TLS 工作流程
将 HTTP 所有传输的内容都经过了加密,加密采用对称加密,但是这个对称加密的秘钥用服务器上的证书(公钥)进行了非对称加密确保这个秘钥的传输安全。因此 HTTPS 消耗了更多的服务器资源,但是安全性较 HTTP 有了质的提升。
上图就是 TLS 的四次握手大致流程,第二次握手之后,客户端可以选择去颁发 server 证书的 CA 验证这个证书的有效性!
下面再从每次握手后 client 和 server 的状态简单阐述一下:
第一次握手,client[A]
server[A,B,选用的加密套件,公钥pk和对应秘钥]
第二次握手,client[A,B,server.crt(公钥pk)]
server[A,B,选用的加密套件,公钥pk和对应秘钥]
server 告知 client ,hello 阶段完成了
第三次握手,client[A,B,C,server.crt(公钥pk),Sesstion Secret]
server[A,B,C1,C,选用的加密套件,公钥pk和对应秘钥,Session Secret]
client 告知 server, 后续的通信都采用协商好的会话秘钥和加密算法
这一步 server 需要验证 F1、F2是否一致,为了确认双方会话秘钥和加密算法一致。
第四次握手,client[A,B,C,server.crt(公钥pk),Sesstion Secret]
server[A,B,C1,C,选用的加密套件,公钥pk和对应秘钥,Session Secret]
server告知 client , 后续的通信都采用协商好的会话秘钥和加密算法
这一步 client 需要验证 F3和原始明文数据是否一致,为了确认 server 生成的会话秘钥和采用的加密算法是否正确。
注意三点:
- 生成 Session Secret 需要三个随机数的明文。
- 服务器证书中包含着服务器非对称加密的密钥对中的公钥,私钥只有服务器知道。
- server 证书中的公钥只用来在协商秘钥时加密会话秘钥中的参数。
本人菜鸟,有错误请告知,感激不尽!
更多题解和源码:github