一.前言
学习过计算机网络的都知道对于计算机网络的体系结构,如果以五层协议为标准可以将整个体系划分为五层,即物理层,数据链路层,网络层,运输层和最后的应用层,应用层的任务是通过应用进程间的交互来完成特定的网络应用,应用层的协议定义的是应用进程间的通信和交互的规则,具体的实现则是由下一层去实现,以 Android 来说就是 Android 客户端应用进程和服务器应用进程的通信。而 HTTP / HTTPs 等协议就是属于应用层的协议。
二. HTTP
1.简介
HTTP 翻译为超文本传输协议,定义了客户进程如何向服务器请求资源以及服务器如何将资源返回给客户端。HTTP 使用的是面向连接的 TCP 的运输层协议,保证数据的可靠传输,但是 HTTP 是无连接的,也就是说在应用层面交换报文的时候不会先进行连接。
2.HTTP 是无状态的
HTTP 是无状态的意思就是说对于同一客户端的每一次请求服务器的处理都是一样的,不会记录客户端的上一次访问,也不记得客户端访问过多少次,因此使得服务器更能支持大量的并发操作。
3.HTTP 从非持续连接到持续连接
虽然 HTTP 是无连接,但是 TCP 是面向连接的,所以客户端发起一个请求的时候还是要先建立连接,然后再进行 HTTP 通信,最后再断开连接。
HTTP 1.0
在HTTP 协议 1.0 版本和之前的时候, HTTP 都是属于这种非持续连接的方式,即每个请求访问都需要建立连接,释放连接,即使在同一个页面下也是如此,这是因为一个页面通常存在多个请求。非持续的连接不仅会增加了服务器的负担而且对于同一个界面的响应速度也会降低。
HTTP 1.1
HTTP 1.1 版本使用了持续连接,持续连接就是客户端和服务器在建立连接后进行通信后,仍然在一段时间内保持连接,这样客户端和服务器后续的请求就不用再进行建立释放的操作。而且持续连接还可以进行非流水线的方式进行通信,就是下一次的客户端请求不用等上一次的服务器的答复就能发送,使得客户端的访问更加高效快速。
4.报文结构
HTTP 有两种报文:
- 请求报文,客端发给服务器请求。
- 响应报文,服务器针对客户端的请求的响应。
在实际的场景的时候我们看到的是如下的格式:
(1) 请求报文
请求报文中包含了请求方法,URL, 协议的版本,接着就是首部行,包含各种各样的请求字段,最后就是报文的主体。
方法,表示这次请求的具体操作,一般有如下几种:
- GET, 获取资源,即简单从服务器获取资源
- POST,上传实体,即将信息上传到服务器
- HEAD,获得响应报文的首部,通常用于检测 URL 的有效性,和资源是否更新。
- OPTIONS,表示查询服务器资源能支持的方法,比如支持 GET,POST就返回 Allow :GET,POST 。
- CONNECT,表示要求在服务在与代理服务器通信的时候建立隧道,实现用隧道协议进行 TCP 通信。
URL,统一资源定位符
- URL 统一资源定位符,在网络中表示互联网资源的地点。
- URI 统一资源标识符,表示某一个互联网的资源。
在网络中很多情况下上 URL 和 URI 表示的同一个东西。
版本,协议的版本
在 HTTP 中有 HTTP/1.0 HTTP/1.1 HTTP/2 ,当然还可能使其他的协议。
首部字段,是对请求的具体方式的进一步的描述
首部字段中包含有通用的字段,即 请求报文或者响应报文都可以有的字段,同时也有请求报文独有的字段。
请求的首部字段:
- Accept,表示能够处理的媒体类型,即对每种类型的优先级。比如
- 文本文件 text/html 。
- 图片文件 image/jpeg, image/gif,image.png。
- 视频文件 video/mpeg。
在后面可使用 q 指点优先接受的媒体类型 范围为 0 ~ 1。
- 视频文件 video/mpeg。
Accept-EnCoding, 允许对资源的压缩解压方式。
- Accept-Charset,允许的字符集。
- Accept-Language,允许的语言,指处理的自然语言集。
- Host,表示请求的资源的所处的服务器和主机名。
- Authorization,表示添加用户的认证信息。
- User-Agent ,创建请求的客户端和用户代理等信息。
- 等等。
(2) 响应报文
版本,这里指的是协议的版本,如果上述的版本一样,这里不再赘述。
状态码/短语,指的是对每一次的请求,服务器做出响应后回将结果放回给客户端,表示成功或失败或更具体地信息。状态码就是对结果状态的一种表示,短语就是添加简单的原因。
2xx 以 2 开头的表示请求正常处理完毕
- 200 OK,表示从客户端发来的请求在服务器端被正常处理了
3xx 表示需要进行附加操作以完成请求(重定向)
- 301 Moved Permanently ,永久性重定向,该状态表示请求的资源已被分配了新的 URI
指的是永久性的移动 - 302 Found ,临时重定向,表示请求的资源已被分配新的 URI ,但是暂时性的
4xx 表示服务器无法处理请求
- 400 Bad Request 该状态码表示请求的报文存在语法错误,需要修改内容再次发送请求。
- 401 Unauthorized,该状态码表示发送的请求需要通过 HTTP 认证的认证信息,例外若需要之前进行过一次请求,则表示用户认证失败
- 403 ForBidden ,表示对请求的资源的访问被服务器拒绝了
- 404 Not Found ,无法找到请求的资源,也可以表示服务端拒绝请求且不想说明的理由。
5xx 服务器请求出错
- 500 Internal Server Error ,服务器内部出现了错误
- 503 Service Unavailable ,表明服务器正处于超负荷或者正在进行停机维护,无法处理请求。
响应首部字段
- Accept-Ranges :请求对资源的一部分进行请求,结果就放回这一部分的范围。
- Age,表示服务器多久前创建了响应
- Location,表示请求的资源被重定向后的 URL.
- Proxy-Authenticate,对代理服务器的认证信息的请求的回答。
(3)通用的首部字段
- Cache-Control,缓存指令,能够控制缓存的行为,缓存响应指令有 no-cache ,目的是为了防止从缓存中返回过期的资源,表示客户端不会接收缓存过的响应。no-store 暗示请求或者响应包中包含机密的信息,不能缓存。
- Connection,控制不再转发给其他代理的首部字段。
- Date,表明HTTP 报文创建的时间。
- 等等
(4)实体字段
- Allow,资源可支持的 HTTP 方法
- Content-Encoding,实体的主体部分选用的内容编码方式。
- Content-Language,实体主体使用的自然语言。
- Content-Length,实体主体的部分的大小,单位是字节。
- Content-Type,实体主体对象 的媒体类型
- 等等
5.Cookie
前面说过 HTTP 是状态的协议,因此不会对之前发生过的请求和响应做处理。但是对于需要登录认证的服务端,每次请求都进行登录认证显然不合适,因此 HTTP 引入 Cookie 技术,通过在请求和响应报文中添加 Cookie 信息来管理客户端的状态。
Cookie 的工作方式:
- 首先客户端第一次访问服务器,服务器会产生一个唯一的标识码,比如 SessionID, 然后把这个标识码添加到响应报文中,以 Set-Cookie 为首部字段。例如 Set-Cookie :1df5f36t61b5y5k2d9w7h3h
- 客户端收到响应报文后,就将这个标识码进行保存,以后再每次请求这个服务器的时候就把这个标识码添加到 HTTP 请求报文中,以 Cookie 为首部字段 ,比如 Cookie : 1df5f36t61b5y5k2d9w7h3h
- 服务器收到这个标识码就可以追踪到客户端的上一次活动。
三.网络安全
在网络通信过程中,由于网络设备,网线光缆,计算机等都有可能是共有的物品,因此在网络上传输一些隐私信息的时候就需要对数据进行保护。一个安全的计算机网络至少应到达下面三个目标:
- 保密性,只有发送方可接收方才能读懂信息的内容,信息的截获者就算获取了信息也无法读懂。
- 端点鉴别,能够识别信息的发送方和接收方的真实身份,确保不是冒充者。
- 信息的完整性,保证信息在传输的过程中没有被篡改。
1.保密性
现在的数据加密技术一般有两种:
- 对称密钥密码体制
- 公钥密码体制
(1)对称密钥加密
又称共享密钥加密,即发送方和接收方都是用同一把密钥对密文进行加密解密,发送方先把密钥发给接收方,接着通过密钥加密数据,最后把密文发送出去,接收方收到密文后就使用前面收到的密钥进行解密。
这种方式显然是有问题的,因为密钥如果被窃取了,后面的密文加密效果就同样失效。
(2)公钥密码体制
对称加密在两方之间使用的是同一把密钥,而公钥密码加密使用的是一对不同的密钥。
- 使用公开密钥加密方式,两个对等方都会有两把密钥,一把是公开的密钥,可以向任何人公开,一把是私有的,不能向外公开。这两把密钥的关系是私有密钥用于解密公开密钥加密的密文。
- 一方通过对方的公开密钥进行加密,然后发送给另一个方。
- 另一方收到密文后就用自己的私有密钥进行解密。
通过这种方式就不存在这对称密钥的不安全问题。但是还是存在着一个问题,就是无法确定密钥是否是对方的公开密钥的问题。实际上这个问题和端点鉴别本质上是一样的,就是确认真实性。
2.端点鉴别
端点鉴别可以分为两种,一种是对于客户端的认证,一种是对于使用者实体的认证,因为就算客户端是真实可信的,但是使用者还是可能存在这是用他人的计算机进行冒充
(1)客户端认证
为了确认通信方,有一种称为证书的手段,可以确认通信方。证书是由值得信任的第三方机构颁发的,用于证明服务器和客户端是实际存在的,而且伪造证书技术十分困难,所以只要持有证书即可判断通信方的真实身份。
对于上述的密钥的问题,对密钥的认证的称为密钥证书。
- 一般服务器会先向认证机构提出身份确认,并对自己的公开密钥做数字签名 (也就是对密钥进行盖章),然后就可以对外公布这个公开密钥,将这个密钥和证书绑定。
- 服务器可以将证书发送给客户端,接到证书的客户端就可以使用证书认证自己持有的共有密钥,(验证密钥和数字签名是否匹配)验证通过就可以确定密钥的真实性,即公开密钥是可以信赖的。(通常发送方会先植入常用的认证机关发布的公开密钥,以免去证书的发送过程)
(2)使用者认证
在 HTTP 中使用了如下几种对用户进行认证的方式:
- BASIC 认证
- DIGEST 认证
- SSL 客户端认证
- FormBase 认证
1.BASIC 认证
BASIC 认证就是使用 Authorization/WWW-Authenticate 首部字段进行认证。
- 客户端发起请求,服务器返回 401 的状态码和 WWW-Authenticate 字段要求认证
- 客户端将账号和密码添加到请求到 Authorization 请求头,发送请求。
- 服务器对信息进行认证,返回成功或者失败。
因为账号和密码是直接在信息中添加的,因此就有泄露的风险。
2.DIGEST 认证
DIGEST 认证不直接发送账号和密码,而是使用质询码。
- 客户端先发送认证请求。
- 服务器返回一端质询码。
- 客户端从质询码计算出响应码后返回。
3.SSL 认证
SSL 认证就是类似于使用客户端认证的方式,服务器凭借客户端的证书进行认证。
4.基于表单认证
客户端会向服务器发送登录信息,按登录的信息结果进行认证,这种方式是通过所密文加密对账号和密码进行保护的,通常使用的认证方式都是属于这种表单认证方式。
3.信息的完整性
对于信息的完整性,通常使用的是 MD5 和 SHA 等散列值校验法,这两种算法都是使用密码散列函数。
散列函数:
散列函数的输入长度可以很长,但是输出长度是固定,并且较短,散列函数的输出叫做散列值,简称散列。
不同的散列值肯定对应步不同的输入,但是不同的输入可能得出相同的散列值
,就是说散列函数的输入和输出是多对一的关系。
因为要找到两个不同的报文使得有相同的散列输出基本不可能实现,因此散列函数是一种单向函数,对于 MD5 ,因为现在已经被证明能够找到一对报文有相同的散列值,所以对于 MD5 进行改进推出 SHA .
通过使用各种鉴别算法,就能提高信息的完整性。
4.安全协议
目前对于网络安全提供安全服务,被广泛使用的有两个协议:
- 安全套接字层 SSL
- 运输层安全 TSL
TSL 是对 SSL 的改进,因此通常将 TSL/SSL 统称为 SSL, SSL 安全服务本质上使用的就是上述三种方法,达到网络通信的安全。
三.HTTPS
对于 HTTP 协议来说,它并没有对数据进行保护,存在网络安全问题:
- 通信使用明文,内容可能被窃听。
- 不验证通信方的身份,因此存在着通信方是冒充者的情况。
- 无法验证报文的完整性,即数据有可能被篡改。
为了解决上述的问题,在 HTTP 的基础上加上网络安全等技术就是 HTTPS .
HTTP + 加密 + 认证 + 完整性保护 = HTTPS
HTTP + SSL = HTTPS
以上两种说法都是说明 HTTPS 在网络通信中已经足够安全,使用 HTTPS 通信的时候不再使用 http:// ,而是使用 https:// ,现在的 Chrome 浏览器就可以识别。
HTTPS 不是一种新的协议,只是对于一些接口使用 SSL 代替。
1.HTTPS 采用的是混合加密
在前面描述过两种加密的方式,第一种速度快但是不安全,第二种安全但是速度慢,因此为了结合两种优点, HTTPS 使用的是两种加密方式混合使用的方式。
- 先使用公开密钥的方式安全的交换共享密钥中使用的密钥。
- 确保交换的密钥是安全的前提下,使用共享密钥进行通信,这样就能共享密钥的安全性,而且提高了通信的速度。
2.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 能够查知报文是否遭到篡改,从而保护报文的完整性。
大致情况如图: