概述
HTTP:HyperText Transfer Protocol, 超文本传输协议,一种用于分布式、协作式和超媒体信息系统的应用层协议。是万维网的数据通信基础。
客户端:通过浏览器、网络爬虫或其他工具,客户端发起一个HTTP 请求到服务器上指定端口(默认80),则客户端可称为 用户代理程序(user agent)。
服务端:应答服务器上存储着一些资源,如 HTTP 文件和图片,则应答服务器可称之为源服务器(orgin server)。
中间层:在用户代理和源服务器之间可能存在多个“中间层”,比如代理服务器、网关和隧道(tunnel)。
协议底层
HTTP 协议中,未规定必须使用它或它支持的层。故实际上,HTTP 可以在任何互联网协议上实现。但 HTTP 假定其底层协议提供可靠的传输。因此,任何能够提供这种保证的协议都可以被其使用。故而,在 TCP/IP 协议族中使用 TCP
作为其传输层。
TCP/IP协议族
用于约定网络中,不同计算机设备间通信的一系列规则,主要用于解决:
- 如何探测到通信目标;
- 由哪一边先发起通信;
- 使用哪种语言通信;
- 怎样结束通信;
TCP/IP的分层
- 应用层
- 提供应用软件间的通信基础;
- 如 HTTP(HyperText Transfer Protocol)、FTP(File Transfer Protocol)、DNS(Domain Name System);
- 传输层
- 提供网络连接中的两台计算机之间的数据传输;
- TCP(Transmission Control Protocol)、UDP(User Data Protocal)
- 网络层
- 用于处理网络上流动的数据包。数据包是网络传输的最小单位。该层规定了通过怎样的路径到达对方计算机,并把数据包发送给对方。
- IP(Internet Protocol);
- 数据链路层
- 用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱动、网卡等物理可见部分。
相关协议
IP,负责传输
把各种数据包传输给对方。两个确保传输抵达的条件:IP 地址和 MAC 地址(Media Access Control Address)。
IP 地址可以和 Mac 地址进行配对。IP 地址可变,MAC 地址基本固定。
通过 ARP(Address Resolution Protocol)以解析地址,通过通信方的 IP 地址就可以反查出对应的 MAC 地址。
TCP,确保可靠性
TCP 位于传输层,提供可靠的字节流服务(Byte Stream Service)。
BSS: 为了方便传输,将大块数据分割成报文段(segment)为单位的数据包进行管理,
可靠:指的是,能够把数据准确可靠的传递给对方。
client --> syn --> server
client <-- syn/ack <-- server
client --> ack --> server
DNS,负责域名解析
DNS, Domain Name System,提供域名到 IP 地址之间的解析服务。
DNS, TCP, IP 对于一个 HTTP 通信的协同工作
相关关键字
URI
Uniform Resource Identifier, 统一资源标识符,用于标示某一互联网资源名称的字符串。
指定标示 web 资源的字符串的各个不同部分。
格式构成:
协议名 + 认证信息 + 服务器地址 + 服务器端口号+ 资源路径 + 查询参数 + 片段标识符
URL
Uniform Resource Locator, 统一资源定位符,标示一个互联网资源,并指定了对其操作或获取该资源的方法。
两者之间的差异:
如:urn:issn:1535-3613
是一个 URI,但不是一个 URL。
如:http://example.org/absolute/URI/with/absolute/path/to/resource.txt
是个 URI,更是一个 URL。
HTTP 协议基础
HTTP三点注意事项:
- 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
- 媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
- 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
请求报文
- 请求行:请求方法 + 请求 URL + 协议版本
- 请求头:请求首部字段(可选)
- 内容实体
// 访问 http://baidu.com
//请求行
Get / HTTP/1.1
//请求头
Host: www.baidu.com
Connection: keep-alive
Cache-Control: max-age=0
User-Agent: Chrome/65.0 ...
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN, zh;q=0.9,en;q=0.8;zh-TW;q=0.7
Cookie: ...
//内容实体
...
响应报文
- 状态行:协议版本 + 响应状态 + 响应描述
- 响应头部:响应头部字段
- 内容实体
//状态行
HTTP/1.1 200 OK
//响应头
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-TYpe: text/html;charset=utf-8
Date: Tue, 17 Apr 2018 15:02:15 GMT
Expires: Tue, 17 Apr 2018 15:02:15 GMT
Server: BWS/1.1
SetCookie: BDSVRTM=117; path=/
TRansfer-Encoding: chunked
//内容实体
<html>
...
请求方法
- GET : 向服务器获取资源
- POST :向服务器发送内容实体
- OPTIONS:询问服务器支持的请求方法
- HEAD:类似 GET,但只返回报文头部,用于确认 URL 的有效性以及资源更新的日期等。
- PUT:向服务器传递文件
- DELETE:从服务器删除文件
- TRACE:追踪路径
- CONNECT:要求用隧道协议连接代理
GET VS POST
区别:语义上,GET 从服务器获取数据,POST 向服务器发送数据
RFC 中定义了 HTTP 方法的几个性质:
- Safe, 安不安全,指的是对服务器的内容是否[只读],例如 GET,自从服务器获取数据而不进行修改,则其为安全的;
- Idempotent, 幕等,指同一个请求方法多次执行和仅执行一次的效果完全相同。如 Get 是幕等的,而 Post不是;
- Cacheable, 可缓存的,RFC 中 GET,HEAD 和某些情况下的 POST 都是可缓存的,但绝大多数浏览器里只支持缓存;
即,GET 是安全的,幕等的,可缓存的;而 POST 反之。
现实中,讨论的不同,多是浏览器约束,或是服务器约束导致的使用上的不同,而非 Get 与 POST 语义上的不同;
如:
- 数据量大小,Get 一样可以传递和 POST 一样的数据, 在 Body 中加入数据;只是一般约定GET不在 Body 中传递数据;
- 数据缓存,GET 可缓存,POST 不能缓存;
- GET 请求,数据 URL 明文可见;POST 请求,数据抓包明文可见;
- GET 参数,长度有限制(受限于 URL 长度,具体的数值取决于浏览器和服务器的限制)
HTTP1.1 相对前面版本的优化手段
- 持久化连接,keep-alive, 默认,减少客户端与服务器建立连接的开销;
- 请求管道化,发出多个请求时,后序请求不需要等待前面请求得到响应后才发出;
- cookie, 通过在客户端写入 Cookie 信息,来保存一些必要状态,下次客户端请求时,自动发出。
HTTP 响应状态码
- 1** 信息性状态码,服务器收到请求,需要请求者继续执行操作
- 2** 成功状态码,操作被成功接受并处理
- 3** 重定向状态码,需要进一步的操作以完成请求
- 4** 客户端错误状态码,请求包含语法错误或无法完成资源请求
- 5** 服务端错误状态码,服务器在处理请求的过程中发生了错误
1**
- 100 Continue, 继续。客户端应继续其请求
- 101 Switching Protocols, 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级(版本)的协议。
2**
- 200 OK,请求成功。一般用于 GET 和 POST。
- 201 Created,已创建。成功请求并创建了新的资源。
- 202 Accepted,已接受。已接受请求,但未完成处理。
- 203 Non-Authoritative Information,非授权信息。请求成功,但返回的 meta 信息不在原始的服务器,而是一个副本。
- 204 No Content,无内容。服务器处理成功,但未返回内容。
- 205 Reset Content,重置内容。服务器处理成功,客户端应该重置文档视图。
- 206 Partial Content,部分内容。客户端进行了范围(range)请求,服务器成功处理了范围 GET 请求。
3**
- 300 Multiple Choices,多种选择。请求的资源可包含多个位置,相应可返回一个资源特征与地址的列表用于客户端的选择。
- 301 Moved Permanently, 永久移动。 请求的资源已经被永久的移动到新的 URI,返回信息会包含新的 URI,浏览器会自动定向到新的 URI。今后任何新的请求都使用新的 URI。
- 302 Found,临时移动。类似301,但资源只是临时移动。客户端继续使用原有的 URI。
- 303 See Other,查看其他地址。类似301,使用 GET 或 POST 查看请求。
- 304 Not Modified,未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回指定日期之后修改的资源。
- 305 Use Proxy,使用代理。所有请求的资源必须通过代理访问。
4**
- 400 Bad Request,客户端请求语法错误,服务器无法理解
- 401 Unauthorized,请求要求用户的身份认证
- 402 Payment Required, 保留,将来使用
- 403 Forbidden,服务器理解客户端的请求,但拒绝执行请求
- 404 Not Found, 服务器无法根据请求找到资源
- 405 Method Not Allowed,请求方法被禁止
- 406 Not Acceptable,服务器无法根据请求的内容特性完成请求
- 407 Proxy Authentication Required,请求要求代理的身份认证,类似401,但要求使用代理
- 408 Request Timeout,服务器等待客户端发送请求时间过长,超时
- 409 Conflict,服务器完成客户端的 PUT 请求可能返回此状态码,表示服务器处理请求时发生了冲突
5**
- 500 Inernal Server Error,服务器内部错误,无法完成请求
- 501 Not Implemented,服务器不支持请求,无法完成请求
- 502 Bad Gateway,充当网关或代理的服务器,从远端服务器接收到了一个无效的请求
- 503 Service Unavailable,由于超载或系统维护,服务器暂时无法处理请求。延时的长度可包含在服务器的 Retry-After 头信息中
- 504 Gateway Timeout,充当网关或代理服务器,未及时从远端服务器获取请求
- 505 HTTP Version not supported,服务器不支持请求的 HTTPS 协议版本,无法完成处理
HTTP 首部
格式:首部字段名: 首部字段值
首部类型:
- 通用首部:请求报文 或 响应报文都可能用到的首部。
- 请求首部:补充请求的附加内容、客户端信息、响应内容优先级等。
- 响应首部:补充响应的附加内容,以及要求客户端额外附加的内容信息。
- 实体首部:补充内容资源的更新时间等与实体有关的信息。
通用首部
首部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存行为,如:强制请求源资源(no-cache),缓存最大时间(max-age),缓存对象(private,public) |
Connection | 控制禁止转发(通过代理)的首部字段,管理持久连接(keep-alive) |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式,通常用于分块(chunked)传输 |
Upgrade | 升级为其他协议,配合 Connection 使用 |
via | 代理服务器的相关信息 |
Warning | 错误通知,报告缓存相关问题 |
请求首部
首部字段名 | 说明 |
---|---|
Accept | 客户端可处理的媒体类型以及优先级,使用MIME类型指定 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码,如:gzip, compress, deflate |
Accept-Language | 优先的自然语言语言,如:zh-cn,q=0.9; |
Authorization | Web 认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮件地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag)是否相同 |
If-None-Match | 比较实体标记不同 |
If-Range | 资源未更新时发送实体 Byte 的范围请求,配合 ETag 请求资源 |
If-Modified-Since | 比较资源的更新时间,与响应返回的 Last-Modified 关联 |
If-Unmodified-Since | 比较资源未更新的时间 |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要去客户端的认证信息 |
Range | 获取部分资源的byte范围 |
Referer | 对请求中 URI 的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | 浏览器相关信息 |
响应首部
首部字段名 | 说明 |
---|---|
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 | 资源的最后修改日期时间 |
HTTPS
TLS(Transport Layer Security)是IETF 对 SSL(Secure Socket Layer) 的标准化;
Hypertext Transfer Protocol Secure, 超文本传输安全协议,常称为 HTTP over SSL/TLS, 是一种通过计算机网络进行安全通信的传输协议。
HTTPS 由 HTTP 进行通信,但使用 SSL/TLS 来加密数据包。
目的:提供对网站服务器的身份认证,保护交换数据的隐私和完整性。
主要思想:在不安全的网络上创建一个安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理防护。
技术细节
与 HTTP 的不同:
- URL 由
https://
起始,默认端口为443
, 不同于 HTTP 使用http://
起始,默认端口为80
。 - 可防止监听和中间人攻击。
协议层
- HTTP 协议 与 安全协议 同属于应用层,安全协议工作于 HTTP 之下,传输层之上;
- 安全协议向运行 HTTP 的进程提供一个类似 TCP 的套接字,供进程向其中注入HTTP报文,安全协议将报文加密并注入传输层套接字;或是从传输层获取加密报文,解密后交给对应的进程。
HTTPS 的简单流程如下:
- 用户在浏览器中访问:https://xxx.com
- TCP 与服务器的 433 端口建立连接
- SSL 层客户端与服务器进行协商出一份加密密钥,用于加密数据;
- HTTP 将用户的请求翻译成 HTTP 请求,如:
Get / HTTP/1.1
Host www.xxx.com
- 浏览器用前面的生成的密钥来加密 HTTP 请求,并通过 TCP 通道传递给服务器;
- 服务器收到并解密经过 SSL 加密后的数据,响应 HTTP 请求,经 SSL 加密后返回给浏览器;
- 浏览器对收到的加密数据进行解密,展现给用户。
- 整个流程示例图如下:
一般的 HTTP 通过 TCP 建立连接:
HTTPS 基于 SSL 的 TCP 建立连接:
HTTPS 中,传输数据前 SSL的握手说明:
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议作为一套加密传输的协议,使用了非对称加密,对称加密以及HASH算法。握手过程的简单描述如下:
- 浏览器将自己支持的一套加密规则发送给网站;
- 网站从中选出一组加密算法与 HASH 算法,并将自己的身份信息以证书的形式发回给浏览器。证书里包含了网站地址,加密密钥,以及证书的颁发机构等信息。
- 获得网站证书后,浏览器做以下工作:
- 验证证书的合法性,如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示
- 如果证书受信任,或者用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
- 使用约定好的 Hash 计算握手信息,并使用生成的随机数对消息进行加密,最后将之前生成的所有消息发送给网站。
- 网站接受浏览器发来的数据之后要做以下操作:
- 使用自己的私钥将信息解密,取出密码,使用密码解密浏览器发来的握手信息,并验证 Hash 是否与浏览器发来的一致 。
- 使用密码加密一段握手信息,发送给浏览器 。
- 浏览器解密并计算握手消息的 Hash,如果与服务器发来的 Hash 一致,此时握手过程结束 ,之后所有的通信数据将由之前浏览器生成的随机密码,并使用对称加密算法进行加密。
密钥协商过程:
- 非对称加密算法进行密钥交换;
- 公钥算法协商出密钥;
- 对称算法来加密数据;
- 使用 Hash 校验数据完整性;
由于非对称加密的速度比较慢,所以它一般用于密钥交换,双方通过公钥算法协商出一份密钥,然后通过对称加密来通信,当然,为了保证数据的完整性,在加密前要先经过HMAC的处理。
这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正数据的传输做一次测试。
服务器设置
- 获得证书:获取由证书颁发机构签发的证书或组织自制的证书。
- 作为访问控制:为用户下发独立的证书(通常包含用户名、邮件地址等),服务器控制用户可访问的内容。
SSL/TLS 使用到的相关算法:
对称加密
对称加密:又分分组密码和序列密码。
- 分组加密:将明文按一定的位长分组,明文组经过加密运算得到密文组,密文组经过解密运算(加密运算的逆运算),还原成明文组。例如:DES,RC5, IDEA.
- 序列密码:指利用少量的密钥(制乱元素)通过某种复杂的运算(密码算法)产生大量的伪随机位流,用于对明文位流的加密。解密是指用同样的密钥和密码算法及与加密相同的伪随机位流,用以还原明文位流。例如:RC4。
非对称加密
公钥加密:简单的说就是加密密钥与解密密钥不同,分私钥和公钥。这种方法大多用于密钥交换,RSA便是一个我们熟知的例子。还有一个常用的称作DH,它只能用于密钥交换,不能用来加密。
单向散列函数
由于信道本身的干扰和人为的破坏,接受到的信息可能与原来发出的信息不同,一个通用的办法就是加入校验码。
单向散列函数便可用于此用途,一个典型的例子是我们熟知的MD5,它产生128位的摘要,在现实中用的更多的是安全散列算法(SHA),SHA的早期版本存在问题,目前用的实际是SHA-1,它可以产生160位的摘要,因此比128位散列更能有效抵抗穷举攻击。
由于单向散列的算法都是公开的,所以其它人可以先改动原文,再生成另外一份摘要。解决这个问题的办法可以通过HMAC(RFC 2104),它包含了一个密钥,只有拥有相同密钥的人才能鉴别这个散列。