阿里-测试开发面经(十一)
点击蓝字关注我们,获取更多面经
当我们使用 HTTP 协议时,传输的数据是不安全的,因为所有在客户端和服务端往来的数据都是明文:
第三方可以获取到真实数据
第三方可以篡改数据
第三方可以冒充服务端或客户端
为了解决这些问题,需要在 HTTP 协议中加入一个安全机制,由此并产生了 HTTPS,我们可以认为 HTTPS = HTTP + TLS/SSL。TLS/SSL 的引入解决了安全问题,而上层应用协议还是 HTTP。
###历史
SSL(Secure Sockets Layer)中文称作“安全套接层”,TLS(Transport Layer Security),中文称作“传输层安全协议”。
1994 年,网景(NetScape)公司设计了 SSL 1.0
1995 年,SSL 2.0,存在严重漏洞
1996 年,SSL 3.0,得到大规模应用
1999 年,IETF 对 SSL 进行标准化,发布了 TLS 1.0
2006 年和 2008 年,TLS 进行了两次升级,分别为 TLS 1.1 和 TLS 1.2
在应用层,我们习惯将两者并称 TLS/SSL,因为它们设计大致相同,我们可以认为它们是同一个事物在不同历史阶段的名称。
HTTPS 可以认为是 HTTP + TLS/SSL,所以我们只需要了解 TLS/SSL 原理即可。在进入原理之前,我们需要了解两个基础概念:数字证书、证书授权中心。
###证书与授权
数字证书(Digital Certificate)是用来证明公钥(非对称密钥算法中用于加密的密钥)所有者身份的。我们人人都可以自己生成一个公钥,但是这个公钥是否能代表是你的,这个认证的过程需要一个权威机构执行,这个机构就是证书授权中心。
证书授权中心(Certificate Authority)负责证书颁发。CA 是行业内信得过的组织机构,它具有权威性,由它颁发的证书大家都相信是可靠的。
###TLS/SSL 协议
由客户端发起握手,告诉服务器客户端支持的 TLS/SSL 版本、数据加密算法、以及一个随机数
1.1. 服务端确认支持这个版本的 TLS/SSL、加密算法,并生成一个随机数
1.2. 服务端将证书(带公钥)、服务端生成的随机数返回给客户端
客户端检查证书是否可信(和已有的 CA 列表对比,看是否是已有 CA 颁发的证书),并生成第三个随机数 PreMasterSecret
客户端使用证书带的公钥将 PreMasterSecret 进行加密,并通过之前交换的数据生成一个 Hash 值,发送给服务端,请求变更编码
3.1. 服务端校验 Hash(确认不是假的客户端),并使用自己证书的私钥解密出 PreMasterSecret
3.2. 服务端根据之前的随机数和约定的加密算法,生成用于加密后续传输数据的会话密钥 SessionSecret
3.3. 服务端根据之前交换的数据生成一个 Hash 值,发送给客户端,确认开始变更编码
客户端校验 Hash (确认不是假的服务端),并生成会话密钥
客户端使用会话密钥加密数据,并发送给服务端
5.1. 服务端使用会话密钥解密数据,执行业务逻辑后产生数据
5.2. 服务端使用会话密钥加密数据,返回给客户端
客户端使用会话密钥解密数据,完成一次和服务端的数据交换
在这个过程中,有几个关键点:
前两次的随机数(客户端随机数、服务端随机数)是明文传输的
非对称密钥算法只被使用了一次,即客户端使用证书公钥加密 PreMasterSecret,服务端使用证书私钥解密出 PreMasterSecret
应用数据的传输使用的是对称密钥算法,客户端/服务端都使用会话密钥进行加/解密
在握手阶段,安全与否的关键在于 PreMasterSecret 是否能够被破解,虽然理论上通过 RSA 算法加密是比较安全的,但还是有破解的可能性。最安全的做法是不发送 PreMasterSecret,而是根据一系列参数由客户端和服务端分别计算出 PreMasterSecret,这个算法就是迪菲-赫尔曼密钥交换。
另外,TLS/SSL 不只适用于 HTTP 的安全问题,它也可以和其他应用层协议搭配使用。
###应用
通过上述介绍,我们得知使用 SSL/TLS 需要做如下准备:
数字证书:可以找权威的证书授权中心颁发证书(有付费的,也有免费的),也可以自己做 CA,然后自己给自己颁发证书
服务端使用证书,比如配置 NGINX 来使用
客户端使用 SSL/TLS 协议和服务端进行通讯,如果是自己的 CA 颁发的证书,还需要在客户端导入 CA 的根证书
下面我们针对自建 CA 做一个完整的示例(证书相关使用 Linux 的 openssl 命令,客户端、服务端使用 Golang)。
####建立 CA
生成 CA 私钥:openssl genrsa -out ca.key 2048
生成 CA 根证书:openssl req -new -x509 -days 3650-key ca.key -out ca.crt
####颁发证书
生成证书私钥:openssl genrsa -out auto.pem 1024
生成证书公钥:openssl rsa -in auto.pem -out auto.key
生成签名请求:openssl req -new -key auto.pem -out auto.csr,其中的 Common Name 一定要填写客户端访问时的域名,并且不能是 IP
CA 签名(颁发)证书:openssl x509 -req -sha256 -in auto.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out auto.crt
最终我们需要的就是公钥 auto.key 以及证书 auto.crt。
####服务端使用证书
1http.ListenAndServeTLS(Auto.Server, "auto.crt", "auto.key", nil)
####客户端发起请求
这里假设客户端已经获得了服务端的证书。
getClient 根据传入的 url 实参中协议部分返回适当的 HTTP 客户端.
其中载入了 CA 证书,原因就是因为我们自建的 CA 不在系统自带的“受信任的根证书颁发机构”中。
1.scoped_ptr:这是最常用的智能指针,当你new一块内存后,把内存地址交给scoped_ptr管理,这样就不用显式调用delete了,当离开作用于后,该内存会被自动释放,如
int* p = new int;
scoped_ptr<int> scoped_int_ptr(p);
注意:无须再delete p;这样会double free。另外一个重要的点是:scoped_ptr不允许传递指针,即他的拷贝构造和赋值函数都是private的,不允许调用,所以你不能写如下代码
scoped_ptr<int> scoped_int_ptr2 = scoped_int_ptr; // 不允许
2.auto_ptr:它和scoped_ptr用法基本是一致的,但是它允许指针传递,拷贝构造和赋值函数允许调用,故名思意,当发生赋值时,原对象的指针会转移给新对象,这时原对象的指针就为NULL了,不能再调用。所以,对指针要把握好,使用应谨慎。
3.shared_ptr:scoped_ptr一样包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针 ,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时才删除被包装的动态分配的对象。但是,shared_ptr注意不要有循环引用,否则会出现内存泄漏。例如:A和B对象互相引用,它们的引用计数都是1,当出了作用域之后,二者不能自动释放,出现了内存泄漏。
4.weak_ptr:是一种智能指针,它对被 std::shared_ptr 管理的对象存在非拥有性(“弱”)引用。在访问所引用的对象前必须先转换为 std::shared_ptr。
std::weak_ptr 用来表达临时所有权的概念:当某个对象只有存在时才需要被访问,而且随时可能被他人删除时,可以使用std::weak_ptr 来跟踪该对象。需要获得临时所有权时,则将其转换为 std::shared_ptr,此时如果原来的std::shared_ptr 被销毁,则该对象的生命期将被延长至这个临时的 std::shared_ptr 同样被销毁为止。
更多面经
扫描二维码
获取更多面经
扶摇就业