Open MicroKibaco opened 4 years ago
万物互联,每一天我们都离不开网络,对于程序员来说网络是基础,我们怎么巩固这方面的基础呢?需要阅读大量的书籍,学好网络我们首先要对那四层协议要有清晰的认知,然后需要掌握一些基本的抓包和反抓包策阅,当然常用的加解密其实也是需要掌握的,好了话不多说,就让我们打开网络之旅吧
为什么要网络分层呢?
其实因为网络的不稳定性
从广义来说: 网络其实是可以分为七层,但是我们这里学习四层就行了:
HTTP/1.0 数据时,每次都需要重新建立连接,增加延迟。
HTTP 1.0:下个请求必须在前一个请求返回后才能发出,request-response对按序发生。显然,如果某个请求长时间没有返回,那么接下来的请求就全部阻塞了。
HTTP 1.1:尝试使用 pipeling 来解决,即浏览器可以一次性发出多个请求(同个域名,同一条 TCP 链接)。但 pipeling 要求返回是按序的,那么前一个请求如果很耗时(比如处理大图片),那么后面的请求即使服务器已经处理完,仍会等待前面的请求处理完才开始按序返回。所以,pipeling 只部分解决了 HOLB。
HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码
解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。
提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用 prefetch。
QUIC,基于UDP
HTTP 消息的 metadata
指定 Body 的长度(字节)。
指定 Body 的类型
HTTP 传输过程中的“中转站”,可以实现缓存加速、负载均衡等功能。
在客户端或中间⽹络节点缓存数据,降低从服务器取数据的频率,以提高⽹网络性能。
MIME 类型
如果Cookie 仅存在 内存里,那么 App 关闭后,所有的 Cookie 都会消失;我们期望的是下次打开app的时候期望的是依然自动登录进入主页面,这就需要我们对Cookie进行文件级别的持久化。但是,Okhttp.cookie 有个很坑的地方;他没有实现Serivalziable,无法序列化,所以我们只能自己实现序列化
在不设置Cookie的时候,OKHttp默认是没有Cookie的,所以我们需要自定义CookieJar的时候,从拿到CookieJar的Cookie然后进行加载
而获取请求的时候,还是在HttpEngine,使用saveFromResponse方法将erver的Cookie存储本地
重点在于: Cookie的校验和存储机制,首先我们得专门设置一个负责管理Cookie的类.这个类显然不是CookieJar的实现类,我们专门设置了一个CookieMannanger,有二级存储功能,即文件存储和内存存储,如果app关闭那么内存存储就会清空,而用到的Cookie都会存到本地文件里面;app启动则从文件里面加载Cookie
服务端通过 Session 来得知连接的 客户端,因此需要一套okHttp 和 Cookie 共有的一套机制,就可以实现在H5页面与原生app同步登陆,通过阅读源码知道 OKHttp 是通过 cookieJar 来设置 Cookie 的,而在 OKhttpClient 的 Builder 方法中,默认的CookieJar是一个空对象,没有设置任何Cookie
所以我们只需要手动获取webView的Cookie并设置在 okHttp的 CookieJar 上即可实现 Cookie 的 共享。webview的引擎为webkit,在webkit是有CookieManaager 对 Cookie 进行管理的
再创建okhttpclient工具类中自定义的cookieJar
为什么 OAuth 要引⼊ Authorization code,并需要申请授权的第三⽅将 Authorization code 发送回⾃⼰的服务器,再从服务器来获取 access token,⽽不是直接返回 access token ?这样复杂的流程意义何在?
为了安全。OAuth 不强制授权流程必须使⽤ HTTPS,因此需要保证当通信路径中存在窃听者时,依然具有⾜够⾼的安全性。
access_token 有失效时间,在它失效后,调⽤ refresh token 接⼝,传⼊ refresh_token 来获取新的 access_token。
安全。当 access_token 失窃,由于它有失效时间,因此坏⼈只有较短的时间来「做坏事」;同时,由于(在标准的 OAuth2 流程中)refresh token 永远只存在与第三⽅服务的服务器中,因此 refresh token ⼏乎没有失窃的⻛险。
数字证书是 HTTPS 实现 安全传输的基础,它是由权威的CA机构颁发,证书的主要内容有: 公钥,证书颁发机构,证书持有者,证书有效期,签名算法,指纹及指纹算法
可以看到公钥是一串很长的2048.bits的字符串,同时也看到使用者额内容包括了一些网站,后面会跟随颁发者,有效期,签名算法等等,当然还有指纹和指纹算法等等
签名在证书后面加一段字符串,可以证明该信息没有被修改过,CA机构将证书的指纹和指纹算法通过私钥加密就是证书签名了
SSL/TLS 是信息安全领域中的权威标准,采用多种先进的加密技术保证通信安全
在客户端和服务器之间协商出⼀套对称密钥,每次发送信息之前将内容加密,收到之后解密,达到内容的加密传输
尽量采用 TLS1.3,它大幅度简化了握手的过程,完全握手只要 1-RTT,而且更加安全
机密性
完整性
身份认证
不可否认
四次挥手
TCP的连接的拆除需要发送四个包
什么是TCP连接?
通信双⽅方建立确认「可以通信」,不会将对方的消息丢弃,即为「建立连接」
主机A会发送一个报文段(序列号seq=p,标志位FIN=1),然后进入FIN-WAIT-1状态,发送了标志位FIN=1之后,表示我要关闭这个连接,后续将不会再有数据传输过来,但是这时候主机A还是可以收到主机B发送过来的数据;
主机B接受到主机A发送的FIN报文段,会发送一个确认报文段,标志位ACK=1,确认序列号ack=p+1,然后就进入CLOSE-WAIT状态,这个过程表示接受到关闭方发送的关闭请求了。
当主机B的数据都发送完毕后,就会想主机A发送释放连接的报文,主机B发送FIN报文段,标志位FIN=1,序列号seq=q,确认序列号p+1,标志位ACK=1,然后就进入LAST-ACK状态;
主机A接收到关闭报文段后,会发出确认报文段,标志位ACK=1,确认序列号ack=q+1,序列号seq=u+1,然后进入TIME-WAIT状态,此时TCP连接还没有释放,会等待2∗MSL(最长报文段寿命)的时间后,才会进入CLOSED状态;
连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息
为什么要建立长连接
因为移动⽹络并不在 Internet 中,⽽是在运营商的内网,并不具有真正的公网 IP,因此当某个 TCP 连接在⼀段时间不通信之后,⽹关会出于网络性能考虑而关闭这条 TCP 连接和公网的连接通道,导致这个TCP 端口不再能收到外部通信消息,即 TCP 连接被动关闭。
长连接实现⽅式
⼼跳。即在一定间隔时间内,使用 TCP 连接发送超短无意义消息来让网关不能将自己定义为「空闲连接」,从⽽防止网关将自己的连接关闭。
TCP报文格式
万物互联,每一天我们都离不开网络,对于程序员来说网络是基础,我们怎么巩固这方面的基础呢?需要阅读大量的书籍,学好网络我们首先要对那四层协议要有清晰的认知,然后需要掌握一些基本的抓包和反抓包策阅,当然常用的加解密其实也是需要掌握的,好了话不多说,就让我们打开网络之旅吧
一. 网络分层
为什么要网络分层呢?
从广义来说: 网络其实是可以分为七层,但是我们这里学习四层就行了:
1.1 Application Layer 应用层
1.2 HTTP
1.2.1 HTTP版本
1.2.1.1 HTTP/1
A. 连接无法复用
HTTP/1.0 数据时,每次都需要重新建立连接,增加延迟。
B. HOLB(队头阻塞)
HTTP 1.0:下个请求必须在前一个请求返回后才能发出,request-response对按序发生。显然,如果某个请求长时间没有返回,那么接下来的请求就全部阻塞了。
HTTP 1.1:尝试使用 pipeling 来解决,即浏览器可以一次性发出多个请求(同个域名,同一条 TCP 链接)。但 pipeling 要求返回是按序的,那么前一个请求如果很耗时(比如处理大图片),那么后面的请求即使服务器已经处理完,仍会等待前面的请求处理完才开始按序返回。所以,pipeling 只部分解决了 HOLB。
1.2.1.2 HTTP/2
1.2.1.2.1 二进制传输
HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码
1.2.1.2.2 多路复用
多路复用解决痛点
解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。
多路复用特性
多路复用优点
1.2.1.2.3 Header压缩
1.2.1.2.4 缓存push
提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用 prefetch。
1.2.1.3 HTTP/3
QUIC,基于UDP
1.2.2 HTTP定义
1.2.3 HTTP 的 Header
1.2.3.1 Header 的作用
HTTP 消息的 metadata
1.2.3.2 Header
1.2.3.3 Host
1.2.3.3.1 Content-Length
指定 Body 的长度(字节)。
1.2.3.3.2 Content-Type
1.2.3.3.3 Content-Type概念
指定 Body 的类型
1.2.3.3.4 Content-Type分类
客户端能接受的数据类型。如 text/html
客户端接受的字符集。如 utf-8
客户端接受的压缩编码类型。如 gzip
压缩类型。如 gzip
1.2.4 HTTP 状态码
临时性消息。如:100 (继续发送)、101(正在切换协议)
成功。最典型的是 200(OK)、201(创建成功)
重定向。如 301(永久移动)、302(暂时移动)、304(内容未改变)
客户端错误。如 400(客户端请求错误)、401(认证失败)、403(被禁止)、404(找不到内容)
服务器错误。如 500(服务器器内部错误)
1.2.5 HTTP 代理
HTTP 传输过程中的“中转站”,可以实现缓存加速、负载均衡等功能。
1.2.6 HTTP Cache-Control
1.2.6.1 Cache-Control作⽤
在客户端或中间⽹络节点缓存数据,降低从服务器取数据的频率,以提高⽹网络性能。
1.2.6.2 Cache-Control字段属性
1.2.6.3 验证资源是否失效需要使用“条件请求”
1.2.6.4 验证资源是否被修改
1.2.6.5 浏览器刷新数据的方式
1.2.7 Http如何传输大文件
1.2.7.1 数据压缩
1.2.7.2 分块传输
1.2.7.3 多段数据
MIME 类型
1.2.8 登录授权
1.2.8.1 Cookie
1.2.8.1.1 Cookie 工作机制
1.2.8.1.2 如何实现一个CookieMannager?
1.2.8.1.3 Cookie持久化存储
如果Cookie 仅存在 内存里,那么 App 关闭后,所有的 Cookie 都会消失;我们期望的是下次打开app的时候期望的是依然自动登录进入主页面,这就需要我们对Cookie进行文件级别的持久化。但是,Okhttp.cookie 有个很坑的地方;他没有实现Serivalziable,无法序列化,所以我们只能自己实现序列化
1.2.8.1.4 OKHttp的Cookie支持及调用机制
在不设置Cookie的时候,OKHttp默认是没有Cookie的,所以我们需要自定义CookieJar的时候,从拿到CookieJar的Cookie然后进行加载
而获取请求的时候,还是在HttpEngine,使用saveFromResponse方法将erver的Cookie存储本地
重点在于: Cookie的校验和存储机制,首先我们得专门设置一个负责管理Cookie的类.这个类显然不是CookieJar的实现类,我们专门设置了一个CookieMannanger,有二级存储功能,即文件存储和内存存储,如果app关闭那么内存存储就会清空,而用到的Cookie都会存到本地文件里面;app启动则从文件里面加载Cookie
1.2.8.1.5 webview 和 OkHttp 实现 Session共享
服务端通过 Session 来得知连接的 客户端,因此需要一套okHttp 和 Cookie 共有的一套机制,就可以实现在H5页面与原生app同步登陆,通过阅读源码知道 OKHttp 是通过 cookieJar 来设置 Cookie 的,而在 OKhttpClient 的 Builder 方法中,默认的CookieJar是一个空对象,没有设置任何Cookie
所以我们只需要手动获取webView的Cookie并设置在 okHttp的 CookieJar 上即可实现 Cookie 的 共享。webview的引擎为webkit,在webkit是有CookieManaager 对 Cookie 进行管理的
再创建okhttpclient工具类中自定义的cookieJar
1.2.8.1.6 Cookie作用
会话管理:登录状态、购物⻋
个性化:⽤户偏好、主题
Tracking:分析⽤户⾏为
1.2.8.1.7 如何保证Cookie的安全性
1.2.8.2 Authorization
1.2.8.3 Authorization 实现方式
方式1: Basic
方式2: Bearer
1.2.8.4 Authorization 授权流程
为了安全。OAuth 不强制授权流程必须使⽤ HTTPS,因此需要保证当通信路径中存在窃听者时,依然具有⾜够⾼的安全性。
1.2.8.5 如何刷新token
用法
access_token 有失效时间,在它失效后,调⽤ refresh token 接⼝,传⼊ refresh_token 来获取新的 access_token。
目的
安全。当 access_token 失窃,由于它有失效时间,因此坏⼈只有较短的时间来「做坏事」;同时,由于(在标准的 OAuth2 流程中)refresh token 永远只存在与第三⽅服务的服务器中,因此 refresh token ⼏乎没有失窃的⻛险。
Line 实现三方登录授权
构建授权实体类
提供授权回调
构造LineSDK回调结果数据
1.3 HTTPS
HTTPS 定义
HTTPS 背景
HTTPS 证书
数字证书是 HTTPS 实现 安全传输的基础,它是由权威的CA机构颁发,证书的主要内容有: 公钥,证书颁发机构,证书持有者,证书有效期,签名算法,指纹及指纹算法
HTTPS 证书内容
可以看到公钥是一串很长的2048.bits的字符串,同时也看到使用者额内容包括了一些网站,后面会跟随颁发者,有效期,签名算法等等,当然还有指纹和指纹算法等等
证书的指纹和签名
签名在证书后面加一段字符串,可以证明该信息没有被修改过,CA机构将证书的指纹和指纹算法通过私钥加密就是证书签名了
需要⾃⼰写证书验证过程的场景
HTTPS 证书的指纹和签名
HTTPS 证书验证请求过程
HTTPS 证书类型
HTTPS 证书作用
HTTPS 如何自定义证书
HTTPS SSL/TLS
SSL/TLS概念
SSL/TLS 是信息安全领域中的权威标准,采用多种先进的加密技术保证通信安全
SSL/TLS 版本
TLS 1.3 相比 TLS 1.2的优化空间
HTTPS 认证方式
HTTPS 单向认证
HTTPS 双向认证
HTTPS 连接建立过程(⼯作原理)
在客户端和服务器之间协商出⼀套对称密钥,每次发送信息之前将内容加密,收到之后解密,达到内容的加密传输
HTTPS 优化
尽量采用 TLS1.3,它大幅度简化了握手的过程,完全握手只要 1-RTT,而且更加安全
HTTPS 保证通信安全
机密性
完整性
身份认证
不可否认
1.3 Transport Layer 传输层
TCP
四次挥手
挥手目的:
TCP的连接的拆除需要发送四个包
通信双⽅方建立确认「可以通信」,不会将对方的消息丢弃,即为「建立连接」
挥手过程:
主机A会发送一个报文段(序列号seq=p,标志位FIN=1),然后进入FIN-WAIT-1状态,发送了标志位FIN=1之后,表示我要关闭这个连接,后续将不会再有数据传输过来,但是这时候主机A还是可以收到主机B发送过来的数据;
主机B接受到主机A发送的FIN报文段,会发送一个确认报文段,标志位ACK=1,确认序列号ack=p+1,然后就进入CLOSE-WAIT状态,这个过程表示接受到关闭方发送的关闭请求了。
当主机B的数据都发送完毕后,就会想主机A发送释放连接的报文,主机B发送FIN报文段,标志位FIN=1,序列号seq=q,确认序列号p+1,标志位ACK=1,然后就进入LAST-ACK状态;
主机A接收到关闭报文段后,会发出确认报文段,标志位ACK=1,确认序列号ack=q+1,序列号seq=u+1,然后进入TIME-WAIT状态,此时TCP连接还没有释放,会等待2∗MSL(最长报文段寿命)的时间后,才会进入CLOSED状态;
三次握手
握手目的
连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息
握手过程
因为移动⽹络并不在 Internet 中,⽽是在运营商的内网,并不具有真正的公网 IP,因此当某个 TCP 连接在⼀段时间不通信之后,⽹关会出于网络性能考虑而关闭这条 TCP 连接和公网的连接通道,导致这个TCP 端口不再能收到外部通信消息,即 TCP 连接被动关闭。
⼼跳。即在一定间隔时间内,使用 TCP 连接发送超短无意义消息来让网关不能将自己定义为「空闲连接」,从⽽防止网关将自己的连接关闭。
UDP
1.4 Internet Layer ⽹络层
1.5 Link Layer 数据链路层