一、 TCP/IP协议族
1.1. TCP/IP协议族概念
- 在说
HTTP
前,我们先来了解一下TCP/IP
协议族:不同的硬件、操作系统之间通信都需要一种规则,这种规则称为协议(protocal)
,而协议中存在各式各样的内容。从电缆的规格到IP
地址的选定方法、寻找异地用户的方法、双方建立通信的顺序,以及Web
页面显示需要处理的步骤等等,像这样把与互联网相关联的协议集合起来总称为TCP/IP
协议族,我们通常使用的网络都是在TCP/IP
协议族的基础上运作的,而HTTP
属于它内部的一个子集。
1.2. TCP/IP协议族分层
- 应用层:提供应用服务,包含
HTTP
/DNS
(域名系统)/FTP
(文件传输)。 - 传输层:提供连接中的计算机间的数据传输(请求报文),包含
TCP
(传输控制协议)和UDP
(用户数据报协议)。 - 网络层:处理网络上流动的数据包,数据包是网络传输的最小数据单位,该层规定了通过怎样的传输路线到达对方计算机,并把数据包传送给对方,包含
IP(Internet Protocol)
网络协议。 - 链路层:处理网络连接的硬件部分。
- 利用
TCP/IP
协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,客户端在应用层(HTTP协议)发出一个HTTP请求
,传输层把接收到的请求报文进行分割,并在各个报文上打上标记号及端口号后转发给网络层,在网络层增加作为通信目的地的的MAC
地址后转发给链路层,接收端的服务器在链路层接收到数据后从链路层往上走,走完之后才算是一个完整的HTTP请求
。
- 发送端经过每层都会加上对应的首部信息,含
TCP首部
、IP首部
、以太网首部
,接受端则每经过一层消去一个首部。这种将数据信息包装起来的做法称为封装
。
1.3. 与HTTP关系密切的协议:DNS、TCP、IP
1. DNS协议
DNS协议
位于应用层,负责将域名
解析为IP地址
。
2. TCP协议
TCP协议
位于传输层,提供可靠的字节流服务,它会将大快数据分割成以报文段为单位的数据包进行管理,且能确认数据最终是否送达到对方。为确保将数据准确传送至对方,采用了三次握手
策略,握手过程中使用了TCP的标志
:SYN(synchronize/使同步)
和ACK(acknowledgement/确认)
。
发送端首先发送一个带SYN标志
的数据包给对方。接收端收到后,回传一个带有SYN/ACK标志
的数据包以示传达确认信息。最后,发送端再回传一个带ACK标志
的数据包,代表"握手"结束。若在握手过程中某个阶段莫名中断,TCP协议
会再次以相同的顺序发送相同的数据包。
3. IP协议
-
IP协议
位于网络层,作用是把各种数据包传输给对方,而传输就需要地址,而地址则需要IP地址(勿和IP协议混淆)
和MAC地址(Media Access Control Address/媒体访问控制地址)
。IP地址
指明了节点被分配到的地址,MAC地址
是指网卡所属的固定地址。IP地址
可以和MAC地址
进行配对,IP地址
可变换,但MAC地址
基本上不会更改。 -
IP地址
间的通信依赖MAC地址
,通信基本都需要进行中转,而在进行中转时,会利用下一站中转设备的MAC地址
来搜索下一个中转目标。这时会采用ARP协议(AddressResolution Protocol/地址解析协议)
,ARP
是一种用以解析地址的协议,根据通信方的IP地址
就可以反查出对应的MAC地址
。在中转过程中,计算机和路由器等网络设备只能获悉粗略的传输路线,这种机制称为路由选择(routing)
。
4. 各种协议与HTTP协议的关系
二、HTTP协议
2.1. HTTP概念
HTPP(HyperText Transfer Protocol)
是一种超文本传输协议,或者说是一种传输规则,用于客户端和服务器,通过请求和响应的交换来达成通信。
1. 无状态
-
HTTP
是无状态协议
,即HTTP协议
自身不具备保存之前发送过的请求或响应的功能,也就是说,无法根据之前的状态进行本次的请求处理。优点是不保存状态可减少服务器的CPU
及内存资源的消耗,但同时缺点也明显,所以出现了使用Cookie
来进行状态管理。 -
Cookie
会根据从服务器端发送的响应报文内的一个叫做Set-Cookie
的首部字段信息,通知客户端保存Cookie
。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入Cookie
值后发送出去。服务器端发现客户端发送过来的Cookie
后,会去检查究竟是从哪一个客户端发来的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。 -
Set-Cookie字段属性
2. 持久连接
HTTP协议
的初始版本中,每进行一次HTTP通信
就要断开一次TCP连接
。所以如果当请求的资源很多时,会造成无谓的TCP连接
建立和断开,增加通信量的开销。为解决TCP连接
的问题,产生了keep-alive
的方法,其特点是:只要任意一端没有明确提出断开连接,则保持TCP连接状态
(在HTTP/1.1
中,所有的连接默认都是持久连接)。
- 持久连接也是
管线化
成为可能,即不用等待响应即可发送下一个请求,这样就能够做到同时并行发送多个请求。
2.2. 客户端
1. 请求报文
- 发送请求时会发送请求报文,其由
请求行
(含请求方法
、请求URI
、协议版本
)、报文首部
和报文实体
构成的,且报文首部
和报文实体
以一空行(CR+LF)分隔,如下图:
1. 请求行
请求方法
常用:
- GET: 获取资源。
- POST: 传输实体主体。
检测查询:
- OPTIONS: 询问支持的方法或预检请求。
- HEAD: 获得报文首部,和GET方法一样,只是不返回报文主体部分。用于确认URI的有效性及资源更新的日期时间等。
- TRACE: 追踪路径。
文件相关:
- PUT: 传输文件。
- DELETE: 删除文件。
安全:
- CONNECT: 要求在与代理服务器通信时建立隧道,实现用隧道协议进行TCP通信。
URI/URL
-
URI:统一资源标识符
(Uniform Resource Identifier)
,代表一种标识。 -
URL:统一资源定位符
(Uniform/Universal Resource Locator)
。 -
URI
是资源的标识或头衔,而URL
更为具体,包含了标识的同时还含有资源定位,平时我们在浏览器地址栏内输入的就是UR
L,因为我们要找到这个资源,当然你输入的也是URI
,因为URL
是更为具体的URI
而已。
协议版本
-
HTTP/1.0
-
HTTP/1.1 (目前常用)
-
HTTP/2.0
2. 报文首部
- 报文首部包含
请求首部字段
、通用首部字段
、实体首部字段
、其他(可能包含HTTP的RFC里未定义的首部(Cookie等))
。
- 请求首部字段
Host
Host
会告知服务器,请求的资源所处的互联网主机名和端口号。在HTTP/1.1
规范内是唯一一个必须被包含在请求内的首部字段。
Referer
Referer
会告知服务器请求的原始资源的URI
。
- 通用首部字段
- 请求报文和响应报文两方都会使用的首部。
2.1 Cache-Control
- 请求值:
- 响应值:
2.2 Connection
- 作用:
① 控制不再转发给代理的首部字段
② 管理持久连接
HTTP/1.1
版本的默认连接都是持久连接。为此,客户端会在持久连接上连续发送请求。当服务器端想明确断开连接时,则指定Connection
首部字段的值为Close
。
2.3 Date
- 表明创建 HTTP 报文的日期和时间
2.4 Pragma
Pragma
是HTTP/1.1
之前版本的历史遗留字段,仅作为与HTTP/1.0
的向后兼容而定义。Pragma: no-cache
:该首部字段属于通用首部字段,但只用在客户端发送的请求中。客户端会要求所有的中间服务器不返回缓存的资源。
2.5 Trailer
- 首部字段
Trailer
会事先说明在报文主体后记录了哪些首部字段。该首部字段可应用在HTTP/1.1
版本分块传输编码时。
2.6 Transfer-Encoding
Transfer-Encoding
规定了传输报文主体时采用的编码方式。
2.7 Upgrade
首部字段Upgrade
用于检测HTTP
协议及其他协议是否可使用更高的版本进行通信,其参数值可以用来指定一个完全不同的通信协议。Upgrade
对象仅限于客户端和邻接服务器之间。因此,使用首部字段Upgrade
时,还需要额外指定Connection:Upgrade
,不再转发给代理。服务器可用101 SwitchingProtocols
状态码作为响应返回。
3.8 Via
- 为了追踪客户端与服务器之间的请求和响应报文的传输路径。
3.9 Warning
- 告知用户一些与缓存相关的问题的警告。
- 实体首部字段
- 针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。
Allow
Allow
用于通知客户端能够支持Request-URI
指定资源的所有HTTP
方法。
Content-Location
Content-Location
表示的是报文主体返回资源对应的URI
,可能会和实际请求的对象不同。Location
是令客户端重定向至指定的URI
Content-MD5
Content-MD5
是一串由MD5
算法生成的值,其目的在于检查报文主体在传输过程中是否保持完整,以及确认传输到达。服务器发往客户端。
Expires
- 资源失效日期,
Cache-Control:max-age
优先级更高。
3. 报文实体
在相同的
IP地址
下,由于虚拟主机可以寄存多个不同主机名和域名的Web
网站,因此在发送HTTP请求
时,必须在Host首部
内完整指定主机名或域名的URI
。
2.3. 服务器
1. 响应报文
1. 状态行
-
协议版本
-
状态码:
状态码用于描述返回的请求结果:
1XX 信息性状态码
——接收的请求正在处理2XX 成功状态码
——请求正常处理完毕3XX 重定向状态码
——需要附加操作以完成请求4XX 客户端错误状态码
——服务器无法处理请求5XX 服务端错误状态码
——服务器处理请求出错
常用状态码:
200 OK
——请求成功。表示从客户端发来的请求在服务器端被正常处理了。204 No Content
——请求处理成功,但没有资源可返回。即无实体返回,一般用于只需客户端往服务器发送消息。206 Partial Content
——范围请求。而服务器成功执行了这部分的GET请求。
301 Moved Permanently
——永久重定向。该状态码表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI,当指定资源路径的最后忘记添加斜杠"/",就会产生 301 状态码。302 Found
——临时重定向。URI将来还可能会变。303 See Other
——该状态码表示由于请求对应的资源存在着另一个URI,应使用GET方法定向获取请求的资源。类似302。307 Temporary Redirect
——临时重定向。类似302,不会将POST变为GET,但也视浏览器而定。
当 301、302、303 响应状态码返回时,几乎所有的浏览器都会把POST改成GET,并删除请求报文内的主体,之后请求会自动再次发送。
304 Not Modified
——资源无变化,不返回实体。
400 Bad Request
——请求报文存在语法错误。401 Unauthorized
——请求需要有通过HTTP认证。认证方式有BASIC认证(基本认证)、DIGEST认证(摘要认证)、SSL客户端认证、FormBase认证(()基于表单认证)。403 Forbidden
——请求资源的访问被服务器拒绝。未获得文件系统的访问授权,访问权限出现某些问题等会产生。404 Not Found
——服务器上无法找到请求的资源。
500 Internal Server Error
——服务器端在执行请求时发生了错误。503 Service Unavailable
——服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
- 状态码原因短语
2. 报文首部
- 响应首部字段
3. 报文实体
- 报文实体可进行内容编码,常用编码有:
gzip (GNU zip)
compress (UNIX系统的标准压缩)
deflate (zlib)
identity (不进行编码)
- 分割发送的分块传输编码:
在 HTTP 通信过程中,请求的编码实体资源尚未全部传输完成之前,浏览器无法显示请求页面。在传输大容量数据时,通过把数据分割成多块,能够让浏览器逐步显示页面。
2.4. 中间商
HTTP通信
时,除客户端和服务器以外,还有一些用于通信数据转发的应用程序:代理、网关、隧道
1. 代理
-
代理是一种有转发功能的
应用程序
,它扮演了位于服务器和客户端“中间人”的角色,接收由客户端发送的请求并转发给服务器,同时也接收服务器返回的响应并转发给客户端。代理不改变请求URI
,会直接发送给前方持有资源的目标服务器,每次通过代理服务器转发请求或响应时,会追加写入Via首部信息
,会标记出经过的主机信息。 -
缓存代理
:
代理转发响应时,缓存代理(Caching Proxy)会预先将资源的副本(缓存)保存在代理服务器上。当代理再次接收到对相同资源的请求时,就可以不从源服务器那里获取资源,而是将之前缓存的资源作为响应返回。
透明代理
:
转发请求或响应时,不对报文做任何加工的代理类型被称为透明代理(Transparent Proxy)。反之,对报文内容进行加工的代理被称为非透明代理
。
2. 网关
- 网关是转发其他服务器通信数据的
服务器
,接收从客户端发送来的请求时,它就像自己拥有资源的源服务器一样对请求进行处理。有时客户端可能都不会察觉,自己的通信目标是一个网关。利用网关可以由HTTP请求转化为其他协议
通信。利用网关能提高通信的安全性,因为可以在客户端与网关之间的通信线路上加密以确保连接的安全。
3. 隧道
- 隧道可按要求建立起一条与其他服务器的通信线路,届时使用SSL等加密手段进行通信。隧道的目的是
确保客户端能与服务器进行安全的通信
。隧道本身不会去解析HTTP请求。请求保持原样中转给之后的服务器,隧道会在通信双方断开连接时结束。
2.5. 缓存
- 了解了以上各个报文字段,下面来综合理解缓存机制:
强缓存:是利用
HTTP
头中的Expires
和Cache-Control
两个字段来控制的。强缓存中,当请求再次发出时,浏览器会根据其中的Expires
和Cache-Control
判断目标资源是否“命中”强缓存,若命中则直接从缓存中获取资源,不会再与服务端发生通信。
协商缓存:协商缓存依赖于服务端与浏览器之间的通信,协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。其中涉及
Last-Modifield
与If-Modified-Since
的配合,ETag
与If-None-Match
的配合。
1. Cache-Control
Cache-Control
,这个字段在请求和响应中都可以使用,对应的值如下:
- 请求中使用的值:
- 响应中使用的值:
Cache-Control: public
- 响应独有:缓存公有化。明确表明其他用户也可利用缓存,即浏览器和代理服务器都可进行缓存,默认值为
private
,但当字段中出现s-maxage
时表示当前值为public
。
Cache-Control: private
- 响应独有:缓存私有化。代理服务器不能对资源进行缓存。
Cache-Control: no-cache
- 请求中含义:客户端不使用缓存资源,绕开浏览器缓存确认,直接向源服务器上进行缓存资源的确认。
- 响应中含义:告知缓存代理在缓存资源时需向源服务器确认资源有效性后进行处理,指不缓存过期的资源。(若响应报文
Cache-Control
中对no-cache
字段名具体指定参数值,如Cache-Control: no-cache=Location
,那么客户端在接收到这个被指定参数值的首部字段对应的响应报文后,就不能使用缓存)
Cache-Control: no-store
- 请求中含义:不使用缓存,也不进行缓存确认,直接发送请求获取资源。
- 响应中含义:告知缓存代理不能进行缓存。
Cache-Control: max-age=秒
- 请求中含义:规定缓存经过的最大时间,如果数值未超过缓存的时间则取缓存资源。如果为0,则相当于想服务器请求资源。
- 响应中含义:规定缓存保存的时间。
Cache-Control: s-maxage=秒
- 响应独有:仅在代理服务器中生效(生效则忽略Expires和max-age指令),规定缓存的过期时间。
Cache-Control: max-stale=秒
- 请求独有:指缓存过期了指定时间后依旧可使用该缓存资源。如不指定时间,则不管过期了多久依旧使用缓存资源。
Cache-Control: min-fresh=秒
- 请求独有:指缓存代理返回至少未经过指定时间的缓存资源。
Cache-Control: no-transform
- 请求中含义:在缓存代理中不能改变实体的媒体类型,可防止缓存或代理压缩图片等类似操作。
- 响应中含义:在缓存代理中不能改变实体的媒体类型,可防止缓存或代理压缩图片等类似操作。
Cache-Control: only-if-cached
- 请求独有:只有缓存代理缓存了资源才要求其返回资源。
Cache-Control: must-revalidate
- 响应独有:缓存代理可缓存,但必须先向源服务器确认资源有效性。会忽略请求的max-stale指令。
Cache-Control: proxy-revalidate
- 响应独有:要求所有的缓存代理在接收到客户端带有该指令的请求返回响应之前,必须再次验证缓存的有效性。
Cache-Control: cache-extension
- 请求中含义:扩展新指令标记。
- 响应中含义:扩展新指令标记。
2. Expires
-
Expires: 时间戳
-
首部字段
Expires
会将资源失效的日期告知客户端。缓存服务器在接收到含有首部字段Expires
的响应后,会以缓存来应答请求,在Expires
字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。 -
优点:与
Cache-Control
同时使用,为了向下兼容。 -
缺点:依赖本地时间。
3. Last-Modifield与If-Modified-Since的配合
Last-Modifield: 时间戳
在首次请求时伴随着Response Headers
返回,是一个时间戳,表示最近的一次资源改动时间:
Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT
复制代码
随后我们每次请求时,会带上一个叫If-Modified-Since
的时间戳字段,它的值正是上一次Response Headers
返回给它的Last-Modifield
值:
If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT
复制代码
服务器接收到这个时间戳后,会比对该时间戳和资源在服务器上的最后修改时间是否一致,从而判断资源是否发生了变化。如果发生了变化,就会返回一个完整的响应内容,并在Response Headers
中添加新的Last-Modified
值;否则,返回304响应
,同时Response Headers
不会再添加Last-Modified
字段。
4. ETag与If-None-Match的配合
对于
Last-Modified
的使用是存在弊端的:①服务器不能正确感知文件的变化,如编辑但未修改文件,也会被当成了修改,②文件修改过快也感知不到,因为精度是秒。所以出现了ETag
,由服务器为每个资源生成的唯一的标识字符串,这个标识字符串是基于文件内容编码的,只要文件内容不同,它们对应的ETag
就是不同的。
ETag
和Last-Modified
类似,当首次请求时,我们会在响应头里获取到一个最初的标识符字符串:
ETag: W/"2a3b-1602480f459"
复制代码
那么下一次请求时,请求头里就会带上一个值相同的、名为if-None-Match
的字符串供服务端比对了:
If-None-Match: W/"2a3b-1602480f459"
复制代码
-
特点:
ETag
优先级更高,当ETag
和Last-Modified
同时存在时,以ETag
为准。 -
优点:精确感应文件变化。
-
缺点:
ETag
的生成过程需要服务器额外付出开销,会影响服务端的性能。
5. 缓存策略
了解了以上缓存,在面对一个具体的缓存需求时,我们到底该如何决策?
根据以上
Chrome官方
给出的这张策略图:①当我们的资源内容不可复用时,直接为Cache-Control
设置no-store
,拒绝一切形式的缓存;②否则考虑是否每次都需要向服务器进行缓存有效确认,如果需要,那么设Cache-Control
的值为no-cache
;③否则考虑该资源是否可以被代理服务器缓存,根据其结果决定是设置为private
还是public
;④然后考虑该资源的过期时间,设置对应的max-age
和s-maxage
值;⑤最后,配置协商缓存需要用到的Etag
、Last-Modified
等参数。
三、HTTPS
3.1. HTTP的不足
- ①身份被伪装
- ②报文被篡改
- ③内容被窃听
所以针对以上问题需要进行身份验证
、通信加密
及内容加密
。
HTTP协议
中没有加密机制,但可以通过和SSL(Secure Socket Layer,安全套接层)
或TLS(Transport Layer Security,安全层传输协议)
的组合使用,加密HTTP
的通信内容。与SSL
组合使用的HTTP
被称为HTTPS(HTTPSecure,超文本传输安全协议)
。
- 通常,
HTTP
直接和TCP
通信。当使用SSL
时,则演变成先和SSL
通信,再由SSL
和TCP
通信,所以HTTPS
是身披SSL
外壳的HTTP
。SSL
采用一种叫做公开密钥加密(Public-key cryptography)
的加密处理方式。
1. 通信加密
公开密钥加密
使用一对非对称的密钥。一把叫做私有密钥(private key)
,另一把叫做公开密钥(public key)
。顾名思义,私有密钥
不能让其他任何人知道,而公开密钥
则可以随意发布,任何人都可以获得。发送密文的一方使用对方的公开密钥
进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥
进行解密。利用这种方式,不需要发送用来解密的私有密钥
,也不必担心密钥被攻击者窃听而盗走。
虽然这样解决了加密的问题,但公开秘钥加密
处理速度相对比较慢,所以引入了一种共享秘钥加密
方式,就是通信双方都使用相同的秘钥进行加密和解密
,而使得双方安全的得到这个秘钥就需要使用上述的公开秘钥加密
方式进行秘钥的传输。HTTPS
就是采用共享密钥加密和公开密钥加密
两者并用的混合加密机制
。
2. 身份验证
通信加密方式解决了,但是如何证明公开秘钥是货真价实的呢?
- 为了解决这个问题,可使用由
数字证书认证机构
和其相关机关颁发的公开密钥证书
。首先,服务器的运营人员向数字证书认证机构提出公开密钥的申请。数字证书认证机构在判明提出申请者的身份之后,会对已申请的公开密钥做数字签名
,然后分配这个已签名的公开密钥,并将该公开密钥放入公钥证书后绑定在一起
。公钥证书
也可叫做数字证书
或直接称为证书
。接到证书的客户端可使用数字证书认证机构的公开密钥,对那张证书上的数字签名进行验证,多数浏览器开发商发布版本时,会事先在内部植入常用认证机关的公开密钥,以便能将公开密钥安全地转交给客户端。
3. 内容加密
使用
MD5
和SHA-1
等散列值校验来保证报文完整性,但依旧不可靠,因为内容依旧可被篡改。
四、Web应用攻击
4.1. 主动攻击
主动攻击
指攻击者通过直接访问Web应用,把攻击代码传入的攻击模式。
1. SQL注入攻击
- 如加入引号拆分字符串进而注释掉部分命令来达到破坏原命令的效果。
2. OS命令注入攻击
- 执行非法的操作系统命令达到攻击的目的。
3. 密码破解
-
穷举法-暴力破解法
-
字典攻击-利用事先收集好的候选密码,经过各种组合方式后存入字典,枚举字典中的密码。
-
措施:密码不以明文方式保存
4.2. 被动攻击
被动攻击
是指利用圈套策略执行攻击代码的攻击模式。
1. 跨站脚本攻击(Cross-Site Scripting,XSS)
- 指攻击者通过植入脚本等方式进行攻击,可采取输入验证、输出转义等措施。
2. 跨站请求伪造(CSRF)
- 指攻击者通过设置好的陷阱,强制对已完成认证的用户进行非预期的个人信息或设定信息等某些状态更新。
3. HTTP首部注入攻击
- 指攻击者通过在响应首部字段内插入换行,添加任意响应首部或主体的一种攻击。会造成
设置任意Cookie信息
、重定向至任意URL
、显示任意的主体
等影响。
4. 提示漏洞攻击
-
对于不正确的错误消息处理如果处理不恰当,会成为攻击者利用的切入点。
-
表单验证提示过于详细也会成为漏洞,应抑制模糊设定提示语。
相关参考:《图解HTTP》、《前端性能优化原理与实践》小册等