MicroKibaco / CrazyDailyQuestion

每日一问: 水滴石穿,聚沙成塔,坚持数月, 必有收获~
35 stars 1 forks source link

说一下网络四层协议? #72

Open MicroKibaco opened 4 years ago

MicroKibaco commented 4 years ago

万物互联,每一天我们都离不开网络,对于程序员来说网络是基础,我们怎么巩固这方面的基础呢?需要阅读大量的书籍,学好网络我们首先要对那四层协议要有清晰的认知,然后需要掌握一些基本的抓包和反抓包策阅,当然常用的加解密其实也是需要掌握的,好了话不多说,就让我们打开网络之旅吧

一. 网络分层

为什么要网络分层呢?

其实因为网络的不稳定性

从广义来说: 网络其实是可以分为七层,但是我们这里学习四层就行了:

1.1 Application Layer 应用层

1.2 HTTP

1.2.1 HTTP版本

1.2.1.1 HTTP/1

A. 连接无法复用

HTTP/1.0 数据时,每次都需要重新建立连接,增加延迟。

B. HOLB(队头阻塞)

1.2.1.2 HTTP/2

1.2.1.2.1 二进制传输

HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码

1.2.1.2.2 多路复用

多路复用解决痛点

解决了浏览器限制同一个域名下的请求数量的问题,同时也接更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。

多路复用特性
  1. 同域名下所有通信都在单个连接上完成。
  2. 单个连接可以承载任意数量的双向数据流。
  3. 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。
    多路复用优点
  4. 同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应,消除了因多个 TCP 连接而带来的延时和内存消耗。
  5. 并行交错地发送多个请求,请求之间互不影响。
  6. 并行交错地发送多个响应,响应之间互不干扰。
  7. HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。

    1.2.1.2.3 Header压缩

    • 在 header 携带 cookie 的情况下,可能每次都需要重复传输几百到几千的字节,为了减少这块的资源消耗并提升性能
      1. 使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送;
      2. 首部表在HTTP/2的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
      3. 每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值

        1.2.1.2.4 缓存push

        提前给客户端推送必要的资源,这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用 prefetch。

        1.2.1.3 HTTP/3

        QUIC,基于UDP

        1.2.2 HTTP定义

  8. ⼀种网络传输协议,位于 TCP / IP 协议族的最顶层——应⽤层
  9. Hypertext Transfer Protocol,超文本传输协议,和 HTML (Hypertext Markup Language 超文本标记语言) 一起诞生,用于在网络上请求和传输 HTML 内容。
  10. 超⽂本,即「扩展型文本」,指的是 HTML 中可以有链向别的文本的链接(hyperlink)

    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分类
  11. text/html 请求 Web ⻚⾯是返回响应的类型,Body 中返回 html 文本。格式如下:
  12. x-www-form-urlencoded
  13. multipart/form-data
  14. application/json , image/jpeg , application/zip
  15. Accept
    客户端能接受的数据类型。如 text/html
  16. Accept-Charset
    客户端接受的字符集。如 utf-8
  17. Accept-Encoding
    客户端接受的压缩编码类型。如 gzip
  18. Content-Encoding
    压缩类型。如 gzip

    1.2.4 HTTP 状态码

    • 1xx
      临时性消息。如:100 (继续发送)、101(正在切换协议)
    • 2xx
      成功。最典型的是 200(OK)、201(创建成功)

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.2 分块传输

1.2.8 登录授权

1.2.8.1 Cookie

1.2.8.1.1 Cookie 工作机制
  1. 服务器需要客户端保存的内容,放在 Set-Cookie headers ⾥返回,客户端会⾃动保存。
  2. 客户端保存的 Cookies,会在之后的所有请求⾥都携带进 Cookie header ⾥发回给服务器。
  3. 客户端保存 Cookie 是按照服务器域名来分类的,例如 shop.com发回的 Cookie 保存下来以后,在之后向 games.com的请求中并不会携带。
  4. 客户端保存的 Cookie 在超时后会被删除、没有设置超时时间的 Cookie (称作 SessionCookie)在浏览器关闭后就会⾃动删除;另外,服务器也可以主动删除还未过期的客户端Cookies。
    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: Basic
1.2.8.4 Authorization 授权流程

  1. 第三⽅ App 向腾讯申请第三⽅授权合作,拿到 client_id 和 client_secret
  2. ⽤户在使⽤第三⽅ App 时,点击「通过微信登录」,第三⽅ App 将使⽤微信 SDK 跳转到微信,并传⼊⾃⼰的 client_id 作为⾃⼰的身份标识
  3. 微信通过和服务器交互,拿到第三⽅ App 的信息,并限制在界⾯中,然后询问⽤户是否同意授权该 App 使⽤微信来登录
  4. ⽤户点击「使⽤微信登录」后,微信和服务器交互将授权信息提交,然后跳转回第三⽅App,并传⼊ Authorization_code 作为⽤户认可的凭证
  5. 第三⽅ App 调⽤⾃⼰服务器的「微信登录」Api,并传⼊ Authorization_code,然后等待服务器的响应
  6. 服务器在收到登录请求后,拿收到的 Authorization_code 去向微信的第三⽅授权接⼝发送请求,将 Authorization_code 和⾃⼰的 client_secret ⼀起作为参数发送,微信在验证通过后,返回 access_token
  7. 服务器在收到 access_token 后,⽴即拿着 access_token 去向微信的⽤户信息接⼝发送请求,微信验证通过后,返回⽤户信息
  8. 服务器在收到⽤户信息后,在⾃⼰的数据库中为⽤户创建⼀个账户,并使⽤从微信服务器拿来的⽤户信息填⼊⾃⼰的数据库,以及将⽤户的 ID 和⽤户的微信 ID 做关联
  9. ⽤户创建完成后,服务器向客户端的请求发送响应,传送回刚创建好的⽤户信息
  10. 客户端收到服务器响应,⽤户登录成功在⾃家 App 中使⽤ Bearer_token 有的 App 会在 Api 的设计中,将登录和授权设计成类似OAuth2 的过程,但简化掉 authorization_code 概念。即:登录接⼝请求成功时,会返回 access_token,然后客户端在之后的请求中,就可以使⽤这个 access_token 来当做 bearer_token 进⾏⽤户操作了。

为什么 OAuth 要引⼊ Authorization code,并需要申请授权的第三⽅将 Authorization code 发送回⾃⼰的服务器,再从服务器来获取 access token,⽽不是直接返回 access token ?这样复杂的流程意义何在?

为了安全。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 定义

  1. HTTP over SSL 的简称,即⼯作在 SSL (或 TLS)上的 HTTP。说白了就是加密通信的 HTTP。
  2. HTTPS 把下层的协议由 TCP/IP 换成了 SSL/TLS

HTTPS 背景

  1. 支持的https的网站基本都是CA机构颁发的证书,默认情况下是可以信任的;
  2. 自己通过keytool去生成一个证书,然后使用,并不是CA机构去颁发的。使用自签名证书的网站,大家在使用浏览器访问的时候,一般都是报风险警告

HTTPS 证书

数字证书是 HTTPS 实现 安全传输的基础,它是由权威的CA机构颁发,证书的主要内容有: 公钥,证书颁发机构,证书持有者,证书有效期,签名算法,指纹及指纹算法

HTTPS 证书内容

可以看到公钥是一串很长的2048.bits的字符串,同时也看到使用者额内容包括了一些网站,后面会跟随颁发者,有效期,签名算法等等,当然还有指纹和指纹算法等等

证书的指纹和签名

签名在证书后面加一段字符串,可以证明该信息没有被修改过,CA机构将证书的指纹和指纹算法通过私钥加密就是证书签名了

需要⾃⼰写证书验证过程的场景
HTTPS 证书的指纹和签名
HTTPS 证书验证请求过程

HTTPS 证书类型

SSL/TLS 是信息安全领域中的权威标准,采用多种先进的加密技术保证通信安全

SSL/TLS 版本

TLS 1.3 相比 TLS 1.2的优化空间

HTTPS 认证方式

HTTPS 单向认证

HTTPS 双向认证

HTTPS 优化

尽量采用 TLS1.3,它大幅度简化了握手的过程,完全握手只要 1-RTT,而且更加安全

HTTPS 保证通信安全

挥手目的:

TCP的连接的拆除需要发送四个包

什么是TCP连接?

通信双⽅方建立确认「可以通信」,不会将对方的消息丢弃,即为「建立连接」

挥手过程:

三次握手

握手目的

连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息

握手过程

为什么要建立长连接

因为移动⽹络并不在 Internet 中,⽽是在运营商的内网,并不具有真正的公网 IP,因此当某个 TCP 连接在⼀段时间不通信之后,⽹关会出于网络性能考虑而关闭这条 TCP 连接和公网的连接通道,导致这个TCP 端口不再能收到外部通信消息,即 TCP 连接被动关闭。

长连接实现⽅式

⼼跳。即在一定间隔时间内,使用 TCP 连接发送超短无意义消息来让网关不能将自己定义为「空闲连接」,从⽽防止网关将自己的连接关闭。

TCP报文格式

UDP

1.4 Internet Layer ⽹络层