学习过计算机网络的都知道对于计算机网络的系统结构,如果以五层协议为标准可以将整个体系划分为五层,即物理层,数据链路层,网络层,运输层和最后的应用层,应用层的任务是通过应用进程间的交互来完成特定的网络应用,应用层的协议定义的是应用进程间的通信和交互的规则,具体的实现则是由下一层去实现,以 Android 来说就是 Android 客户端应用进程和服务器应用进程的通信。而 HTTP / HTTPs 等协议就是属于应用层的协议。
HTTP 翻译为超文本传输协议,定义了客户进程如何向服务器请求资源以及服务器如何将资源返回给客户端。HTTP 使用的是面向连接的 TCP 的运输层协议,保证数据的可靠传输,但是 HTTP 是无连接的,也就是说在应用层面交换报文的时候不会先进行连接。
HTTP 是无状态的意思就是说对于同一客户端的每一次请求服务器的处理都是一样的,不会记录客户端的上一次访问,也不记得客户端访问过多少次,因此使得服务器更能支持大量的并发操作。
虽然 HTTP 是无连接,但是 TCP 是面向连接的,所以客户端发起一个请求的时候还是要先建立连接,然后再进行 HTTP 通信,最后再断开连接。
在HTTP 协议 1.0 版本和之前的时候, HTTP 都是属于这种非持续连接的方式,即每个请求访问都需要建立连接,释放连接,即使在同一个页面下也是如此,这是因为一个页面通常存在多个请求。非持续的连接不仅会增加了服务器的负担而且对于同一个界面的响应速度也会降低。
HTTP 1.1 版本使用了持续连接,持续连接就是客户端和服务器在建立连接后进行通信后,仍然在一段时间内保持连接,这样客户端和服务器后续的请求就不用再进行建立释放的操作。而且持续连接还可以进行非流水线的方式进行通信,就是下一次的客户端请求不用等上一次的服务器的答复就能发送,使得客户端的访问更加高效快速。
HTTP 有两种报文:
在实际的场景的时候我们看到的是如下的格式:
请求报文中包含了请求方法,URL, 协议的版本,接着就是首部行,包含各种各样的请求字段,最后就是报文的主体。
在 HTTP 中有 HTTP/1.0 HTTP/1.1 HTTP/2 ,当然还可能使其他的协议。
首部字段中包含有通用的字段,即 请求报文或者响应报文都可以有的字段,同时也有请求报文独有的字段。
请求的首部字段:
Accept,表示能够处理的媒体类型,即对每种类型的优先级。比如
Accept-EnCoding, 允许对资源的压缩解压方式。
Accept-Charset,允许的字符集。
Accept-Language,允许的语言,指处理的自然语言集。
Host,表示请求的资源的所处的服务器和主机名。
Authorization,表示添加用户的认证信息。
User-Agent ,创建请求的客户端和用户代理等信息。
等等。
2xx 以 2 开头的表示请求正常处理完毕
3xx 表示需要进行附加操作以完成请求(重定向)
4xx 表示服务器无法处理请求
5xx 服务器请求出错
前面说过 HTTP 是状态的协议,因此不会对之前发生过的请求和响应做处理。但是对于需要登录认证的服务端,每次请求都进行登录认证显然不合适,因此 HTTP 引入 Cookie 技术,通过在请求和响应报文中添加 Cookie 信息来管理客户端的状态。
Cookie 的工作方式:
在网络通信过程中,由于网络设备,网线光缆,计算机等都有可能是共有的物品,因此在网络上传输一些隐私信息的时候就需要对数据进行保护。一个安全的计算机网络至少应到达下面三个目标:
现在的数据加密技术一般有两种:
又称共享密钥加密,即发送方和接收方都是用同一把密钥对密文进行加密解密,发送方先把密钥发给接收方,接着通过密钥加密数据,最后把密文发送出去,接收方收到密文后就使用前面收到的密钥进行解密。
这种方式显然是有问题的,因为密钥如果被窃取了,后面的密文加密效果就同样失效。
对称加密在两方之间使用的是同一把密钥,而公钥密码加密使用的是一对不同的密钥。
通过这种方式就不存在这对称密钥的不安全问题。但是还是存在着一个问题,就是无法确定密钥是否是对方的公开密钥的问题。实际上这个问题和端点鉴别本质上是一样的,就是确认真实性。
端点鉴别可以分为两种,一种是对于客户端的认证,一种是对于使用者实体的认证,因为就算客户端是真实可信的,但是使用者还是可能存在这是用他人的计算机进行冒充
为了确认通信方,有一种称为证书的手段,可以确认通信方。证书是由值得信任的第三方机构颁发的,用于证明服务器和客户端是实际存在的,而且伪造证书技术十分困难,所以只要持有证书即可判断通信方的真实身份。
对于上述的密钥的问题,对密钥的认证的称为密钥证书。
在 HTTP 中使用了如下几种对用户进行认证的方式:
BASIC 认证就是使用 Authorization/WWW-Authenticate 首部字段进行认证。
因为账号和密码是直接在信息中添加的,因此就有泄露的风险。
DIGEST 认证不直接发送账号和密码,而是使用质询码。
SSL 认证就是类似于使用客户端认证的方式,服务器凭借客户端的证书进行认证。
客户端会向服务器发送登录信息,按登录的信息结果进行认证,这种方式是通过所密文加密对账号和密码进行保护的,通常使用的认证方式都是属于这种表单认证方式。
对于信息的完整性,通常使用的是 MD5 和 SHA 等散列值校验法,这两种算法都是使用密码散列函数。
散列函数:
散列函数的输入长度可以很长,但是输出长度是固定,并且较短,散列函数的输出叫做散列值,简称散列。
不同的散列值肯定对应步不同的输入,但是不同的输入可能得出相同的散列值
,就是说散列函数的输入和输出是多对一的关系。
因为要找到两个不同的报文使得有相同的散列输出基本不可能实现,因此散列函数是一种单向函数,对于 MD5 ,因为现在已经被证明能够找到一对报文有相同的散列值,所以对于 MD5 进行改进推出 SHA .
通过使用各种鉴别算法,就能提高信息的完整性。
目前对于网络安全提供安全服务,被广泛使用的有两个协议:
TSL 是对 SSL 的改进,因此通常将 TSL/SSL 统称为 SSL, SSL 安全服务本质上使用的就是上述三种方法,达到网络通信的安全。
对于 HTTP 协议来说,它并没有对数据进行保护,存在网络安全问题:
为了解决上述的问题,在 HTTP 的基础上加上网络安全等技术就是 HTTPS .
HTTP + 加密 + 认证 + 完整性保护 = HTTPS
HTTP + SSL = HTTPS
以上两种说法都是说明 HTTPS 在网络通信中已经足够安全,使用 HTTPS 通信的时候不再使用 http:// ,而是使用 https:// ,现在的 Chrome 浏览器就可以识别。
HTTPS 不是一种新的协议,只是对于一些接口使用 SSL 代替。
在前面描述过两种加密的方式,第一种速度快但是不安全,第二种安全但是速度慢,因此为了结合两种优点, HTTPS 使用的是两种加密方式混合使用的方式。
结合上述的知识,HTTPS 的通信如下:
引用自 上野 宣的《图解 HTTP 》
步骤 1: 客户端通过发送 Client Hello 报文开始 SSL 通信。报文中包含客户端支持的 SSL 的指定版本、加密组件列表(所使用的加密算法及密钥长度等)。
步骤 2: 服务器可进行 SSL 通信时,会以 Server Hello 报文作为应答。和客户端一样,在报文中包含 SSL 版本以及加密组件。服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的。也就是从客户端的列表选出服务器支持的加密组件然后通知客户端使用哪一种加密。
步骤 3: 之后服务器发送 Certificate 报文。报文中包含公开密钥证书。
步骤 4: 最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的SSL握手协商部分结束。
步骤 5: SSL 第一次握手结束之后,客户端以 Client Key Exchange 报文作为回应。报文中包含通信加密中使用的一种被称为 Pre-master secret 的随机密码串。该报文已用步骤 3 中的公开密钥进行加密。
步骤 6: 接着客户端继续发送 Change Cipher Spec 报文。该报文会提示服务器,在此报文之后的通信会采用 Pre-master secret 密钥加密。
步骤 7: 客户端发送 Finished 报文。该报文包含连接至今全部报文的整体校验值。这次握手协商是否能够成功,要以服务器是否能够正确解密该报文作为判定标准。
步骤 8: 服务器同样发送 Change Cipher Spec 报文。
步骤 9: 服务器同样发送 Finished 报文。
步骤 10: 服务器和客户端的 Finished 报文交换完毕之后,SSL 连接就算建立完成。当然,通信会受到 SSL 的保护。从此处开始进行应用层协议的通信,即发送 HTTP请求。
步骤 11: 应用层协议通信,即发送 HTTP 响应。
步骤 12: 最后由客户端断开连接。断开连接时,发送 close_notify 报文。这步之后再发送 TCP FIN 报文来关闭与 TCP 的通信。在以上流程中,应用层发送数据时会附加一种叫做 MAC(Message Authentication Code)的报文摘要。MAC 能够查知报文是否遭到篡改,从而保护报文的完整性。
大致情况如图: