001-2020-网络-通用

577 阅读24分钟

1.知识点

1.HTTP

Hypertext Transfer Protocol,超文本传输协议

2.URL

  1. URL可以拆为3部分:协议类型 , 服务器地址及端口号 , 路径
  2. 协议类型://服务器地址[:端口号]路径
https://juejin.im/timeline
协议类型:   https
服务器地址: juejin.im
路径:       /timeline

3.幂等操作

在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同.

4.HTTP请求方法

  1. GET:
    • 用于获取数据,不修改资源,无Body.
    • 幂等
  2. POST:
    • 用于增加,修改资源,有Body.
    • 非幂等
  3. PUT:
    • 仅用于修改资源,有Body.
    • 幂等
  4. DELETE:
    • 仅用于删除资源,无Body
    • 幂等
  5. HEAD:
    • 和GET使用方法完全相同. 只是响应中无Body.
    • 幂等
    • 例如想下载资源,先发送HEAD请求,看资源长度,支不支持断点续传等--

5.HTTP状态码

百度百科HTTP状态码

  • 1开头:临时性消息
    • 100: 客户端应该继续发送请求
    用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。
    客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应。
    
    • 101: 正在切换协议
    服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。
    在发送完这个响应最后的空行后,服务器将会切换到在Upgrade 消息头中定义的那些协议。
    
  • 2开头:成功
    • 200: 成功
    • 201: 创建成功
    • 206: 成功处理范围请求
      • 服务器已经成功处理了部分 GET 请求,就是就分段下载,断点续传的响应,会返回206
  • 3开头:重定向
    • 301: 永久重定向
      • 被请求的资源已永久移动到新位置,客户端应当自动把请求的地址修改为响应中的Location.
      • 301比较常用的场景是使用域名跳转。
        比如,我们访问http://www.baidu.com会跳转到https://www.baidu.com,
        发送请求之后,就会返回301状态码,然后返回一个location,提示新的地址,
        浏览器就会拿着这个新的地址去访问
        
    • 302: 临时重定向
      • 302用来做临时跳转.比如未登陆的用户访问用户中心重定向到登录页面.
    • 304: 内容未改变
  • 4开头:客户端错误
    • 400: 客户端请求报文中存在语法错误
    • 401: 当前请求需要用户验证 或 用户认证失败
    • 403: 请求被禁止/被服务器拒绝
      • 例如访问一些当前用户没有权限的文件,就会返回403
    • 404: 找不到内容
  • 5开头:服务器错误
    • 500: 服务器内部错误

6.Header - HTTP请求/响应的元数据

  1. Host: 不是在网络上用于寻址的,而是在目标服务器上用于定位子服务器的.
    • 因为同1个IP可能对应多个子服务器.
      {
        "111.111.111.111": [
          "a.com",
          "b.com",
          "c.com"
        ]
      }
      
    • 寻址:使用DNS
      • 域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库
  2. Content-Length: 指定Body(请求体 或 响应体)的字节长度
  3. Transfer-Encoding: chunked
    • HTTP协议扫盲(八 )响应报文之 Transfer-Encoding=chunked方式
    • 由于 Content-Length 字段必须真实反映实体长度,但是对于动态生成的内容来说,在内容创建完之前,长度是不可知的.用于尽快给出响应,减少用户等待.
      每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF(\r\n),也不包括分块数据结尾的 CRLF(\r\n)。
      最后一个分块长度值必须为 0,对应的分块数据没有内容,表示实体结束。
      例:
      
      HTTP/1.1 200 OK
      Content-Type: text/plain
      Transfer-Encoding: chunked
      
      23\r\n
      This is the data in the first chunk\r\n
      1A\r\n
      and this is the second one\r\n
      3\r\n
      con\r\n
      8\r\n
      sequence\r\n
      0\r\n
      \r\n
      
      Content-Encoding 和 Transfer-Encoding 二者经常会结合来用,
      其实就是针对 Transfer-Encoding 的分块再进行 Content-Encoding压缩。
      
  4. Location: 指定重定向的目标 URL
    实例:
    还是刚刚那个网址. https://www.bbsmax.com/A/pRdBaGrD5n/ .
    在浏览器中将https修改为http,回车访问.
    查看网络响应.
    
    请求Header:
    GET /A/pRdBaGrD5n/ HTTP/1.1
    Host: www.bbsmax.com
    ***
    
    响应Header
    //301 永久重定向
    HTTP/1.1 301 Moved Permanently
    //浏览器应该继续访问 https://www.bbsmax.com/A/pRdBaGrD5n/
    Location: https://www.bbsmax.com/A/pRdBaGrD5n/
    ***
    
    继续请求-->
    //继续请求https**
    Request URL: https://www.bbsmax.com/A/pRdBaGrD5n/
    Request Method: GET
    //成功返回响应结果
    Status Code: 200 OK
    
  5. User-Agent:
    • User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等
    • 用于服务器区分不同终端,返回与之匹配的内容
  6. Range / Accept-Range
    • Range Accept-Range可以用来做断点续传,多线程下载;
    • Accept-Range:bytes:响应报文中出现,表示服务器支持按字节来取范围数据;
    • Range:bytes=start-end:请求报文中出现,表示要取哪段数据;
    • Content-Range:start-end/total:响应报文中出现,表示发送的是哪段数据;
  7. Cache和Buffer的区别:
    • Cache是之前用过的东西以后可能会再用,先存着;
    • Buffer是没有用过的东西以后可能/一定会用,先存着;
    • Cache是针对用过的;Buffer是针对没用过的;
    • Buffer一定是针对工作流的;
  8. Cache: 在客户端或中间网络节点缓存数据,降低从服务器取数据的频率,以提高网络性能.
    • 响应中使用Cache-Control:
      • public :中间网络节点可以缓存该网络响应,数据是共用数据,和特定用户无关.
      • private :中间网络节点不能缓存该网络响应,数据是特定用户的个性化数据.
      • private不代表私密/加密的意思,单纯指不同用户个性化数据不可共用.
  9. Content-Type
    • application/json , image/jpeg , application/zip ...单项内容(文本或非文本都可以),用于 Web Api 的响应或者 POST / PUT 的请求,可用于文件上传.
    • 文件上传使用下面方式更简单,不必非得使用multitype/form-data . 单纯提交一个文件,相比 multitype/form-data 可以避免使用 boundary ,降低了带宽占用,提升了速度.
      @POST("music/{musicId}/album")
      Call<User> uploadMusicAblum(@Path("musicId") String musicId, @Body RequestBody musicAlbum);
      ...
      String musicId = "music1";
      File fileAlbum = ***;
      RequestBody musicAlbum = RequestBody.create(MediaType.parse("image/jpeg"),albumFile);
      api.uploadMusicAblum(musicId, musicAlbum)
      
      POST /music/music1/album HTTP/1.1
      Host: ***
      Content-Type: image/jpeg
      Content-Length: 111111111111
      SJGLDJGLSKGH;LDSKGH......
      
    • text/html: html文本
    • x-www-form-urlencoded: 普通表单
    • multitype/form-data: 包含二进制文件时的提交方式,单纯上传1个文件,使用POST性能更好,可以避免boundary占用带宽.
  10. Accept
    • 客户端告知服务端,自身能够接收的媒体类型及相对优先级.
    • Accept可以指定多个媒体类型,若服务端可提供多种媒体类型,优先返回优先级最高的.
    • 权重值从0-1,精确到小数点后3位,权重值越大,优先级越高.
    • 仅仅指定1个媒体类型,则权重值默认是1
      Accept : text/html
      
    • 指定多个媒体类型
      //客户端接受 纯文本,权重为0.3html(默认权重是1)
      //服务端收到请求,优先返回html
      Accept: text/plain;q=0.3, text/html
      
  11. Accept-Charset: 客户端告知服务端,自身接受的字符集
    • 同Accept,也支持传入多种,添加权重
  12. Accept-Encoding: 客户端告知服务端,自身接受的压缩编码类型
    • 同Accept,也支持传入多种,添加权重
  13. Content-Encoding:
    • 服务端告知客户端,自身对Body进行的压缩编码类型.
    • 常用压缩类型:gzip, deflate

7.对称加密

  1. 1个密钥+2个算法(加密算法,解密算法)
  2. 明文-->(密钥+加密算法)-->密文
  3. 密文-->(密钥+解密算法)-->明文
  4. 算法: DES(56位密钥,密钥太短逐渐被弃用), AES(128位,192位,256位,当下最流行的对称加密算法)
  5. 对称加密的POJIE:
    • 首先设法拿到一组或多组原文-密文对;
    • 设法找到一个密钥,可以将原文-->密文,并将密文-->原文,即为POJIE成功;
    • 反POJIE:一种优秀的对称加密算法的标准是,找不到比穷举法更有效的手段,且POJIE足够久
  6. 对称加密的缺点:无法在不可信网络上传输密钥,一旦被第三方获取到密钥,则通信失败.

8.非对称加密

  1. 2个密钥(公钥+私钥)+1个加密算法
  2. A发送数据给B:
    • A:明文-->(B的公钥+加密算法)-->密文 ==> B:(B的私钥+加密算法)-->明文
  3. 公钥和私钥互相可解.公钥发给对方,私钥自己保管.
  4. 经典非对称加密算法:RSA(可用于加密和签名),DSA(仅用于签名,但速度更快)
  5. 由于公钥和私钥互相可解,非对称加密可应用于数字签名技术.通常会对原始数据hash以后对hash签名,然后附加在原始数据的后面作为签名.
  6. 对方公钥加密,自身私钥签名
  7. 非对称加密的POJIE:
    • 和对称加密不同的是,非对称加密的公钥很容易获得,制造 原文-密文对很容易;
    • 关键在于如何找到正确的私钥,可以解密所有经过公钥加密后的密文.找到这样的私钥即为成功POJIE;
    • 对称加密POJIE是不断尝试新密钥是否可以将拿到的原文-密文对加密和解密;
    • 非对称加密POJIE,是不断尝试新私钥是否和公钥可以互解.
    • 非对称加密算法优秀的标准和加密算法一样,找不到比穷举法更有效的手段,且穷举法POJIE时间足够长.
  8. 非对称加密的优点:可在不可信网络上传输公钥.缺点:计算复杂,性能差.
  9. 公钥私钥互相可解,那是否可以任意公开一个保密一个?
    • 不能.
    • 因为公钥和私钥的位置是不对等的,很多时候根据私钥可以很容易推算出公钥.但是通过公钥无法导出私钥

9.编码及解码

  1. 编码:把数据从一中形式转换为另一种形式. 解码:将数据恢复到原始格式.
  2. 编码一定有解码与之对应,单向转换不是编码.

10.Base64

  1. 将二进制数据中每6位对应成Base64索引表中的一个字符,编排成1个字符串(每个字符占8位).
  2. Base64属于编码,不属于加密(对称加密秘钥不公开,非对称加密的私钥不公开,而Base64编码解码逻辑是公开的).
  3. Base64性能差,原数据每6位转换为8位(1个字符),存储和传输会增加1/3的消耗.使用Base64的好处就是使用字符串相对于普通二进制数据/文件的好处.
  4. 码表,Java中有2套,分别用于普通场景及URL地址转换场景
    /**
     * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
     * equivalents as specified in Table 1 of RFC 2045.
     *
     * Thanks to "commons" project in ws.apache.org for this code.
     * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
     */
    private static final byte[] STANDARD_ENCODE_TABLE = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
    };
    
    /**
     * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
     * changed to - and _ to make the encoded Base64 results more URL-SAFE.
     * This table is only used when the Base64's mode is set to URL-SAFE.
     */
    private static final byte[] URL_SAFE_ENCODE_TABLE = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
    };
    

11.压缩和解压缩属于编码解码

12.序列化

  1. 将内存中对象转换为字节序列的过程,可以将字节序列存储到磁盘,或者进行网络传输;
  2. 序列化不是编码,不属于数据格式的转换;
  3. Serializable接口:
    1. xxx
    2. xxx

13.Hash

  1. Hash不属于编码,单向不可逆不属于编码,也不属于加密,加密属于编码,解密属于解码
  2. Hash实际用途:
    • 唯一性验证-hashCode()
    • 数据完整性验证,如下载文件附加MD5用户可校验文件是否被篡改或损坏
    • 快速查找-HashMap
      • 重写hashCode为什么也要重写equals/hashCode和equals为什么要同时修改?
      • 看看HashMap源码就明白了
    • 隐私保护
      • 明文存储密码不安全,存储密码Hash简单密码也容易被彩虹表暴力POJIE.加盐可解决彩虹表问题.可以将(用户密码+随机字符串 按指定规则组合后)取hash,将hash和随机字符串进行存储.
      • 加盐: www.jianshu.com/p/f1954e614…

14.Cookie

  1. Cookie工作机制
    • 服务器器需要客户端保存的内容,放在 Set-Cookie headers 里返回,客户端会自动保存.
      Set-Cookie:user=ZhangSan
      
    • 客户端保存的 Cookies,会在之后的所有请求里都携带 Cookie header 里发回给服务器.
      Cookie:user=ZhangSan
      
    • 客户端保存 Cookie 是按照服务器域名来分类的.例如 shop.com 发回的 Cookie 保存下来,之后向 games.com 的请求中不会携带.
    • 客户端保存的 Cookie 在超时后会被删除、没有设置超时时间的 Cookie (称作 Session Cookie)在浏览器器关闭后就会⾃自动删除;另外,服务器器也可以主动删除还未过期的客户端 Cookies.
  2. Cookie作用
    • 会话管理:如登陆状态.服务器响应数据Header包含 Set-Cookie:user_id = 123
    • 记录用户偏好
    • 分析用户行为
      追踪用户信息,永远不是用A网站记录访问A网站的用哪个用户.
      而是用1个统一的第三方网站,保存某个终端/设备访问所有网站的记录.
      

15.Http确认授权的2种方式

  1. 通过Cokkie .如上述 user_id
  2. 通过Header中添加Authorization
    • Authorization两种主流方式:Basic , Bearer
    • Authorization: Basic username:password执行Base64编码的字符串
      Authorization: Basic 12345678
      
    • Authorization: Bearer bearer token
      • bearer token 需要通过 OAuth2的授权流程获取.

16.OAuth2

  1. 掘金一篇文章很不错 做前后端分离项目前,劝你先了解 OAuth2.0 的四种授权方式
  2. OAuth2流程
    • 第三方网站向授权方网站申请第三方授权合作,拿到client id和client secret.client secret需要绝对保密,一直存在第三方网站服务器.
    • 用户使用掘金,点击GitHub登录,首先跳转到GitHub网站,并将client id传入.
    • GitHub根据client id,将掘金信息及掘金需要的GitHub用户的权限进行展示,询问用户是否同意
    • 用户点击'同意',GitHub重新跳转回掘金,并传入Authorization code作为用户同意凭证.
    • 掘金将Authorization code发送回掘金自己服务器
    • 掘金服务器将Authorization code及client secret一并发送给GitHub服务器(这个连接一定是HTTPS连接,是绝对安全的),GitHub验证通过,则返回access token/bearer token.
    • 获取到 access token/bearer token 后,OAuth2流程已经结束.
    • 后续:掘金获取到access token,后台服务器就向GitHub发送请求,用于获取该用户的信息/操作用户账户.然后根据用户信息创建'掘金账号',并将'掘金账号'和GitHub的用户信息进行关联.
  3. 引入Authorization code ,并且要在后台服务器将 Authorization code,client secret发送给GitHub获取access token,为什么不直接返回access token?
    • 为了安全.因为client secret由第三方服务器保存绝对安全,后台服务器和GitHub使用HTTPS获取access token,access token不会暴露给客户端,避免客户端直接使用access token进行网络传输被窃取.
  4. Refresh token
    • 服务器返回access_token的相应数据格式类似:
    {
        "token_type": "Bearer",
        "access_token": "111",
        "refresh_token": "222",
        "expires_time": "111"
    }
    
    • 用法:access token 有失效时间,在它失效后,调用 refresh token 接口,将 client id, client secret, Authorization code, refresh-token 一起通过HTTPS发送到第三方授权网站,重新获取新的 access-token.
    • 目的:安全.当access token失窃,由于它有失效时间,因此坏人只有较短的时间使用.同时,由于refresh token 永远只存在与第三方服务的服务器中,refresh token 几乎没有失窃的风险

17.HTTPS

HTTPS 为什么是安全的

  1. 定义: HTTP over SSL,建立在TLS/SSL上的HTTP.就是加密通信的HTTP
  2. 工作原理:
    • 在客户端和服务器之间协商出一套对称加密密钥
    • 每次发送消息前进行加密,收到消息后进行解密
  3. 为什么不直接使用非对称加密
    • 非对称加密使用了复杂的数学原理,计算相当复杂.每次都是用非对称加密,会严重影响网络通信性能
  4. HMAC
    • HMAC运算利用hash算法,以一个消息M和一个密钥K(Secret)作为输入,生成一个定长的消息摘要作为输出。
      原始消息:"111111111111111"
      普通hash算法后:"aaaaaaaa"
      HMAC:"aabbccdd"
      
    • 只有发送方发送消息时使用的Secret和接收方验证时使用的一致,对同样原始消息进行HMAC摘要运算才能得到相同的HMAC结果.
    • 而Secret是双方协商出来保存在本地,不会在网络上进行传输,不存在被窃取的可能.
  5. HTTPS 连接建立步骤
    1. Client Hello
    2. Server Hello
    3. 服务器器证书 信任建⽴立
    4. Pre-master Secret
    5. 客户端通知:将使用加密通信
    6. 客户端发送:Finished
    7. 服务器器通知:将使用加密通信
    8. 服务器器发送:Finished
    
  6. 比如A想访问B网站,B网站的证书是BA;A在在发送请求路程中间,被C网站截获,C网站将自己的证书CA返回给A. CA本身也是一个合法的证书,A怎么去辨认?
    • 通过证书信息中的域名(host)去辨认.比如A要访问alibaba,结果被tencent截获,返回了tencent的证书,虽然tencent证书本身合法,但是tencent的证书信息中,host是tencent,不是alibaba,和A要访问的域名不一致,就不会进行后续的验证工作.
    • 证书不能伪造,也不能篡改.因为证书签发机构的私钥第三方是拿不到的,改了任何信息,都会导致修改后信息的HASH和证书签名被签发机构公钥运算后的结果对不上,导致认证失败!
  7. 在 Android 中使用 HTTPS
    • 正常情况下直接使用即可
    • 以下情况不能直接使用,需要自己写证书验证过程
      1. 用的是自签名证书(例如只用于内网的 https)
        • 直接使用OkHttp中的CertificatePinner可以很方便的实现自签名证书验证
          https://blog.csdn.net/challenge51all/article/details/82909965
          可以直接看 CertificatePinner 的注释,有使用方法:
          
          将异常中的公钥散列粘贴到证书pinner的配置中:
          String hostname = "publicobject.com";
          CertificatePinner certificatePinner = new CertificatePinner.Builder()
             .add(hostname, "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
             .add(hostname, "sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=")
             .add(hostname, "sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=")
             .add(hostname, "sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=")
             .build();
          OkHttpClient client = new OkHttpClient();
          client.setCertificatePinner(certificatePinner);
          Request request = new Request.Builder()
               .url("https://" + hostname)
               .build();
          client.newCall(request).execute();
          
      2. 证书信息不不全,缺乏中间证书机构(可能性不不⼤大)
      3. 手机操作系统较旧,没有安装最新加入的根证书
      4. 自己怎么写证书验证过程: 通过 HTTPS 和 SSL 确保安全

18.HTTPS 连接建立步骤详细

  1. 客户端向服务器发送"Client Hello",包含以下内容:
    • 客户端可以接受的 所有的SSL/TLS的版本
    • 客户端可以接受的 所有的 非对称加密算法+对称加密算法+hash算法组合.每个组合称为1个Cipher Suite(密钥算法套件).
    • 客户端随机数
    • Server name:告知服务器要下发到哪个子服务器
  2. 服务器收到客户端发来的"Client Hello"后,选出要使用的SSL/TLS版本+Cipher Suite,再加上服务器随机数,再一起发给客户端:"Server Hello"
    • 保存客户端随机数
    • 从客户端提供的所有 SSL/TLS版本 中选出要使用的版本
    • 从客户端提供的所有 Cipher Suite 中选出要使用的 Cipher Suite
    • 然后将选好的 SSL/TLS版本+Cipher Suite,再加上服务器随机数,一起发给客户端:"Server Hello"
    • 选好的 SSL/TLS版本+Cipher Suite+客户端随机数+服务器随机数,服务器和客户端一人一份
  3. 服务器向客户端发送 服务器证书,若客户端对服务器证书的验证通过,则客户端对服务器的信任建立成功
    • 服务器证书结构:
      1. 证书本身信息(绿色部分)
      2. 证书签发机构信息(橙色部分)
      3. 证书签发机构的签发机构信息(蓝色部分):签发机构的签发机构,就存在我们电脑/手机根证书列表里,对于设备上存在的根证书,我们只能必须信任
    • 客户端对服务器证书进行验证,满足2个条件,则服务器证书验证通过:
      1. 确保的确是证书签发机构对服务器证书进行了签名
      2. 确保证书签发机构是可信的
    • 服务器证书中证书签名来源
      1. 首先把 证书信息,证书公钥,证书签名算法这3个信息揉在一起, 做1个hash,得到原始值OriStr.具体什么hash算法在 证书签名算法里面有.
      2. 证书签名算法中包含:具体hash算法,签名用那种非对称加密算法
      3. 然后用证书签发机构的私钥对OriStr进行加密运算,得到最终的 证书签名
    • 客户端怎么验证证书合法
      1. 客户端把 证书信息,证书公钥,证书签名算法通过 证书签名算法中的hash算法得出 hash值 ClientHash
      2. 用证书签发机构的公钥对 证书签名进行hash,得到 ServerHash
      3. 如果 ClientHash和ServerHash相等,就说明的确是证书签发机构对证书进行了签名(只有用 证书签发机构的私钥 加密,公钥解密,才可能ServerHash=ClientHash)
      4. 如何验证 证书签发机构 是可信的:用设备上存在的 签发机构的签发机构 来验证签发机构是否可信
        • 对设备上存在的 签发机构的签发机构/根证书,我们只能信任
        • 验证流程和验证证书签名是一致的:
          1. 客户端把 签发机构基本信息,签发机构公钥,签发机构签名算法通过 签发机构签名算法中的hash算法得出 hash值 Hash1
          2. 客户端用 签发机构的签发机构的公钥 对 签发机构签名进行hash,得到 Hash2
          3. 如果 Hash1=Hash2,说明证书签发机构也是可信的
  4. Pre-master Secret/随机密码串
    • Pre-master Secret被称为随机密码串. 是随机产生的,加上使用服务器证书公钥加密,保证了安全.
      • 不怕之前和服务器的交互信息被第三方截获,截获后第三方生成的Pre-master Secret也和真正客户端生成的不一样
      • 使用服务器证书公钥进行加密,第三方截获后也没办法解密
    • 客户端自己算出1个Pre-master Secret,保存之,并将Pre-master Secret使用服务器证书公钥加密后发送给服务器,服务器解密后保存Pre-master Secret.两边一人一份
    • 客户端和服务器利用两边同样的 客户端随机数+服务器随机数+Pre-master Secret,用固定算法计算出 Master Secret
    • 所有的客户端和服务器沟通,都是用同样的算法计算出Master Secret
    • Master Secret得到后,客户端随机数+服务器随机数+Pre-master Secret就没用了,客户端和服务器都保存Master Secret
    • 客户端和服务器用Master Secret计算出:
      1. 真正加密通讯时使用的2个对称加密秘钥
        • 客户端给服务器发消息使用的对称加密密钥M1:客户端密钥
        • 服务器给客户端发消息使用的对称加密秘钥M2:服务器密钥
      2. 客户端给服务器,以及服务器给客户端发送消息时用来做HMAC算法的MAC Secret
        • 客户端MAC Secret
        • 服务器MAC Secret
  5. 客户端向服务器发送一条通知:将使用加密通信
  6. 客户端向服务器发送:Finished
    1. 客户端将步骤1-步骤5 所有信息使用 M1加密得到密文C1
    2. 客户端将步骤1-步骤5 所有信息使用 客户端MAC Secret 进行HMAC运算得到签名S1
    3. 客户端将C1及S1一起发送至服务端
    4. 服务端接收到消息:
      1. C1使用 M1解密得到原文C2.并将C2和自身保存的步骤1-5进行比对,确认解密成功.
      2. 对步骤1-5使用 客户端MAC Secret 进行HMAC运算得到签名S2. 若S1=S2, 确认签名验证成功.
  7. 服务器向客户端发送一条通知:我也将使用加密通信
  8. 服务器向客户端发送:Finished
    1. 服务端将步骤1-步骤7 所有信息使用 M2加密得到密文C1
    2. 服务端将步骤1-步骤7 所有信息使用 服务器MAC Secret 进行HMAC运算得到签名S1
    3. 服务端将C1及S1一起发送至客户端
    4. 客户服务端接收到消息:
      • 使用同样方式确认 解密成功 及 签名验证成功
  9. 以上8步通过,客户端就向服务器发送第一条HTTPS消息.
    • HTTPS请求的样子:
      应用层消息:后面是一大串无法解读的字符串
      
      即使消息被第3方截获,也只能知道是1个应用层消息,却无法解读,因为客户端密钥和服务器密钥第3方无法拿到. 
      客户端和服务器互发消息,除了会使用客户端密钥和服务器密钥进行加密,也都会使用HMAC进行签名.
      

19.字符集

字符集:1个由 整数 向 实际的文字符号 的映射

示例:
0 : "a"
1 : "b"
2 : "c"

20.网络分层模型

21.端口 , IP地址/域名

端口是针对TCP,UDP的,是传输层的概念;
HTTP不存在端口的概念,HTTP属于应用层;
IP/域名是 IP层/网络层的概念;

2.开发中遇到的问题

1.CLEARTEXT communication to '指定网址' not permitted by network security policy

  1. 在Android P(API 28)及更高系统的设备上,默认要求使用加密连接/HTTPS。不进行配置就使用HTTP通信,则会得到上面的异常.
  2. 3种解决办法
    1. targetSdkVersion设置为小于28
    2. 服务器网址由 http 升级为 https
    3. 进行配置
  3. 配置流程
    1. 在 res/xml/ 下创建 network_security_config.xml
      <?xml version="1.0" encoding="utf-8"?>
      <network-security-config>
          <base-config cleartextTrafficPermitted="true" />
      </network-security-config>
      
    2. 修改AndroidManifest.xml, application中添加属性android:networkSecurityConfig="@xml/network_security_config"
      <application
          android:allowBackup="true"
          android:icon="@mipmap/ic_launcher"
          android:label="@string/app_name"
          android:networkSecurityConfig="@xml/network_security_config"