参考文档
阮一峰的博客:
https://www.ruanyifeng.com/blog/2016/08/http.html
https://www.runoob.com/w3cnote/http-vs-https.html
http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
http://www.ruanyifeng.com/blog/2016/08/migrate-from-http-to-https.html
http的缓存机制
https://www.cnblogs.com/chenqf/p/6386163.html
Android中使用https
https://juejin.cn/post/6844903470584037383
http
tcp协议的三次握手
要先回忆下tcp协议的三次握手过程, 因为无论是http还是https, 都需要建立在tcp建立连接之后.
形象一点表述就是
具体里面的交互, syn, ack字段什么, 我觉得不重要, 到时候查资料就可以了, 关键是要理解这个过程
http协议简史
文档 https://www.ruanyifeng.com/blog/2016/08/http.html
- 现在最流行的版本是http/1.1版本, 之前有发布过http/0.9 http/1.0版本. 最新的版本是http/2版本.
- http/0.9 只有一个GET命令, 服务端只能回复一个html格式的回复
- http/1.0 引入POST与HEAD命令, 要求必须有头信息, 增加了状态码, 多字符集, 多部分发送(multi-part type), 权限, 缓存, 内容编码等
- http/1.0 有一个最大的缺点是, 每个TCP连接只能发送一次请求, 发送请求完毕, 连接就关闭, 如果还要请求资源, 就必须再重新建立一个连接. 所以成本很高
- http/1.1修改了上述问题, 引入了持久连接的概念, TCP连接默认不关闭, 可以被多个请求复用. 当客户端和服务端发现对方一段时间没有活动, 就主动关闭连接. 对于同一域名, 大多数浏览器允许同时建立6个持久连接.
- http/1.1版本引入了管道机制(pipelinling), 客户端可以同时发送多个请求, 但是服务端必须要按照顺序来回应请求, 那这个时候就会面临一个问题, 我怎么知道这个数据包属于哪次http请求.http/1.1有两种解决方案.
- 定义一个Content-Length字段, 声明本次回应的长度.
- 采用分块传输, Transfer-Encoding: chunked. 每次http内容发送完毕之后, 发送一个Content-Length:0的数据包, 标明这次已经请求已经发送完毕.
- (但是以上就能解决所有的问题吗? 因为客户端是可以同时发送多个请求的, 那么如果后发的请求先到服务端了怎么办? 这种顺序怎么保证? 目前没有看到资料, 可能要深入到http和tcp协议里面看下
- http/1.1有一个缺点, 就是服务端是顺序处理的, 如果一个请求处理的慢了, 就会形成堵塞. 为了解决这个问题, 引入了http/2
- http/2是2015年才发布的, 采用了二进制协议, 即头信息和数据体都要求是二进制, 并且统称为"帧",
- http/2中, 采用多工机制, 即客户端和服务端都可以同时发送多个请求, 那么怎么区分每个回复的数据包呢. 当然是引入一个数据流的id…
- 我还是不太明白, http/2中怎么保证请求和回复一一对应, 当然, http/1.1中也有这个问题, 待查阅资料.
http协议那些头
- Connection: keep-alive\close http/1.1中默认为keep-alive, 表示不关闭TCP链接, 当需要关闭的时候, 可以发一个close
- Content-Encoding: gzip\compress\deflate, 数据的压缩方法
- Content-Type: text/html; charset=utf-8 . 数据格式
- Accept: / 客户端声明自己支持哪些数据格式
http协议的缓存机制
这一片文章写得太好了, 深入浅出 https://www.cnblogs.com/chenqf/p/6386163.html
总结下这篇文章中的知识点
- 客户端(浏览器)是有一个缓存数据库的, 根据一定策略, 要么从缓存数据库中取数据, 要么从服务端取数据, 要么拿了客户端数据去和服务端的比较
- 主要是通过Cache-Control字段来标明缓存策略的, 取值如下
- private 客户端可以缓存
- public 客户端和代理服务器都可以缓存
- max-age=xxx: 缓存的内容会在xxx秒之后失效
- no-cache: 使用对比缓存
- no-store: 不使用缓存.
- 对比缓存 客户端本次存储缓存, 下次请求时, 带上缓存标识, 服务端如果发现没有更新, 就直接返回304和头部分, 通知客户端你用缓存就行, 我不给你新数据了, 缓存标识分为下面几类
- Last-Modified/If-Modified-Since. 服务器通过Last-Modified字段来告诉客户端资源的最后修改时间, 下次客户端请求时, 会通过If-Modified-Since把这个时间带上, 服务端用来比较
- Etag/If-None-Match , Etag是服务端返回的唯一表示, If-None-Match就是要带上这个标识
https
https协议的握手过程
参考文档 http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html
http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html
https协议其实就是http+TLS协议, 在交互之前, 除了TCP的握手之外, 要完成TLS协议的握手, 具体规则如下
握手分为四个阶段
1. 客户端向服务端发出加密通信的请求, 也被叫做ClientHello请求
客户端发送以下信息
- 支持的协议版本
- 一个客户端发出的随机数, 稍后用于生成"对话秘钥"
- 支持的加密方法, 比如说RSA公钥加密
- 支持的压缩方法
2. 服务器收到客户端请求之后发出回应, 也叫做ServerHello
该回应包含以下信息
- 确定使用的加密通信版本
- 一个服务端生成的随机数, 稍后用于生成"对话秘钥"
- 确认使用的加密方法, 比如说RSA公钥加密
- 服务器证书, 即CA证书
需要注意的是
- 上述CA证书中只包含公钥
- 如果服务器需要确认客户端的身份, 还会包含一项请求, 要求客户端提供"客户端证书", 比如, 金融机构往往只允许认证客户端接入自己的网络, 就会向客户端要求提供USB秘钥, 里面汉堡一张客户端的证书.
3. 客户端回应
客户端收到服务器的回应之后, 会首先验证下服务器的根证书, 如果证书不是可信机构颁布的, 或者证书中的域名与实际域名不一致, 或者证书已经过期等等, 就会给访问者一个提示, 提示用户是否继续访问(如之前12306的证书就是自签发的证书, 浏览器不能识别)
如果没有问题, 客户端就会从服务端的证书中取出公钥, 然后, 向服务端发送以下信息
- 一个随机数, 该随机数用CA证书中的公钥加密, 防止被窃听
- 编码改变通知, 表示随后的信息都将用双方商定的加密方法和秘钥发送
- 客户端握手结束通知.
其中, 上述中的随机数, 是整个握手阶段出现的第三个随机数, 通过之前的三个随机数一起生成"会话秘钥"
4. 服务端最后的响应
服务端收到客户端的第三个请求后, 技术生成会话秘钥, 然后向客户端发送以下信息
- 编码改变通知, 表示税后的信息都将用双方商定的加密方法和秘钥发送
- 服务器握手结束通知, 表示服务器的握手阶段已经结束
接下来, 双方进入到加密通信阶段, 完全使用普通的http协议. 只不过这些都是用会话密码对称加密内容
上面的整个流程看完之后, 可能还是会有一些疑问, 下面是我的一些理解(不一定正确, 欢迎指正)
Q1: 为什么要使用会话秘钥
加密通信阶段使用会话秘钥, 可以加快加密的速度, 这是个是对应加密的. 而握手阶段采用的公钥加密, 属于不对称加密, 比较耗费时间
Q2: 为什么要用CA证书, 为什么可以防备中间人攻击
客户端预制了一部分证书, 所以CA证书必须要由特定结构来进行签发, 校验域名等信息, 所以可以防备中间人攻击
Q3: 整个流程看下来, 其实基本上主要是客户端校验服务端的身份
http与https协议的区别
概括一下区别
- HTTP是明文传输的, 数据都是未加密的, 安全性较差. HTTPS数据传输过程是加密的, 安全性较好
- 使用HTTPS协议需要用到CA证书, 一般免费证书比较少, 因而需要一定的费用.
- HTTP页面响应速度比HTTPS较快(理论上), 因为HTTPS需要建立TLS握手的过程
- 使用的默认端口不一样, http是80端口, https默认是443端口
- https是构建在ssl/tls之上的http协议, 所以, 要比http更耗费服务器资源.
上述http页面的响应速度比https快, 这个如果要细分, 是可以分情况的
参看这篇文章
https协议的七个误解
第一次请求, https肯定比http要慢
之后请求, 因为连接已经建立起来了, 所以两者相差无几, https略微多一丁点
部分情况下, https比http要快, 因为网关可能会截取分析网络通信, https通信因为加密了, 网关无法分析, 可能就直接放行了
CA证书
怎么理解CA证书
参看这篇文章吧 https://www.cnblogs.com/handsomeBoys/p/6556336.html
直接把内容贴过来
看过一些博客,写的比较形象具体。
◇ 普通的介绍信
想必大伙儿都听说过介绍信的例子吧?假设 A 公司的张三先生要到 B 公司去拜访,但是 B 公司的所有人都不认识他,他咋办捏?常用的办法是带公司开的一张介绍信,在信中说:兹有张三先生前往贵公司办理业务,请给予接洽…云云。然后在信上敲上A公司的公章。
张三先生到了 B 公司后,把介绍信递给 B 公司的前台李四小姐。李小姐一看介绍信上有 A 公司的公章,而且 A 公司是经常和 B 公司有业务往来的,这位李小姐就相信张先生不是歹人了。
这里,A公司就是CA证书
◇ 引入中介机构的介绍信
好,回到刚才的话题。如果和 B 公司有业务往来的公司很多,每个公司的公章都不同,那前台就要懂得分辨各种公章,非常滴麻烦。所以,有某个中介公司 C,发现了这个商机。C公司专门开设了一项“代理公章”的业务。
今后,A 公司的业务员去 B 公司,需要带2个介绍信:
介绍信1
含有 C 公司的公章及 A 公司的公章。并且特地注明:C 公司信任 A 公司。
介绍信2
仅含有 A 公司的公章,然后写上:兹有张三先生前往贵公司办理业务,请给予接洽…云云。
某些不开窍的同学会问了,这样不是增加麻烦了吗?有啥好处捏?
主要的好处在于,对于接待公司的前台,就不需要记住各个公司的公章分别是啥样子的;他/她只要记住中介公司 C 的公章即可。当他/她拿到两份介绍信之后,先对介绍信1的 C 公章,验明正身;确认无误之后,再比对介绍信1和介绍信2的两个 A 公章是否一致。如果是一样的,那就可以证明介绍信2是可以信任的了。
感觉CA证书有点像一个信任链. A信任B, B信任C, B信任C. 作为客户端, 我只需要保留A机构的信息就可以了. CA证书体现出信任链关系, 让客户端知道C最终是可以信任的
Android中的http与https
通常的使用姿势
参看文档
android官方网络配置
通常来说, 不要什么额外的配置, 直接默认使用https就好
但是有人希望使用http, 在Android P版本(28)之后, 按照官方的说法, 是限制客户端使用http了. 除非做以下修改
定义一个network_security_config.xml文件, 内容如下
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
AndroidManfiest的application中加上一下配置
<application
...
android:networkSecurityConfig="@xml/network_security_config"
...
/>
这里要澄清的一点是, Google官方是说Android P版本之后默认不让使用http了, 但是亲测之后发现可以. 走读了下源码, 该部分是有系统的DEFAULT_CLEARTEXT_TRAFFIC_PERMITTED字段控制的, true表示允许使用http. 目前Android源码里, 这个值是true.
所以没有明白这个逻辑, 可能google只是"吓唬"我们的? 为了保险起见, 还是加上上面的network_security_config配置吧. 不多