1. HTTP 为啥不安全
网络中的数据是以包的形式在网络模型各层之间进行传递的,HTTP协议位于应用层,TCP/IP协议的上层,而数据报文在这些层之间传递都是没有加密明文传递的。这也就导致了如下问题:
1.1 通信时采用明文(不加密),内容可能被窃听
从上面可以看出,我们作为客户端处于庞大互联网中的一个节点,而在与进行通信时,中间会经历很多个阶段,而每一个阶段报文内容都有可能被窃听!
HTTP协议无法加密数据,所有通信数据都在网络中明文“裸奔”。通过网络的嗅探设备及一些技术手段,就可还原HTTP报文内容。
1.2 无法验证接收报文的完整性,可能已被篡改
无法验证完整性,即意味着接收到的报文可能是缺失的,也意味着接收到的报文可能是错误的,也就是不是我们想要的,如下图:
作为客户端向服务器请求数据,服务器响应的是A内容,客户端接收到的是B内容,但是客户端并不能知道A是否与B相同,因为在传输过程中报文就可能被篡改了。这个过程通常被称为“中间人攻击”。
1.3 HTTP 协议不验证通信方身份,因此可能被伪装

HTTP协议设计的十分简单,并且不验证通信双方,也就意味着,不论是谁发送的请求,只要合法(后台没有限制访问IP和端口号),服务器都会接受。而不确认通信方身份可能会导致如下几个问题:
- 无法确定请求发送至目标的
Web服务器是否是按真实意图返回响应的那台服务器。有可能是已伪装的Web服务器。 - 无法确定响应返回到的客户端是否是按真实意图接收响应的那个客户端。有可能是已伪装的客户端。
- 无法确定正在通信的对方是否具备访问权限。因为某些
Web服务器上保存着重要的信息,只想发给特定用户通信的权限。 - 无法判定请求是来自何方、出自谁手。
- 即使是无意义的请求也会照单全收。无法阻止海量请求下的
DoS攻击(Denial of Service,拒绝服务攻击)。也就是容易遭受攻击。2. HTTPS 实现原理
HTTPS并非是应用层上的一种新协议,HTTPS本质也是基于HTTP协议的,只不过通过一些安全手段来解决上面HTTP存在的问题。它的通用接口部分使用SSL/TLS(TLS是更为安全的升级版SSL)协议代替。以前来说,HTTP协议是应用层协议,直接和下层TCP进行通信,而增加了SSL协议之后,就变成了HTTP先跟SSL通信,再由SSL跟TCP通信,也就是说HTTPS是披着SSL协议外壳的HTTP协议。
SSL是独立于HTTP的协议,所以不光是HTTP协议,其他运行在应用层的SMTP和Telnet等协议均可配合SSL协议使用。可以说SSL是当今世界上应用最为广泛的网络安全技术。

HTTPS=HTTP+ 加密 + 证书 + 完整性保护
2.1 解决内容可能被窃听的问题 —— 加密
大家可能都听说过HTTPS协议之所以是安全的是因为HTTPS协议会对传输的数据进行加密,而加密过程是使用了对称加密+非对称加密混合加密实现。其实HTTPS在内容传输的加密上使用的是对称加密,非对称加密只作用在证书验证阶段。
2.1.1 数据传输阶段 —— 对称密钥加密
对称密钥加密又称为共享密钥加密(Common key crypto system),是在加密和解密阶段使用同一个密钥的方式。这也就意味着通信双方必须都存储一份相同的密钥。没有密钥就无法对密码解密,反过来说,任何人只要持有密钥就能解密了。
以对称密钥加密方式加密时必须将密钥也发给对方,所以在互联网上转发密钥时,如果通信被监听那么密钥也可能落入攻击者之手,从而破解HTTP报文,这样也就失去了加密的意义。
因此,加密的重中之重就是如何能安全的发送密钥不被窃取?
2.1.2 证书验证阶段 —— 非对称密钥加密
公开密钥加密(Public-key cryptography)解决了上述的发送密钥问题。它采用一对非对称的密钥,一把是私有密钥(private key),一把是公开密钥(public key)。私有密钥不能让其他任何人知道,而公开密钥则可以随意发布,任何人都可以获得。
加密过程就是:服务端持有私钥,返回公钥给客户端,客户端使用服务端返回的公钥对发送的信息进行加密处理,服务端收到被自己公钥加密的信息,再使用自己的私钥进行解密。利用这种方式,不需要发送用来解密的私有密钥,也不必担心密钥被攻击者窃听而盗走。
非对称加密的特点是信息传输一对多,服务器只需要维持一个私钥就能够和多个客户端进行加密通信。
2.1.3 HTTPS 采用的 —— 混合加密机制
HTTPS采用的是混合加密,那么既然非对称的公开密钥方式更好,为啥不只采这一种方式呢?
原因是,非对称密钥相比对称密钥加密解密处理起来更为复杂,效率更低。在前端业务交互中,一般来说都是存在大量的HTTP请求的,所以非对称密钥的效率是无法被接受的。此外非对称密钥的场景只在服务端保存私钥,也就是说一对公私钥只能实现单向的加解密,用来确认通信安全以及服务端返回证书。
使用对称密钥的好处是加密解密的效率比较快,使用非对称密钥的好处是可以使得传输的内容不能被破解,因为就算你拦截到了数据,但是没有对应的私钥,也是不能破解内容的(比如说你抢到了一个保险柜,但是没有保险柜的钥匙也不能打开保险柜)。那我们就将对称加密与非对称加密结合起来,充分利用两者各自的优势,在交换密钥环节使用非对称加密方式,之后的建立通信交换报文阶段则使用对称加密方式。
具体做法是:发送密文的一方使用对方的公钥进行加密处理“对称的密钥”,然后对方用自己的私钥解密拿到“对称的密钥”,这样可以确保交换的密钥是安全的前提下,使用对称加密方式进行通信。所以,HTTPS采用对称加密和非对称加密两者并用的混合加密机制。
2.2 解决报文可能遭篡改的问题 —— 数字签名
网络传输过程中需要经过很多中间节点,虽然数据无法被解密,但可能被篡改,那如何校验数据的完整性呢?——校验数字签名。
数字签名是一段由发送者生成的特殊加密校验码,用于传输过程中确认报文的完整性。数字签名的整个过程涉及到两种技术:非对称加密和数字摘要。生成数字摘要的算法通是MD5和SHA这种不可逆算法,将不定长的报文内容提取出定长的数字摘要。
数字签名的整个签名和校验过程分为五步:
- 发送方用摘要算法对报文提取生成数字摘要。
- 使用私钥对摘要进行加密,加密后的摘要作为数字签名附加在报文上,一起发送给接收方。
- 接收方收到报文后,使用相同的摘要算法提取出摘要。
- 再使用公钥对报文的数字签名进行解密。
- 如果解密后的数字签名与提取出得摘要相同,那么就可以证明报文没被篡改,数据是完整的。
2.3 解决通信方身份可能被伪装的问题 —— 证书
上面的过程也存在一个问题,安全的本质是使用密钥来进行数据加密解密。那么如果最本质的密钥都是有问题的,那么安全性就无从谈起,因此,这个密钥必须是通信双方,也就是客户端和服务端都认证通过的才行。这个工作既不能客户端去做,也不能服务端去做,一般来说是交给第三方权威机构 —— 数字证书认证机构(CA,Certificate Authority)。
假设不存在认证机构,任何人都可以制作证书,这带来的安全风险便是经典的“中间人攻击”问题。
“中间人攻击”的具体过程如下:
- 本地请求被劫持(
DNS劫持),所有请求均发送到中间人的服务器,然后伪装成客户端与服务器进行通信。 - 服务器生成证书公钥(服)和私钥(服),返回证书公钥(服)给中间人。
- 中间人收到服务器发来的证书公钥(服)并存储起来备用,同时生成它自己的证书公钥(中)和私钥(中)。
- 中间人返回证书公钥(中)给客户端。
- 客户端生成密钥(客),通过中间人证书公钥(中)对密钥(客)加密后传送给中间人。
- 中间人使用私钥(中)对密钥(客)进行解密,得到密钥(客)并存储起来备用。
- 中间人生成密钥(中),使用第四步得到的证书公钥(服)进行加密传输给服务器。
- 服务器使用私钥(服)解密得到密钥(中),然后凭密钥(中)构造对称加密对传输内容进行加密,传输给中间人。
- 中间人因为有密钥(中),可以通过对称加密算法进行内容解密。然后再使用第七步得到的密钥(客)构造对称加密对传输内容进行加密,传输给客户端。
- 客户端使用密钥(客)对传输内容解密,得到内容。
所以“中间人攻击”的关键是与客户端通信获取客户端的密钥,然后伪装成客户端与服务器进行通信获得内容,最后再用获得的客户端的密钥对内容进行加密返还给客户端。
使用中间人攻击手段,必须要让客户端信任中间人的证书,如果客户端不信任,则这种攻击手段也无法发挥作用。
2.3.1 证书验证流程

认证机关的公开密钥必须安全地转交给客户端。使用通信方式时,如何安全转交是一件很困难的事,因此,多数浏览器开发商发布版本时,会事先在内部植入常用认证机关的公开密钥,如下图所示(火狐浏览器内置证书):
数字证书认证机构的业务流程大概如下:
- 服务器的运营人员向第三方机构
CA提交公钥、组织信息、个人信息(域名)等信息并申请认证。 CA通过线上、线下等多种手段验证申请者提供信息的真实性,如组织是否存在、企业是否合法,是否拥有域名的所有权等。- 如信息审核通过,
CA会向申请者颁发认证文件——证书。证书包含以下信息:申请者公钥、申请者的组织信息和个人信息、颁发机构CA的信息、有效期、证书序列号等信息的明文,同时包含一个数字签名。其中数字签名的产生算法:首先,使用散列函数计算公开的明文信息的信息摘要,然后,采用CA的私钥对信息摘要进行加密,密文即数字签名。 - 客户端向服务端发出请求时,服务端返回公钥证书文件给客户端。
- 接下来客户端验证证书的合法性:
- 首先验证域名、有效期、所有者等信息是否正确。证书上都有包含这些信息,比较容易完成验证;
- 判断证书来源是否合法。每份签发证书都可以根据验证链查找到对应的根证书,操作系统、浏览器会在本地存储权威机构的根证书,利用本地根证书可以对对应机构签发证书完成来源验证;
- 验证证书的真实性。客户端使用内置的
CA的公开密钥,向CA验证公钥证书上的数字签名,以确认服务器的公开密钥的真实性; - 判断证书是否被篡改。如果服务器的公开密钥真实,客户端
Client会读取证书中的相关的明文信息,采用相同的散列函数计算得到信息摘要,使用内置信任CA的公开密钥对证书中的数字签名进行解密,对比证书的信息摘要,如果一致,则可以确认证书的完整性。 - 校验证书是否被吊销。通过
CRL(Certificate Revocation List,证书注销列表)或OCSP(Online Certificate Status Protocol,在线证书状态协议)来实现。
记住,不要随便安装受信任证书,否则
HTTPS也帮不了你。我们平时为了调试HTTPS请求,使用Charles进行抓包,也需要在手机端导入一个证书,让用户选择信任安装,目的就是将Charles作为中间人代理,如果没有用户信任安装证书的过程,也同样无法解析HTTPS的请求包。
3. HTTPS 通信完整过程

- 证书验证阶段(非对称加密)
- 浏览器发起
HTTPS请求 - 服务端返回
HTTPS证书 - 客户端验证证书是否合法,如果不合法则提示告警
- 浏览器发起
- 数据传输阶段(对称加密)
- 当证书验证合法后,在本地生成随机数
- 通过公钥加密随机数,并把加密后的随机数传输到服务端
- 服务端通过私钥对随机数进行解密
- 服务端通过客户端传入的随机数构造对称加密算法,对返回结果内容进行加密后传输
4. Q&A 形式进行全文总结
4.1 HTTP 与 HTTPS 的区别
HTTP是明文传输协议,HTTPS协议是由SSL + HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。HTTPS比HTTP更加安全,对搜索引擎更友好,利于SEO,谷歌、百度优先索引HTTPS网页。HTTPS需要用到SSL证书,而HTTP不用。HTTPS标准端口443,HTTP标准端口80。HTTPS基于传输层,HTTP基于应用层。HTTPS在浏览器显示绿色安全锁,HTTP没有显示。
4.2 HTTP 为什么不安全
- 报文是明文的,未加密
- 无法验证报文完整性,传输过程中可能会被篡改
- 不验证通信双方身份,可能被伪装
4.3 HTTPS 为什么安全
因为HTTPS保证了传输安全,防止传输过程被监听、防止数据被窃取,可以确认网站的真实性。
4.4 HTTPS 的传输过程是怎样的?
客户端发起HTTPS请求,服务端返回证书,客户端对证书进行验证,验证通过后本地生成用于改造对称加密算法的随机数,通过证书中的公钥对随机数进行加密传输到服务端,服务端接收后通过私钥解密得到随机数,之后的数据交互通过对称加密算法进行加解密。
4.5 本地随机数被窃取怎么办?
HTTPS并不包含对随机数的安全保证,HTTPS保证的只是传输过程安全,而随机数存储于本地,本地的安全属于另一安全范畴,应对的措施有安装杀毒软件、反木马、浏览器升级修复漏洞等。
4.6 为什么需要证书?
防止中间人攻击,同时可以为网站提供身份证明。
4.7 使用 HTTPS 会被抓包吗?
会被抓包,只不过内容是被加密过的,HTTPS只防止用户在不知情的情况下通信被监听,用户是可以主动对证书进行授信的,如果用户授信通过,那么代理软件是可以对传输内容进行解密的。
4.8 为何不所有网站都使用 HTTPS ?
- 速度会慢
2~100倍
HTTPS慢其实是慢在SSL协议通信商上,因为SSL协议要进行加密解密处理,会占用CPU和网络资源,总体上会慢一些。
CA证书一般来说不免费
申请CA证书是需要花钱的,当然,现在很多手段可以申请到免费的 HTTPS证书,但是大部分权威的还是收费的。所以大部分小型个人开发者,使用的应该都是HTTP协议。
4.9 HTTP2.0 与 HTTP1.x 相比的新特性
- 新的二进制格式(
Binary Format):HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。 - 多路复用(
MultiPlexing):具体见下一个问题。 - header压缩:
HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,既避免了重复header的传输,又减小了需要传输的大小。 - 服务端推送(
Server Push):服务端推送是一种在客户端请求之前发送数据的机制。在HTTP/2中,服务器可以对客户端的一个请求发送多个响应。如果服务端接收到客户端(主页)主请求,能够“预测”主请求的依赖资源(js、css等),在响应主请求的同时,主动并发推送依赖资源至客户端。客户端解析主请求响应后,可以”无延时”从本地缓存获取依赖资源,减少访问延时,提高访问体验,也加大了链路的并发能力。Server Push正是基于此原理来提高网络体验。
4.10 HTTP2.0 的多路复用和 HTTP1.1 中的长连接复用有什么区别?
HTTP/1.0:每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。为了解决这个问题,需要使用Connection: keep-alive这个字段。HTTP/1.1:该版本引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。还引入了管道(pipelining)机制,即在一个TCP连接中,多个请求(Chrome下一般是6个)排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的HOLB(Head of line blocking,线头阻塞)。HTTP/2.0:在一个TCP连接中允许发起多重的请求-响应消息,即多个请求可同时在一个TCP连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行。

