可以说计算机网络,就是玩那几层中的那些协议们,本层玩,本层玩完了跨层玩,跨层玩,跨层玩完了本层玩…不过上一篇网络分层后,还有些细节得好好看一下,比如:
PART1-1:HTTP:HTTP 协议是基于 TCP 协议实现的,它是一个超文本传输协议,其实就是一个简单的请求-响应协议(主要是负责点对点之间通信)HTTP 协议指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应

  • HTTP 协议叫做超文本传输协议:

    • 超文本就是用超链接的方法,将各种不同空间的文字信息组织在一起的网状文本。比如说html,内部定义了很多图片视频的链接,放在浏览器上就呈现出了画面。
    • 协议就是约定俗称的东西彼此之间共同约定好的就叫做协议
    • 传递的这个过程就是运输
  • HTTP协议特点:
    • HTTP 是一个 无状态(stateless)协议【HTTP的无状态这个特点是一把双刃剑】,也就是说服务器不维护任何有关客户端过去所发请求的消息。这其实是一种懒政,有状态协议会更加复杂,需要维护状态(历史信息),而且如果客户或服务器失效,会产生状态的不一致,解决这种不一致的代价更高,

      • 所以HTTP无状态的有点就是省了服务器不用记录维护状态信息,很轻松。
      • 缺点就是遇到有关联的操作时比较麻烦。解决方法是用Cookie技术【Cookie 通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态
    • HTTP 协是基于 TCP协议,发送 HTTP 请求之前首先要建立 TCP 连接也就是要经历 3 次握手。面向连接的
    • 长连接的,目前使用的 HTTP 协议大部分都是 1.1。在 1.1 的协议里面,默认是开启了 Keep-Alive 的,这样的话建立的连接就可以在多次请求中被复用了
    • HTTP比较灵活,和Spring一样,支持自改他改【HTTP协议里的各类请求方法、URI/URL、状态码、头字段等每个组成要求都没有被固定死,都允许开发人员自定义和扩充;HTTP 由于是工作在应用层( OSI 第七层),则它下层可以随意变化,比如HTTPS 也就是在 HTTP 与 TCP 层之间增加了 SSL/TLS 安全传输层,HTTP/3 甚至把 TCP 层换成了基于 UDP 的 QUIC
    • 明文传输:通过浏览器的 F12 控制台或 Wireshark 抓包都可以直接肉眼查看,为我们调试工作带了极大的便利性,但是缺点就是裸奔带来的坏处【HTTP 的下面三个安全问题,可以用 HTTPS 的方式解决,也就是通过引入 SSL/TLS 层,使得在安全上达到了极致。】
      • 没有加密,容易被人窃取
      • 没有角色认证,通信双方可能会被伪装
      • 没有验证报文的完整性,所以有可能信息被修改
  • HTTP常见的状态码有哪些?

    • 1xx:服务器收到请求,需要请求者继续执行操作,用的比较少
    • 2xx:成功,操作被成功接收并处理
      • 200:服务器已 成功 处理了请求。 通常,这表示服务器提供了请求的网页
      • 204 No Content也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据
      • 206 Partial Content是应用于 HTTP 分块下载或断点续传,表示 响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态
    • 3xx:重定向,需要进一步的操作以完成请求
      • 301 : (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置
      • 302:(临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
        • 状态码301和302的区别是什么?

          • 共同点:301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)
          • 重定向原因:或者说为什么要重定向
            • 网站调整(如改变网页目录结构);
            • 网页被移到一个新地址;
            • 网页扩展名改变(如应用需要把.php改成.Html或.shtml)
          • 不同点:301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是 临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO中302好于301。
      • 304 Not Modified不具有跳转的含义,304表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉 客户端可以继续使用缓存资源,用于缓存控制
    • 4xx:客户端错误,请求包含语法错误无法完成请求
      • 400 :客户端请求有语法错误,不能被服务器所理解。
      • 403 :服务器收到请求,但是拒绝提供服务,也就是服务器禁止客户端访问资源。
      • 404 :(未找到) 服务器找不到请求的网页,没办法提供给客户端资源。
    • 5xx:服务器错误,服务器在处理请求的过程中发生了错误
      • 500: (服务器内部错误) 服务器遇到错误,无法完成请求。
      • 501 Not Implemented表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思
      • 502 Bad Gateway通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误
      • 503 Service Unavailable表示服务器当前很忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”的意思
  • HTTP 常用的请求方式?

    • GET请求和POST请求的区别?(其实常用的请求方法也就是GET方法和POST方法)

      • GET使用URL或Cookie传参,而POST将数据放在BODY中”,这个是因为HTTP协议用法的约定
      • GET方式提交的数据有长度限制,则POST的数据则可以非常大”,这个是因为它们使用的操作系统和浏览器设置的不同引起的区别
        • GET,在获取URI指定的信息时,如果URI指定的是文件则返回文件的内容,如果URI指定的是CGI程序,则返回该程序中的输出数据
      • POST比GET安全,因为数据在地址栏上不可见”,这个说法没毛病,但依然不是GET和POST本身的区别(GET和POST最大的区别主要是GET请求是幂等性的,POST请求不是。这个是它们本质区别。)
        • 幂等性是指一次和多次请求某一个资源或者说多次执行相同的操作,结果都是相同的。简单来说意味着对同一URL的多个请求应该返回同样的结果

          • GET 方法就是安全且幂等的,因为GET 方法它是只读操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。所以,可以对 GET 请求的数据做缓存,这个缓存可以做到浏览器本身上(彻底避免浏览器发请求),也可以做到代理上(如nginx),而且在浏览器中 GET 请求可以保存为书签

            • 芋道源码老师的Nginx 的 5 大应用场景:Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署;反向代理应该是Nginx使用最多的功能了,反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。【简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已】
          • POST 因为是新增或提交数据的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。所以,浏览器一般不会缓存 POST 请求,也不能把 POST 请求保存为书签。
        • 在 HTTP 协议里,所谓的 安全是指请求方法不会破坏服务器上的资源
    • GET:
      • 一般当我们访问Web服务器获取网页数据时使用的就是GET方法【请求从服务器获取特定资源。举个例子:GET /users(获取所有学生)】:访问过程大概是这样的

        • 首先在请求消息中写上GET方法
        • 然后在URI中写上存放网页数据的文件名,比如“/aaa/file1.html”(这样就表示我们需要获取/aaa/file1.html这个路径下的这个文件中的数据)
        • 当Web服务器收到消息后会打开/aaa/file1.html文件并读取出里面的数据,然后把读出的数据存放到响应消息中,返回给客户端
        • 最后客户端浏览器会收到这些数据并显示在屏幕上
      • HTTP之GET在咱们Spring框架中的体现方式:
    • POST:另一个经常用的方法是POST【在服务器上创建一个新的资源。举个例子:POST /users(创建学生)
      • 我们一般在表单中填写数据并将其发送给Web服务器时就会用POST方法

        • 常见的比如说,网上购物填写收货地址、姓名…
        • 再比如就是网上填写调查问卷等带有输入框的网页,这些可以输入信息的部分就是表单
      • HTTP之POST在咱们Spring框架中的体现方式:
        • @PostMapping("users") 等价于@RequestMapping(value="/users",method=RequestMethod.POST)

          @PostMapping("/users")
          public ResponseEntity<User> createUser(@Valid @RequestBody UserCreateRequest userCreateRequest) {return userRespository.save(userCreateRequest);
          }
          
    • PUT :更新服务器上的资源(客户端提供更新后的整个资源)。举个例子:PUT /users/12(更新编号为 12 的学生)
      • HTTP之PUT在咱们Spring框架中的体现方式:

        • @PutMapping("/users/{userId}") 等价于@RequestMapping(value="/users/{userId}",method=RequestMethod.PUT)

          @PutMapping("/users/{userId}")
          public ResponseEntity<User> updateUser(@PathVariable(value = "userId") Long userId,@Valid @RequestBody UserUpdateRequest userUpdateRequest) {......
          }
          
    • DELETE :从服务器删除特定的资源。举个例子:DELETE /users/12(删除编号为 12 的学生)
      • HTTP之DELETE在咱们Spring框架中的体现方式:

        • @DeleteMapping(“/users/{userId}”)等价于@RequestMapping(value=“/users/{userId}”,method=RequestMethod.DELETE)
    • PATCH :更新服务器上的资源(客户端提供更改的属性,可以看做作是部分更新),使用的比较少
      • HTTP之PATCH 在咱们Spring框架中的体现方式:

        • 一般都是 PUT 不够用了之后才用 PATCH 请求去更新数据。
        @PatchMapping("/profile")public ResponseEntity updateStudent(@RequestBody StudentUpdateRequest studentUpdateRequest) {studentRepository.updateDetail(studentUpdateRequest);return ResponseEntity.ok().build();}
        
  • HTTP 缓存:【对于一些具有 重复性的 HTTP 请求,比如每次请求得到的数据都一样的,我们可以 把这对请求-响应的数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应了,HTTP性能就能有所提高(HTTP 协议的头部有不少是针对缓存的字段)】
    • 缓存的实现:客户端会把第一次请求以及响应的数据保存在本地磁盘上,其中将请求的 URL 作为 key,而响应作为 value,两者形成映射关系。这样当后续发起相同的请求时,就可以先在本地磁盘上通过 key 查到对应的 value,也就是响应,如果找到了,就直接从本地读取该响应。而 为了防止缓存过期:服务器在发送 HTTP 响应时,会估算一个过期的时间,并把这个信息放到响应头部中,这样客户端在查看响应头部的信息时,一旦发现缓存的响应是过期的,则就会重新发送网络请求
    • HTTP 缓存有两种实现方式,分别是强制缓存和协商缓存:
      • 强缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。

        • 强缓存是 利用【Cache-Control, 是一个相对时间、Expires,是一个绝对时间】这两个 HTTP 响应头部(Response Header)字段实现的,它们都用来表示资源在客户端缓存的有效期:
      • 当我们在浏览器使用开发者工具的时候,可能会看到过某些请求的响应码是 304,这个是告诉浏览器可以使用本地缓存的资源,通常这种通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存协商缓存就是与服务端协商之后,通过协商结果来判断是否使用本地缓存。】
        • 协商缓存可以基于请求头部中的 If-Modified-Since 字段与响应头部中的 Last-Modified 字段组合或者请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段组合来实现。
        • 使用Etag字段实现的协商缓存的过程

          • 只需要客户端在重新发送请求时,在请求的 Etag 头部带上第一次请求的响应头部中的摘要,这个摘要是唯一标识响应的资源,当服务器收到请求后,会将本地资源的摘要与请求中的摘要做个比较。如果不同,那么说明客户端的缓存已经没有价值,服务器在响应中带上最新的资源。如果相同,说明客户端的缓存还是可以继续使用的,那么服务器仅返回不含有包体的 304 Not Modified 响应,告诉客户端仍然有效,这样就可以减少响应资源在网络中传输的延时
  • HTTP长连接和短连接?—HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接
    • 在HTTP/1.0中,默认使用的是短连接。也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。【当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS 文件等),每遇到这样一个 Web 资源,浏览器就会重新建立一个TCP连接,这样就会导致有大量的“握手报文”和“挥手报文”占用了带宽。】
    • 从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:Connection:keep-alive为了解决 HTTP/1.0 存在的资源浪费的问题, HTTP/1.1 优化为默认长连接模式 。 采用长连接模式的请求报文会通知服务端:“我向你请求连接,并且连接成功建立后,请不要关闭”。因此,该TCP连接将持续打开,为后续的客户端-服务端的数据交互服务。也就是说在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。】
      • 在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。【如果 TCP 连接一直保持的话也是对资源的浪费,因此,一些服务器软件(如 Apache)还会支持超时时间的时间。在超时时间之内没有新的请求达到,TCP 连接才会被关闭。HTTP/1.0仍提供了长连接选项,即在请求头中加入Connection: Keep-alive。同样的,在HTTP/1.1中,如果不希望使用长连接选项,也可以在请求头中加入Connection: close,这样会通知服务器端:“我不需要长连接,连接成功后即可关闭”。】所以Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接要客户端和服务端都支持长连接。HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。】
      • HTTP1.0和HTTP1.1的六个区别?

        • 长连接

          • HTTP 1.1支持长连接(Persistent Connection)【持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态,当然,如果某个 HTTP 长连接超过一定时间没有任何数据交互,服务端就会主动断开这个连接】和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的性能消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
          • 早期 HTTP1.0 的每一次请求都伴随着一次三次握手的过程,并且是串行的请求,增加了不必要的性能开销
        • 缓存处理:
          • 在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP/1.0提供的缓存机制非常简单。服务器端使用Expires标签来标志(时间)一个响应体,在Expires标志时间内的请求,都会获得该响应体缓存。服务器端在初次返回给客户端的响应体中,有一个Last-Modified标签,该标签标记了被请求资源在服务器端的最后一次修改。在请求头中,使用If-Modified-Since标签,该标签标志一个时间,意为客户端向服务器进行问询:“该时间之后,我要请求的资源是否有被修改过?”通常情况下,请求头中的If-Modified-Since的值即为上一次获得该资源时,响应体中的Last-Modified的值

            • 如果服务器接收到了请求头,并判断If-Modified-Since时间后,资源确实没有修改过,则返回给客户端一个304 not modified响应头,表示”缓冲可用,你从浏览器里拿吧!”。
            • 如果服务器判断If-Modified-Since时间后,资源被修改过,则返回给客户端一个200 OK的响应体,并附带全新的资源内容,表示”你要的我已经改过的,给你一份新的”。
          • HTTP1.1则引入了更多的缓存控制策略,例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等可供选择的缓存头来控制缓存策略。
        • 管道:pipeline
          • HTTP1.0 只有串行发送,没有管道
          • HTTP1.1 增加了管道的概念【这就是由于HTTP/1.1 采用了长连接的方式,才能有管道这个新玩意】,使得在同一个 TCP 链接当中可以同时发出多个请求【即可在同一个 TCP 连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。但是服务器必须按照接收请求的顺序发送对这些管道化请求的响应。】
            • 如果 服务端在处理 A 请求时耗时比较长,那么后续的请求的处理都会被阻塞住,这称为「队头堵塞」。所以,HTTP/1.1 管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞
        • 压缩:
        • 断点续传:
          • HTTP1.0 不支持断点续传,并且存在一些浪费带宽的现象(HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了
          • HTTP1.1 则在请求头引入了range头域,用来指定数据字节位置,它允许只请求资源的某个部分,即返回码是206(Partial Content),开启了断点续传的时代。并且这样就方便了开发者自由的选择以便于充分利用带宽和连接。**【HTTP/1.1引入了范围请求(range request)机制,以避免带宽的浪费。当客户端想请求一个文件的一部分,或者需要继续下载一个已经下载了部分但被终止的文件,HTTP/1.1可以在请求中加入Range头部,以请求(并只能请求字节型数据)数据的一部分。服务器端可以忽略Range头部,也可以返回若干Range响应。如果一个响应包含部分数据的话,那么将带有206 (Partial Content)状态码。该状态码的意义在于避免了HTTP/1.0代理缓存错误地把该响应认为是一个完整的数据响应,从而把他当作为一个请求的响应缓存。在范围响应中,Content-Range头部标志指示出了该数据块的偏移量和数据块的长度】
        • 错误通知的管理(错误状态响应码):在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
          • HTTP/1.0仅定义了16种状态码。HTTP/1.1中新加入了大量的状态码,光是错误响应状态码就新增了24种。比如说,100 (Continue)——在请求大资源前的预热请求,206 (Partial Content)——范围请求的标识码,409 (Conflict)——请求与当前资源的规定冲突,410 (Gone)——资源已被永久转移,而且没有任何已知的转发地址。

            • HTTP/1.1中新加入了状态码100。该状态码的使用场景为,存在某些较大的文件请求,服务器可能不愿意响应这种请求,此时状态码100可以作为指示请求是否会被正常响应
            • 然而在HTTP/1.0中,并没有100 (Continue)状态码,要想触发这一机制,可以发送一个Expect头部,其中包含一个100-continue的值
        • Host头处理:

          • 在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址(HTTP1.0 任务主机只有一个节点),因此,请求消息中的URL并没有传递主机名(hostname)(也就是并没有传 HOST)。
          • HTTP1.1 时代,虚拟机技术越来越发达,一台机器上也有可能有很多节点,故增加了 HOST 信息但随着虚拟主机技术的发展,因为在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
        • 至此,虽然说了HTTP1.1相对于HTTP1.0的升级,但是HTTP1.1还是有性能瓶颈或者说性能问题:HTTP/1.1 的高延迟,影响用户体验
          • 请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大。只能压缩 Body 的部分。发送冗长的首部。每次互相发送相同的首部造成的浪费较多

            • 由于 HTTP 协议是无状态的,每一个请求都得携带 HTTP 头部,特别是对于有携带 cookie 的头部,而 cookie 的大小通常很大
          • 服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是 队头阻塞。没有请求优先级控制【同一连接只能在完成一个 HTTP 事务(请求和响应)后,才能处理下一个事务
          • 请求只能从客户端开始,服务器只能被动响应
        • 上面说完了HTTP1.1的可以算是优缺点,而下面的HTTP2.0也做了一定的升级,但咱们还是要总结一下,HTTP/1.1 优化点有几个呢【下面虽然说优化了HTTP1.1,但是HTTP1.1一些关键的地方或者说缺点问题是没办法优化的,比如请求-响应模型、头部巨大且重复、并发连接耗时、服务器不能主动推送等,要改变这些必须重新设计 HTTP 协议,于是 HTTP/2 就出来了】:
          • 尽量避免发送 HTTP 请求

            • 避免发送 HTTP 请求的方法就是通过 HTTP 协议的缓存技术

              • 对于一些具有重复性的 HTTP 请求,比如每次请求得到的数据都一样的,我们 可以把这对请求-响应的数据都缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应了
              • HTTP 协议的缓存实现方式:客户端会 把第一次请求以及响应的数据保存在本地磁盘上,其中将请求的 URL 作为 key,而响应作为 value,两者形成映射关系。这样 当后续发起相同的请求时,就可以先在本地磁盘上通过 key 查到对应的 value,也就是响应,如果找到了,就直接从本地读取该响应。
            • 防止缓存过期:
              • 服务器在发送 HTTP 响应时,会估算一个过期的时间,并把这个信息放到响应头部中,这样客户端在查看响应头部的信息时,一旦发现缓存的响应是过期的,则就会重新发送网络请求
              • 实现方式:
                • 客户端在重新发送请求时,在请求的 Etag 头部带上第一次请求的响应头部中的摘要,这个摘要是唯一标识响应的资源,当服务器收到请求后,会将本地资源的摘要与请求中的摘要做个比较。如果不同,那么说明客户端的缓存已经没有价值,服务器在响应中带上最新的资源。如果相同,说明客户端的缓存还是可以继续使用的,那么服务器仅返回不含有包体的 304 Not Modified 响应,告诉客户端仍然有效,这样就可以减少响应资源在网络中传输的延时
          • 在需要发送 HTTP 请求时,考虑如何减少请求次数
            • 减少重定向请求次数

              • 如果重定向请求越多,那么客户端就要多次发起 HTTP 请求,每一次的 HTTP 请求都得经过网络,这无疑会越降低网络性能。
              • 如果重定向的工作交由代理服务器完成,就能减少 HTTP 请求次数了,而且当代理服务器知晓了重定向规则后,可以进一步减少消息传递次数,
            • 合并请求【但是这样的合并请求会带来新的问题,当大资源中的某一个小资源发生变化后,客户端必须重新下载整个完整的大资源文件,这显然带来了额外的网络消耗
              • 如果 把多个访问小文件的请求合并成一个大的请求,虽然传输的总资源还是一样,但是减少请求,也就意味着 减少了重复发送的 HTTP 头部。【另外由于 HTTP/1.1 是请求响应模型,如果第一个发送的请求,未收到对应的响应,那么后续的请求就不会发送,于是为了防止单个请求的阻塞,所以一般浏览器会同时发起 5-6 个请求,每一个请求都是不同的 TCP 连接,那么如果合并了请求,也就会减少 TCP 连接的数量,因而省去了 TCP 握手和慢启动过程耗费的时间。】
              • 具体合并方法:
                • 比如服务端使用 webpack 等打包工具将 js、css 等资源合并打包成大文件以减少 HTTP 请求的次数,从而减少网络的开销。
                • 还可以将图片的二进制数据用 base64 编码后,以 URL 的形式潜入到 HTML 文件,跟随 HTML 文件一并发送。这样客户端收到 HTML 后,就可以直接解码出数据,然后直接显示图片,就不用再发起图片相关的请求,这样便减少了请求的次数。
            • 延迟发送请求
              • 一般 HTML 里会含有很多 HTTP 的 URL,当前不需要的资源,我们没必要也获取过来,于是可以通过按需获取的方式,来减少第一时间的 HTTP 请求次数请求网页的时候,没必要把全部资源都获取到,而是只获取当前用户所看到的页面资源,当用户向下滑动页面的时候,再向服务器获取接下来的资源,这样就达到了延迟发送请求的效果
          • 减少服务器的 HTTP 响应的数据大小【HTTP2.0不就进行了头部压缩嘛】,通过两种压缩方式:
            • 无损压缩:无损压缩是指资源经过压缩后,信息不被破坏,还能完全恢复到压缩前的原样。gzip 就是比较常见的无损压缩。

              • 首先,我们针对代码的语法规则进行压缩,因为通常代码文件都有很多换行符或者空格,这些是为了帮助程序员更好的阅读,但是机器执行时并不要这些符,把这些多余的符号给去除掉。然后需要对原始资源建立统计模型,利用这个统计模型,将常出现的数据用较短的二进制比特序列表示,将不常出现的数据用较长的二进制比特序列表示,生成二进制比特序列一般是霍夫曼编码算法。
            • 有损压缩
              • 解压的数据会与原始数据不同但是非常接近。有损压缩主要将次要的数据舍弃,牺牲一些质量来减少数据量、提高压缩比,这种方法经常用于压缩多媒体数据,比如音频、视频、图片
              • 可以通过 HTTP 请求头部中的 Accept 字段里的 q 质量因子,告诉服务器期望的资源质量。Accept: audio/*; q=0.2, audio/basic
      • HTTP1.1和 HTTP2.0的区别?【HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的,协议升级有一个很重要的地方,就是要兼容老版本的协议,否则新协议推广起来就相当困难,所幸 HTTP/2 做到了兼容 HTTP/1.1

        • HTTP2.0相比HTTP1.1支持的特性:

          • 新的二进制格式

            • HTTP1.1的解析是基于文本,也就是采用明文的形式。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,
            • HTTP/2 全⾯采⽤了⼆进制格式,头信息和数据体都是⼆进制【一条 HTTP 响应,划分成了两类帧来传输,并且采用二进制来编码】:二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮
              • 头信息和数据体都是二进制,并且统称为帧(frame):头信息帧(Headers Frame)和数据帧(Data Frame),这样对用户不友好但是对计算机很友好,计算机收到报文后直接解析二进制报文,这增加了数据传输的效率
              • 将 HTTP/1 的文本格式改成二进制格式传输数据,极大提高了 HTTP 传输效率,而且二进制数据使用位运算能高效解析
          • 多路复用,即连接共享,即 每一个request都是用作连接共享机制的一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
            • HTTP/1.1 的实现是基于请求-响应模型的。HTTP/1.1 的同一个连接中,HTTP 完成一个事务(请求与响应),才能处理下一个事务,也就是说在发出请求等待响应的过程中,是没办法做其他事情的,如果响应迟迟不来,那么后续的请求是无法发送的,也造成了队头阻塞的问题。
            • HTTP/2 通过 Stream 这个设计,多个 Stream 复用一条 TCP 连接,达到并发的效果,解决了 HTTP/1.1 队头阻塞的问题,提高了 HTTP 传输的吞吐量。

              • 在⼀个连接中,服务器收到了客户端 A 和 B 的两个请求,但是发现在处理 A 的过程中⾮常耗时,索性就先回应 A 已经处理好的部分,再接着回应 B 请求,最后再回应 A 请求剩下的部分。HTTP/2 可以在⼀个连接中并发处理多个请求或回应。相当于说HTTP/2移**除了 HTTP/1.1 中的串行请求,不需要排队等待,也就不会再出现「队头阻塞」问题**,降低了延迟,大幅度提高了连接的利用率。
              • 在 HTTP/2 连接上,不同 Stream 的帧是可以乱序发送的(因此可以并发不同的 Stream ),因为每个帧的头部会携带 Stream ID 信息,所以接收端可以通过 Stream ID 有序组装成 HTTP 消息,而同一 Stream 内部的帧必须是严格有序的。同一个连接中的 Stream ID 是不能复用的,只能顺序递增,所以当 Stream ID 耗尽时,需要发一个控制帧 GOAWAY,用来关闭 TCP 连接。
              • 客户端和服务器双方都可以建立 Stream, Stream ID 也是有区别的,客户端建立的 Stream 必须是奇数号,而服务器建立的 Stream 必须是偶数号。
              • HTTP/2 还可以对每个 Stream 设置不同优先级,帧头中的「标志位」可以设置优先级,比如客户端访问 HTML/CSS 和图片资源时,希望服务器先传递 HTML/CSS,再传图片,那么就可以通过设置 Stream 的优先级来实现,以此提高用户体验
          • 头部压缩
            • HTTP1.1的头部(header)带有大量信息,比如Cookie、User Agent、Accept 等,而且每次都要重复发送;

              • HTTP 协议的报文是由「Header + Body」构成的,对于 Body 部分,HTTP/1.1 协议可以使用头字段 「Content-Encoding」指定 Body 的压缩方式,比如用 gzip 压缩,这样可以节约带宽,但报文中的另外一部分 Header,HTTP/1.1 协议是没有针对它的优化手段
            • HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小在 HTTP2 当中,如果你发出了多个请求,并且它们的头部(header)是相同的,那么 HTTP2 协议会帮你消除同样的部分。(其实就是在客户端和服务端维护一张索引表来实现)
              • 这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了
              • HTTP/2 没使用常见的 gzip 压缩方式来压缩头部,而是开发了 HPACK 算法,HPACK 算法主要包含三个组成部分:静态字典【HTTP/2 为高频出现在头部的字符串和字段建立了一张静态表,它是写入到 HTTP/2 框架里的,不会变化的,静态表里共有 61 组。表中的 Index 表示索引(Key),Header Value 表示索引对应的 Value,Header Name 表示字段的名字】、动态字典、Huffman 编码(压缩算法)【客户端和服务器两端都会建立和维护「字典」,用长度较小的索引号表示重复的字符串,再用 Huffman 编码压缩数据,可达到 50%~90% 的高压缩率
          • 服务端推送:服务器除了对最初请求的响应外,服务器还可以额外的向客户端推送资源(服务器可以主动向客户端发送请求),而无需客户端明确的请求。
            • 这个的应用就比如说客户端通过 HTTP/1.1 请求从服务器那获取到了 HTML 文件,而 HTML 可能还需要依赖 CSS 来渲染页面,这时客户端还要再发起获取 CSS 文件的请求。在 HTTP/2 中,客户端在访问 HTML 时,服务器可以直接主动推送 CSS 文件,减少了消息传递的次数。
          • 数据流:HTTP/2 的数据包不是按顺序发送的,同⼀个连接⾥⾯连续的数据包,可能属于不同的回应。(对数据包做了标记,标志其属于哪一个请求,其中规定客户端发出的数据流编号为奇数,服务器发出的数据流编号为偶数。客户端还可以指定数据流的优先级,优先级⾼的请求,服务器就先响应该请求)
            • 在 HTTP/2 中每个请求或响应的所有数据包,称为一个数据流(Stream)。每个数据流都标记着一个独一无二的编号(Stream ID),不同 Stream 的帧是可以乱序发送的(因此可以并发不同的 Stream ),因为每个帧的头部会携带 Stream ID 信息,所以接收端可以通过 Stream ID 有序组装成 HTTP 消息。客户端和服务器双方都可以建立 Stream, Stream ID 也是有区别的,客户端建立的 Stream 必须是奇数号,而服务器建立的 Stream 必须是偶数号
        • 以上,吹完了HTTP/2,那他有啥缺点吗,肯定是有的。HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,看似很完美了,但是 HTTP/2 还是存在“队头阻塞”的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层
          • HTTP/2 队头阻塞问题:HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据。或者说中间有一个包丢了或者超时了,那就得触发TCP的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来
      • HTTP3.0和 HTTP2.0的区别?【HTTP/2 队头阻塞的问题是因为 TCP,所以 HTTP/3 把 HTTP 下层的 TCP 协议改成了 UDP

        • 协议不同:

          • HTTP2 是基于 TCP 协议实现的
          • HTTP3 是基于 UDP 协议实现的【基于 UDP 协议在应用层实现了 QUIC 协议
            • UDP 是不可靠传输的,但基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输UDP 是不需要连接的,也就不需要握手和挥手的过程,所以天然的就比 TCP 快
        • QUIC:HTTP3 新增了 QUIC 协议来实现可靠性的传输,而QUIC正是有下面三个特点自己才很牛逼,可以实现可靠性传输呀
          • 正是因为HTTP/2有三个缺陷【HTTP/2 通过头部压缩、二进制编码、多路复用、服务器推送等新特性大幅度提升了 HTTP/1.1 的性能,而美中不足的是 HTTP/2 协议是基于 TCP 实现的】,才有了HTTP3的三个特点:

            • 队头阻塞

              • HTTP/2 多个请求是跑在一个 TCP 连接中的,那么当 TCP 丢包时,整个 TCP 都要等待重传,那么就会阻塞该 TCP 连接中的所有请求【因为 TCP 是字节流协议TCP 层必须保证收到的字节数据是完整且有序的,如果序列号较低的 TCP 段在网络传输中丢失了,即使序列号较高的 TCP 段已经被接收了,应用层也无法从内核中读取到这部分数据,当然,这种问题是在 TCP 层面发生的,从 HTTP 视角看,就是请求被阻塞了。】
            • TCP 与 TLS 的握手时延迟
              • 另外, TCP 由于具有「拥塞控制」的特性,所以刚建立连接的 TCP 会有个「慢启动」的过程,它会对 TCP 连接产生"减速"效果
            • 网络迁移需要重新连接,这个问题都是 TCP 协议固有的问题,无论应用层的 HTTP/2 在怎么设计都无法逃脱。要解决这个问题,就必须把传输层协议替换成 UDP,HTTP3做到了
              • 一个 TCP 连接是由四元组(源 IP 地址,源端口,目标 IP 地址,目标端口)确定的,这意味着如果 IP 地址或者端口变动了,就会导致需要 TCP 与 TLS 重新握手
          • QUIC 有 3 个特点:
            • 无队头阻塞:

              • QUIC 协议也有类似 HTTP/2 Stream 与多路复用的概念,也是可以在同一条连接上并发传输多个 Stream,Stream 可以认为就是一条 HTTP 请求QUIC 有自己的一套机制可以保证传输的可靠性的。当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题。这与 HTTP/2 不同,HTTP/2 只要某个流中的数据包丢失了,其他流也会因此受影响。
              • QUIC 协议会保证数据包的可靠性,每个数据包都有一个序号唯一标识。当某个流中的一个数据包丢失了,即使该流的其他数据包到达了,数据也无法被 HTTP/3 读取,直到 QUIC 重传丢失的报文,数据才会交给 HTTP/3。而其他流的数据报文只要被完整接收,HTTP/3 就可以读取到数据。这与 HTTP/2 不同,HTTP/2 只要某个流中的数据包丢失了,其他流也会因此受影响
              • 另外,HTTP/3 同 HTTP/2 一样采用二进制帧的结构,不同的地方在于 HTTP/2 的二进制帧里需要定义 Stream,而 HTTP/3 自身不需要再定义 Stream,直接使用 QUIC 里的 Stream,于是 HTTP/3 的帧的结构也变简单了,HTTP/3 帧头只有两个字段:类型和长度。
            • 更快的连接建立:
              • 对于 HTTP/1 和 HTTP/2 协议,TCP 和 TLS 是分层的,分别属于内核实现的传输层、openssl 库实现的表示层,因此它们难以合并在一起,需要分批次来握手,先 TCP 握手,再 TLS 握手。HTTP/3 在传输数据前虽然需要 QUIC 协议握手,这个握手过程只需要 1 RTT,握手的目的是为确认双方的「连接 ID」,连接迁移就是基于连接 ID 实现的【HTTP/3 的 QUIC 协议并不是与 TLS 分层,而是QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的“记录”,再加上 QUIC 使用的是 TLS/1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商。甚至在第二次连接的时候,应用数据包可以和 QUIC 握手信息(连接信息 + TLS 信息)一起发送,达到 0-RTT 的效果。】
            • 连接迁移【QUIC 是一个在 UDP 之上的伪 TCP + TLS + HTTP/2 的多路复用的协议】
            • 当然,除了上面三个特点还有其他优点,QUIC是基于UDP实现的应用层协议,它也具有类似 TCP 的连接管理、拥塞窗口、流量控制的网络特性,所以不用担心数据包丢失的问题
        • 握手次数:
          • HTTP2 是基于 HTTPS 实现的,建立连接需要先进行 TCP 3次握手,然后再进行 TLS 3次握手,总共6次握手
          • HTTP3 只需要 QUIC 的3次握手【基于 UDP 的 QUIC 协议 可以实现类似 TCP 的可靠性传输】
  • HTTP请求报文和响应报文的格式?

    • 请求报文格式:

      • 请求行(请求方法+URI协议+版本)
      • 请求头部
      • 空行
      • 请求主体
    • 响应报文:

      • 状态行(版本+状态码+原因短语)
      • 响应首部
      • 空行
      • 响应主体

扩展:HTTP中主要的头字段:

  • HTTP 与 HTTPS 的区别?【HTTPS 协议(Hyper Text Transfer Protocol Secure),是 HTTP 的加强安全版本。HTTPS 是基于 HTTP 的,也是用 TCP 作为底层协议,并额外使用 SSL/TLS 协议用作加密和安全认证。默认端口号是 443.】

    • 1).SSL安全协议:【SSL 和 TLS 没有太大的区别。SSL 指安全套接字协议(Secure Sockets Layer),首次发布与 1996 年。SSL 的首次发布其实已经是他的 3.0 版本,SSL 1.0 从未面世,SSL 2.0 则具有较大的缺陷(DROWN 缺陷——Decrypting RSA with Obsolete and Weakened eNcryption)。很快,在 1999 年,SSL 3.0 进一步升级,新版本被命名为 TLS 1.0。因此,TLS 是基于 SSL 之上的,但由于习惯叫法,通常把 HTTPS 中的核心加密协议混成为 SSL/TLS【】】

      • 上面咱们说了HTTP的三个缺点:

        • 没有加密,明文容器被窃取
        • 没有角色认证,通信双方容易被伪装
        • 没有检验报文的完整性,所以有可能信息被修改,被增加一句或者删除一句之类的
      • 所以HTTPS应运而生,解决上面的三个风险:
        • HTTPS加密过程:
        • HTTPS 采用的是对称加密和非对称加密结合的混合加密的方式实现信息的机密性,解决了窃取的风险

          • 在通信建立前采用非对称加密的方式交换会话秘钥,后续就不再使用非对称加密---->在通信过程中全部使用对称加密的会话秘钥的方式加密明文数据,具体见下:
        • 将服务器公钥放入到数字证书中,解决了冒充伪装角色的风险
          • 个人信息 + 公钥 + 数字签名打包成一个数字证书,防近亲伪造

            • 在计算机里,这个可以颁发数字证书的权威的机构就是 CA (数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的
        • 摘要算法的方式来实现完整性,它能够为数据生成独一无二的指纹,指纹用于校验数据的完整性,解决了篡改的风险。
          • HTTPS 的应用数据保证完整性的办法:
          • 在计算机里会用摘要算法(哈希函数)来计算出内容的哈希值,也就是内容的指纹,这个哈希值是唯一的,且无法通过哈希值推导出内容。通过哈希算法可以确保内容不会被篡改,但是并不能保证「内容 + 哈希值」不会被中间人替换,因为这里缺少对客户端收到的消息是否来源于服务端的证明【比如仿照请假条上的监护人签字】,所以引入了数字签名算法。【用非对称加密算法,共有两个密钥,这两个密钥可以双向加解密的,比如可以用公钥加密内容,然后用私钥解密,也可以用私钥加密内容,公钥解密内容。私钥是由服务端保管,然后服务端会向客户端颁发对应的公钥。如果客户端收到的信息能被公钥解密,就说明该消息是由服务器发送的。】
      • SSL/TLS 的工作原理:【在双方通信之前,需要商量一个用于对称加密的密钥。我们知道网络通信的信道是不安全的,传输报文对任何人是可见的,密钥的交换肯定不能直接在网络信道中传输。因此,使用非对称加密,对对称加密的密钥进行加密,保护该密钥不在网络信道中被窃听。这样,通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性
        • 非对称加密:SSL/TLS 的核心要素是非对称加密非对称加密采用两个密钥——一个公钥,一个私钥。在通信时,私钥仅由解密者保存,公钥由任何一个想与解密者通信的发送者(加密者)所知。

          • 非对称加密的公钥和私钥需要采用一种复杂的数学机制生成(密码学认为,为了较高的安全性,尽量不要自己创造加密方案)。公私钥对的生成算法依赖于单向陷门函数

          • 根据私钥生成的方式,DH 算法分为两种实现:
            • static DH 算法,已废弃

              • static DH 算法里有一方的私钥是静态的,也就说每次密钥协商的时候有一方的私钥都是一样的,一般是服务器方固定,即 a 不变,客户端的私钥则是随机生成的
            • DHE 算法,现在常用的
              • 双方的私钥在每次密钥交换通信时,都是随机生成的、临时的,这个方式也就是 DHE 算法,E 全称是 ephemeral(临时性的)。【每个通信过程的私钥都是没有任何关系的,都是独立的,这样就保证了前向安全】
        • 对称加密:【通信双方共享唯一密钥 k,加解密算法已知,加密方利用密钥 k 加密,解密方利用密钥 k 解密,保密性依赖于密钥 k 的保密性。】使用 SSL/TLS 进行通信的双方需要使用非对称加密方案来通信,但是非对称加密设计了较为复杂的数学算法,在实际通信过程中,计算的代价较高,效率太低,因此,SSL/TLS 实际对消息的加密使用的是对称加密
        • 公钥传输的信赖性:客户端 C 和服务器 S 想要使用 SSL/TLS 通信,由上述 SSL/TLS 通信原理,C 需要先知道 S 的公钥,而 S 公钥的唯一获取途径,就是把 S 公钥在网络信道中传输。假设 S 公钥不做加密,在信道中传输,那么很有可能存在一个攻击者 A,发送给 C 一个诈包,假装是 S 公钥,其实是诱饵服务器 AS 的公钥。当 C 收获了 AS 的公钥(却以为是 S 的公钥),C 后续就会使用 AS 公钥对数据进行加密,并在公开信道传输,那么 A 将捕获这些加密包,用 AS 的私钥解密,就截获了 C 本要给 S 发送的内容,而 C 和 S 二人全然不知。同样的,S 公钥即使做加密,也难以避免这种信任性问题,C 被 AS 拐跑了!

          • 为了公钥传输的信赖性问题,第三方机构应运而生——证书颁发机构(CA,Certificate Authority)。CA 默认是受信任的第三方。CA 会给各个服务器颁发证书,证书存储在服务器上,并附有 CA 的电子签名【当客户端(浏览器)向服务器发送 HTTPS 请求时,一定要先获取目标服务器的证书,并根据证书上的信息,检验证书的合法性。一旦客户端检测到证书非法,就会发生错误。客户端获取了服务器的证书后,由于证书的信任性是由第三方信赖机构认证的,而证书上又包含着服务器的公钥信息,客户端就可以放心的信任证书上的公钥就是目标服务器的公钥。】

            • CA证书:HTTPS 协议需要向 CA(证书权威。机构)申请数字证书来保证服务器的身份是可信的。数字证书的作用,是用来认证公钥持有者的身份,以防止第三方进行冒充。说简单些,证书就是用来告诉客户端,该服务端是否是合法的,因为只有证书合法,才代表服务端身份是可信的

              • 一个数字证书包含了:
              • 为了让服务端的公钥被大家信任,服务端的证书都是由 CA (Certificate Authority,证书认证机构)签名的,CA 就是网络世界里的公安局、公证中心,具有极高的可信度,所以由它来给各个公钥签名,信任的一方签发的证书,那必然证书也是被信任的。之所以要签名,是因为签名的作用可以避免中间人在获取证书时对证书内容的篡改
            • 带有证书的公钥传输机制如下:

              • 设有服务器 S,客户端 C,和第三方信赖机构 CA。
              • S 信任 CA,CA 是知道 S 公钥的,CA 向 S 颁发证书。并附上 CA 私钥对消息摘要的加密签名。
              • S 获得 CA 颁发的证书,将该证书传递给 C。
              • C 获得 S 的证书,信任 CA 并知晓 CA 公钥,使用 CA 公钥对 S 证书上的签名解密,同时对消息进行散列处理,得到摘要。比较摘要,验证 S 证书的真实性。
              • 如果 C 验证 S 证书是真实的,则信任 S 的公钥(在 S 证书中)。
          • 数字签名,是 CA 在给服务器颁发证书时,使用散列+加密的组合技术,在证书上盖个章,以此来提供验伪的功能。

            • 数字证书签发和验证流程:
            • 有时候,证书的验证过程中还存在一个证书信任链的问题【这也是为了确保根证书的绝对安全性,将根证书隔离地越严格越好,不然根证书如果失守了,那么整个信任链都会有问题】,因为我们向 CA 申请的证书一般不是根证书签发的,而是由中间证书签发的,有中间人就存在多层验证的过程
      • HTTP 是超⽂本传输协议,信息是明⽂传输,存在安全⻛险的问题。
      • HTTPS 则解决 HTTP 不安全的缺陷,在TCP 和 HTTP ⽹络层之间加⼊了 SSL/TLS 安全协议,使得报⽂能够加密传输。
      • HTTPS 协议中,SSL 通道通常使用基于密钥的加密算法,密钥长度通常是 40 比特或 128 比特
    • 2).建立连接
      • HTTP 连接建⽴相对简单, TCP 三次握⼿之后便可进⾏ HTTP 的报⽂传输。
      • HTTPS 在 TCP 三次握⼿之后,还需进⾏ SSL/TLS 的握⼿过程,才可进⼊加密报⽂传输
        • SSL/TLS 握手阶段:

          • TLS 第一次握手:

            • 客户端首先会发一个Client Hello消息,这是 客户端跟服务器打招呼 的意思。
            • 消息里面有客户端使用的 TLS 版本号、支持的密码套件列表,以及生成的随机数(Client Random),这个随机数会被服务端保留,它是生成对称加密密钥的材料之一
          • TLS 第二次握手
            • 当服务端收到客户端的Client Hello消息后,确认 TLS 版本号是否支持,和从密码套件列表中选择一个密码套件,以及生成随机数(Server Random)。接着,服务端返回Server Hello消息,消息里面有服务器确认的 TLS 版本号,也给出了随机数(Server Random),然后从客户端的密码套件列表选择了一个合适的密码套件

              • 前面这两个客户端和服务端相互打招呼的过程或者说**前两握,客户端和服务端就已确认了 TLS 版本和使用的密码套件,而且客户端和服务端都会各自生成一个随机数,并且还会把随机数传递给对方。这两个随机数是后续作为生成会话密钥的条件,所谓的会话密钥就是数据传输时,所使用的对称加密密钥**
            • 然后,服务端为了证明自己的身份,会发送Server Certificate给客户端,这个消息里含有数字证书。
              • 客户端拿到了服务端的数字证书后也会进行验证服务端发来证明身份的数字证书是否有效。
            • 随后,服务端发了Server Hello Done消息,目的是 告诉客户端,我已经把该给你的东西都给你了,本次打招呼完毕
          • TLS 第三次握手
            • 客户端验证完证书后,认为可信则继续往下走。接着,客户端就会生成一个新的随机数 (pre-master),用服务器的 RSA 公钥加密该随机数,通过Change Cipher Key Exchange消息传给服务端。服务端收到后,用 RSA 私钥解密,得到客户端发来的随机数 (pre-master)。
            • 至此,客户端和服务端双方都共享了三个随机数,分别是 Client Random、Server Random、pre-master双方根据已经得到的三个随机数,生成会话密钥(Master Secret),它是对称密钥,用于对后续的 HTTP 请求/响应的数据加解密生成完会话密钥后,然后客户端发一个Change Cipher Spec,告诉服务端开始使用加密方式发送消息。然后,客户端再发一个Encrypted Handshake Message(Finishd)消息,把之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信是否可用和之前握手信息是否有被中途篡改过
              • Change Cipher Spec之前传输的 TLS 握手数据都是明文,之后都是对称密钥加密的密文
          • TLS 第四次握手:
            • 服务器也是同样的操作,发Change Cipher Spec和Encrypted Handshake Message消息,如果双方都验证加密和解密没问题,那么握手正式完成。最后,就用会话密钥加解密 HTTP 请求和响应了。
        • ECDHE 密钥协商算法:
          • 使用 RSA 密钥协商算法(也就是四次TLS握手)的最大问题是不支持前向保密。因为客户端传递随机数(用于生成对称加密密钥的条件之一)给服务端时使用的是公钥加密的,服务端收到到后,会用私钥解密得到随机数。所以一旦服务端的私钥泄漏了,过去被第三方截获的所有 TLS 通讯密文都会被破解。为了解决这个问题,后面就出现了 ECDHE 密钥协商算法,我们现在大多数网站使用的正是 ECDHE 密钥协商算法
          • HTTPS 常用的密钥交换算法有两种:

            • RSA算法
            • ECDHE 算法:ECDHE 算法具有前向安全,并且由于DHE 算法计算性能不佳,因为需要做大量的乘法,为了提升 DHE 算法的性能,所以就出现了现在广泛用于密钥交换算法 —— ECDHE 算法。
          • ECDHE 握手过程:用 ECDHE 密钥协商算法的 TSL 握手过程,也是四次握手【使用了 ECDHE,在 TLS 第四次握手前,客户端就已经发送了加密的 HTTP 数据,而对于 RSA 握手过程,必须要完成 TLS 四次握手,才能传输应用数据。所以,ECDHE 相比 RSA 握手过程省去了一个消息往返的时间,这个有点抢跑的意思,它被称为是TLS False Start,跟TCP Fast Open有点像,都是 在连接还没完全建立前,就发送了应用数据,这样便提高了传输的效率。】
            • TLS 第一次握手:

              • 客户端首先会发一个Client Hello消息,消息里面有客户端使用的 TLS 版本号、支持的密码套件列表,以及生成的随机数(Client Random)
            • TLS 第二次握手:
              • 服务端收到客户端的打招呼,同样也要回礼,会返回Server Hello消息,消息面有服务器确认的 TLS 版本号,也给出了一个随机数(Server Random),然后从客户端的密码套件列表选择了一个合适的密码套件。
              • 接着,服务端为了证明自己的身份,发送「Certificate」消息,会把证书也发给客户端。
              • 这一步就和 RSA 握手过程有很大到区别了,因为服务端选择了 ECDHE 密钥协商算法,所以会在发送完证书后,发送Server Key Exchange消息
              • 随后,就是Server Hello Done消息,服务端跟客户端表明:“这些就是我提供的信息,打招呼完毕”。【至此,TLS 两次握手就已经完成了,目前客户端和服务端通过明文共享了这几个信息:Client Random、Server Random 、使用的椭圆曲线、椭圆曲线基点 G、服务端椭圆曲线的公钥,这几个信息很重要,是后续生成会话密钥的材料
            • TLS 第三次握手
              • 客户端收到了服务端的证书后,自然要校验证书是否合法,如果证书合法,那么服务端到身份就是没问题的。校验证书的过程会走证书链逐级验证,确认证书的真实性,再用证书的公钥验证签名,这样就能确认服务端的身份了,确认无误后,就可以继续往下走。客户端会生成一个随机数作为客户端椭圆曲线的私钥,然后再根据服务端前面给的信息,生成客户端的椭圆曲线公钥,然后用Client Key Exchange消息发给服务端。至此,双方都有对方的椭圆曲线公钥、自己的椭圆曲线私钥、椭圆曲线基点 G。于是,双方都就计算出点(x,y),其中 x 坐标值双方都是一样的

                • 最终的会话密钥,就是用客户端随机数 + 服务端随机数 + x(ECDHE 算法算出的共享密钥) 三个材料生成的。因为 TLS 设计者不信任客户端或服务器伪随机数的可靠性,为了保证真正的完全随机,把三个不可靠的随机数混合起来,那么随机的程度就非常高了,足够让黑客计算不出最终的会话密钥,安全性更高。
              • 算好会话密钥后,客户端会发一个Change Cipher Spec消息,告诉服务端后续改用对称算法加密通信。
              • 接着,客户端会发Encrypted Handshake Message消息,把之前发送的数据做一个摘要,再用对称密钥加密一下,让服务端做个验证,验证下本次生成的对称密钥是否可以正常使用。
            • TLS 第四次握手:
              • 最后,服务端也会有一个同样的操作,发Change Cipher Spec和Encrypted Handshake Message消息,如果双方都验证加密和解密没问题,那么握手正式完成。于是,就可以正常收发加密的 HTTP 请求和响应了。
    • HTTPS 的加密、解密、验证以及传输过程具体流程?
      • 1.客户端请求 HTTPS 网址,然后连接到 server 的 443 端口 (HTTPS 默认端口,类似于 HTTP 的80端口)
      • 2.采用 HTTPS 协议的服务器必须要有一套数字 CA (Certification Authority)证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证书被篡改。
      • 3.服务器响应客户端请求,将证书传递给客户端,证书包含公钥和大量其他信息,比如证书颁发机构信息,公司信息和证书有效期等。
      • 4.客户端解析证书并对其进行验证。
        • 如果证书不是可信机构颁布,或者证书中的域名与实际域名不一致,或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。
        • 如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥A。然后客户端还会生成一个随机码 KEY,并使用公钥A将其加密。
      • 5.客户端把加密后的随机码 KEY 发送给服务器,作为后面对称加密的密钥。
      • 6.服务器在收到随机码 KEY 之后会使用私钥B将其解密。经过以上这些步骤,客户端和服务器终于建立了安全连接,完美解决了对称加密的密钥泄露问题,接下来就可以用对称加密愉快地进行通信了。
      • 7.服务器使用密钥 (随机码 KEY)对数据进行对称加密并发送给客户端,客户端使用相同的密钥 (随机码 KEY)解密数据。
      • 8.双方使用对称加密愉快地传输所有数据。
    • HTTPS 的优缺点?
      • 优点:安全性:

        • 使用**HTTPS协议可认证用户和服务器**,确保数据发送到正确的客户机和服务器;
        • HTTPS协议是由SSL+HTTP协议构建的**可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性**
        • HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本
        • SEO方面:谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。
      • 缺点:
        • 在相同网络环境中,HTTPS 相比 HTTP 无论是响应时间还是耗电量都有大幅度上升。
        • HTTPS 的安全是有范围的,在黑客攻击、服务器劫持等情况下几乎起不到作用
        • 在现有的证书机制下,中间人攻击依然有可能发生。
        • HTTPS 需要更多的服务器资源,也会导致成本的升高。
    • 上面说完了HTTP1.1、HTTP2.0、HTTP3.0的可以算是优缺点,但咱们还是要总结一下,HTTPS优化点有几个呢:
      • HTTPS 相比 HTTP 协议多一个 TLS 协议握手过程,目的是为了通过非对称加密握手协商或者交换出对称加密密钥,这个过程最长可以花费掉 2 RTT,接着后续传输的应用数据都得使用对称加密密钥来加密/解密
      • 上面HTTPS的大概运行流程也可以看出,HTTPS 产生性能消耗的两个环节是:
        • 第一个环节, TLS 协议握手过程

          • TLS 协议握手过程不仅增加了网络延时(最长可以花费掉 2 RTT),而且握手过程中的一些步骤也会产生性能损耗。
        • 第二个环节,握手后的对称加密报文传输
          • 现在主流的对称加密算法 AES、ChaCha20 性能都是不错的,而且一些 CPU 厂商还针对它们做了硬件级别的优化,因此这个环节的性能消耗可以说非常地小。
      • HTTPS优化策略:
        • 尽量选用 ECDHE 密钥交换算法替换 RSA 算法

          • 该算法由于支持False Start,它是“抢跑”的意思,客户端可以在 TLS 协议的第 3 次握手后,第 4 次握手前,发送加密的应用数据,以此将 TLS 握手的消息往返由 2 RTT 减少到 1 RTT,而且安全性也高,具备前向安全性。
        • 尽量选择 x25519 曲线,该曲线是目前最快的椭圆曲线。
      • TLS 升级
        • 直接把 TLS 1.2 升级成 TLS 1.3,TLS 1.3 大幅度简化了握手的步骤,完成 TLS 握手只要 1 RTT,而且安全性更高。

          • 【在 TLS 1.2 的握手中,一般是需要 4 次握手,先要通过 Client Hello (第 1 次握手)和 Server Hello(第 2 次握手) 消息协商出后续使用的加密算法,再互相交换公钥(第 3 和 第 4 次握手),然后计算出最终的会话密钥
          • TLS 1.3 把 Hello 和公钥交换这两个消息合并成了一个消息,于是这样就减少到只需 1 RTT 就能完成 TLS 握手
      • 证书优化
        • 对于服务器的证书应该选择椭圆曲线(ECDSA)证书,而不是 RSA 证书,因为在相同安全强度下, ECC 密钥长度比 RSA 短的多。椭圆曲线(ECDSA)证书更便于传输,证书小,这样可以节约带宽,也能减少客户端的运算量
        • 另一个层面,服务器向 CA 周期性地查询证书状态,获得一个带有时间戳和签名的响应结果并缓存它。当有客户端发起连接请求时,服务器会把这个响应结果在 TLS 握手过程中发给客户端。由于有签名的存在,服务器无法篡改,因此客户端就能得知证书是否已被吊销了,这样客户端就不需要再去查询
      • 会话复用
        • 把首次 TLS 握手协商的对称加密密钥缓存起来,待下次需要建立 HTTPS 连接时,直接复用这个密钥,不就减少 TLS 握手的性能损耗了嘛
        • 会话复用分两种:
          • Session ID:客户端和服务器首次 TLS 握手连接后,双方会在内存缓存会话密钥,并用唯一的 Session ID 来标识,Session ID 和会话密钥相当于 key-value 的关系。当客户端再次连接时,hello 消息里会带上 Session ID,服务器收到后就会从内存找,如果找到就直接用该会话密钥恢复会话状态,跳过其余的过程,只用一个消息往返就可以建立安全通信。当然为了安全性,内存中的会话密钥会定期失效
        • Session Ticket:
          • 为了解决 Session ID 的问题,就出现了 Session Ticket,服务器不再缓存每个客户端的会话密钥,而是把缓存的工作交给了客户端,类似于 HTTP 的 Cookie。客户端与服务器首次建立连接时,服务器会加密会话密钥作为 Ticket 发给客户端,交给客户端缓存该 Ticket。客户端再次连接服务器时,客户端会发送 Ticket,服务器解密后就可以获取上一次的会话密钥,然后验证有效期,如果没问题,就可以恢复会话了,开始加密通信
        • Pre-shared Key:
          • Session ID 和 Session Ticket 方式都需要在 1 RTT 才能恢复会话。 TLS1.3 对于重连 TLS1.3 只需要 0 RTT,原理和 Ticket 类似,只不过在重连时,客户端会把 Ticket 和 HTTP 请求一同发送给服务端,这种方式叫 Pre-shared Key
  • DDos全称Distributed Denial of Service,分布式拒绝服务攻击,DDoS则是采用分布式的方法,通过在网络上占领多台“肉鸡”,用多台计算机发起攻击。DOS攻击现在基本没啥作用了,因为服务器的性能都很好,而且是多台服务器共同作用,1V1的模式黑客无法占上风。
    • 最基本的DOS攻击过程如下:

      • 客户端向服务端发送请求链接数据包。
      • 服务端向客户端发送确认数据包。
      • 客户端不向服务端发送确认数据包,服务器一直等待来自客户端的确认
    • 对于DDOS攻击,预防方法有:
      • 减少SYN timeout时间在握手的第三步,服务器会等待30秒-120秒的时间,减少这个等待时间就能释放更多的资源。
      • 限制同时打开的SYN半连接数目。
  • SQL注入是什么,如何避免SQL注入:SQL 注入就是在用户输入的字符串中加入 SQL 语句,如果在设计不良的程序中忽略了检查,那么这些注入进去的 SQL 语句就会被数据库服务器误认为是正常的 SQL 语句而运行,攻击者就可以执行计划外的命令或访问未被授权的数据。
    • SQL注入的原理主要有以下 4 点:

      • 恶意拼接查询
      • 利用注释执行非法命令
      • 传入非法参数
      • 添加额外条件
    • 避免SQL注入的一些方法:
      • 限制数据库权限,给用户提供仅仅能够满足其工作的最低权限。
      • 对进入数据库的特殊字符(’”\尖括号&*;等)转义处理。
      • 提供参数化查询接口,不要直接使用原生SQL。
  • 认证 (Authentication) 和授权 (Authorization):
    • Authentication 被称为身份/用户验证:验证身份的凭据(例如用户名/用户 ID 和密码
    • Authorization(授权):主要掌管我们访问系统的权限。比如有些特定资源只能具有特定权限的人才能访问比如 admin,有些对系统资源操作比如删除、添加、更新只能特定人才具有
  • 目前业界主流的 权限模型 有两种,
    • RBAC 模型:系统权限控制最常采用的访问控制模型就是 RBAC 模型,通常来说,如果系统对于权限控制要求比较严格的话,一般都会选择使用 RBAC 模型来做权限控制。

      • RBAC 即基于角色的权限访问控制(Role-Based Access Control)。这是一种通过角色关联权限,角色同时又关联用户的授权的方式【一个用户可以拥有若干角色,每一个角色又可以被分配若干权限,这样就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系

        • 在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。
      • 基于角色的访问控制(RBAC)举例:用户系统中有 Admin、Maintainer、Operator 三种角色,这三种角色分别具备不同的权限,比如只有 Admin 具备创建代码仓库、删除代码仓库的权限,其他的角色都不具备我们授予某个用户 Admin 这个角色,他就具备了 创建代码仓库 和 删除代码仓库 这两个权限
        • 通过 RBAC模型 ,当存在多个用户拥有相同权限时,我们只需要创建好拥有该权限的角色,然后给不同的用户分配不同的角色,后续只需要修改角色的权限,就能自动修改角色内所有用户的权限
    • 基于属性的访问控制(ABAC):
      • 基于属性的访问控制(Attribute-Based Access Control,简称 ABAC) 是一种比 RBAC模型 更加灵活的授权模型,基于属性的访问控制(ABAC)的原理是通过各种属性来动态判断一个操作是否可以被允许。这个模型在云系统中使用的比较多,比如 AWS,阿里云等。
      • ABAC 模型的原理:在 ABAC模型 中,一个操作是否被允许是基于对象、资源、操作和环境信息共同动态计算决定的。在 ABAC模型 的决策语句的执行过程中,决策引擎会根据定义好的决策语句,结合对象、资源、操作、环境等因素动态计算出决策结果。每当发生访问请求时,ABAC模型 决策系统都会分析属性值是否与已建立的策略匹配。如果有匹配的策略,访问请求就会被通过
      • 关于SSO、权限系统设计、JWT等可以看看javaGuide老师的文章,很赞

PART1-2:

  • 什么是 Cookie 和 Session ?Cookie 和 Session 都是用来跟踪浏览器用户身份的会话方式,但是两者的应用场景不太一样。

    • 什么是 Cookie:HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地【cookie在客户端】的一小块数据,它**会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上**。

      • 通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。所以Cookie 主要用于以下三个方面:

        • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)

          • cookie一般用来保存咱们已经登陆过的用户信息,下次访问网站时自动帮咱们填信息登陆,不需要重新登陆,这就是因为咱们登陆时存放了一个Token在Cookie中,下一次登陆时只需要根据Token值来查找用户
        • 个性化设置(如用户自定义设置、主题等)
        • 浏览器行为跟踪(如跟踪分析用户行为等)
      • Cookie 被禁用怎么办?
        • 最常用的就是利用 URL 重写把 Session ID 直接附加在 URL 路径的后面
      • 不论是 Cookie 还是 Token 都无法避免 跨站脚本攻击(Cross Site Scripting)XSS
        • 什么是XSS攻击:XSS也称 cross-site scripting,跨站脚本。这种攻击是**由于服务器将攻击者存储的数据原原本本地显示给其他用户所致的**。比如一个存在XSS漏洞的论坛,用户发帖时就可以引入带有<script>标签的代码,导致恶意代码的执行。XSS 中攻击者会用各种方式将恶意代码注入到其他用户的页面中。就可以通过脚本盗用信息比如 Cookie
        • 预防措施有::
          • 前端:过滤。

            • 系统需要对用户输入的文本进行敏感词过滤如色情、政治、暴力相关的词汇,敏感词过滤用的使用比较多的 Trie 树算法 和 DFA 算法

              • Trie 树 也称为字典树、单词查找树,哈希树的一种变种,通常被用于字符串匹配,用来解决在一组字符串集合中快速查找某个字符串的问题。像浏览器搜索的关键词提示一般就是基于 Trie 树来做的。

                • Trie 树的核心原理其实很简单,就是通过公共前缀来提高字符串匹配效率
                • AC 自动机算法使用 Trie 树来存放模式串的前缀【Aho-Corasick(AC)自动机是一种建立在 Trie 树上的一种改进算法,是一种多模式匹配算法】,通过失败匹配指针(失配指针)来处理匹配失败的跳转。
              • DFA(Deterministic Finite Automata)即确定有穷自动机,与之对应的是 NFA(Non-Deterministic Finite Automata,有穷自动机)
          • 后端:转义,比如go自带的处理器就具有转义功能。
      • 为什么 Cookie 无法防止 CSRF 攻击,而 Token 可以?
        • CSRF(Cross Site Request Forgery) 一般被翻译为 跨站请求伪造 。那么什么是 跨站请求伪造 呢?说简单用你的身份去发送一些对你不友好的请求

          • 进行 Session 认证的时候,我们一般使用 Cookie 来存储 SessionId,当我们登陆后后端生成一个 SessionId 放在 Cookie 中返回给客户端,服务端通过 Redis 或者其他存储工具记录保存着这个 SessionId,客户端登录以后每次请求都会带上这个 SessionId,服务端通过这个 SessionId 来标示你这个人。如果别人通过 Cookie 拿到了 SessionId 后就可以代替你的身份访问系统了。Session 认证中 Cookie 中的 SessionId 是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果
        • 我们使用 Token 的话就不会存在这个问题,在我们登录成功获得 Token 之后,一般会选择存放在 localStorage (浏览器本地存储)中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 Token,这样就不会出现 CSRF 漏洞的问题。因为,即使有个你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 Token 的,所以这个请求将是非法的
      • 项目中如何使用Cookie,比如SpringBoot中:
    • 什么是 Session:Session 代表着服务器和客户端一次会话的过程Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失【因为由于HTTP是无状态的,所以容易丢失】,而是**在整个用户会话中一直存在下去**。当客户端关闭会话,或者 Session 超时失效时会话结束

      • session的运行依赖session id,而session id是存在cookie中的,也就是说,如果浏览器禁用了cookie,同时session也会失效(但是可以通过其它方式实现,比如在url中传递session id)
    • Cookie和Session的区别?
      • 作用范围不同,Cookie 保存在客户端(浏览器),Session 默认保存在服务器端的一个文件里【不过session可放在文件、数据库、内存中都可以】
      • 存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意数据类型,一般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等。
      • 有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
      • 隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。【如果使用 Cookie 的一些敏感信息不要写入 Cookie 中,最好能将 Cookie 信息加密然后使用到的时候再去服务器端解密。】
      • 存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie
    • 如果没有 Cookie 的话 Session 还能用吗?
      • 一般是通过 Cookie 来保存 SessionID ,假如你使用了 Cookie 保存 SessionID 的方案的话, 如果客户端禁用了 Cookie,那么 Session 就无法正常工作。但是,并不是没有 Cookie 之后就不能用 Session 了,比如你可以将 SessionID 放在请求的 url 里面https://xxx.cn/?Session_id=xxx 。这种方案的话可行,但是安全性和用户体验感降低。当然,为了你也可以对 SessionID 进行一次加密之后再传入后端。
  • Cookie 和 Session 是如何配合的呢?----SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

    • 用户 第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session ,请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器,浏览器接收到服务器返回的 SessionID 信息后,会**将此信息存入到 Cookie 中**,同时 Cookie 记录此 SessionID 属于哪个域名。
    • 当用户 第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。
  • 如何考虑分布式 Session 问题?
    • 在互联网公司为了 可以支撑更大的流量,后端往往需要多台服务器共同来支撑前端用户请求,那如果用户在 A 服务器登录了,第二次请求跑到服务 B 就会出现登录失效问题。

      • 分布式 Session 一般会有以下几种解决方案:建议采用共享 Session的方案。

        • 客户端存储:直接将信息存储在cookie中,cookie是存储在客户端上的一小段数据,客户端通过http协议和服务器进行cookie交互,通常用来存储一些不敏感信息
        • Nginx ip_hash 策略:服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。
          • 芋道源码老师的Nginx 的 5 大应用场景:Nginx本身也是一个静态资源的服务器,当只有静态资源的时候,就可以使用Nginx来做服务器,如果一个网站只是静态页面的话,那么就可以通过这种方式来实现部署;反向代理应该是Nginx使用最多的功能了,反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。【简单来说就是真实的服务器不能直接被外部网络访问,所以需要一台代理服务器,而代理服务器能被外部网络访问的同时又跟真实服务器在同一个网络环境,当然也可能是同一台服务器,端口不同而已】
        • Session 复制:任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。
          • 每一个服务器保存的 Session 信息都是互相同步的,也就是说每一个服务器都保存了全量的 Session 信息。每当一个服务器的 Session 信息发生变化,我们就将其同步到其他服务器。这种方案成本太大,并且,节点越多时,同步成本也越高。
        • 共享 Session:服务端无状态话,将用户的 Session 等信息使用缓存中间件(如Redis)来统一管理,保障分发到每一个服务器的响应结果都一致。 。所以看看这里的redis吧NoSQL、Redis配置文件redis.conf、Redis性能测试、Redis的数据结构、Redis的应用场景、Redis是单线程的、Redis是单线程的速度还快、Redis线程模型
        • 某个用户的所有请求都通过特性的哈希策略分配给同一个服务器处理。这样的话,每个服务器都保存了一部分用户的 Session 信息。服务器宕机,其保存的所有 Session 信息就完全丢失了
        • 单独使用一个所有服务器都能访问到的数据节点(比如缓存)来存放 Session 信息。为了保证高可用,数据节点尽量要避免是单点
  • JWT (JSON Web Token):目前最流行的 跨域认证解决方案,是一种基于 Token 的认证授权机制
    • JWT 本身也是 Token,一种规范化之后的 JSON 结构的 TokenJWT 自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储 Session 信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。JWT 更符合设计 RESTful API 时的「Stateless(无状态)」原则
    • 相比于 Session 认证的方式来说,使用 JWT 进行身份认证主要有下面 4 个优势:
      • 无状态

        • JWT 自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储 Session 信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。不过,也正是由于 JWT 的无状态,也导致了它最大的缺点:不可控!。就比如说,我们想要在 JWT 有效期内废弃一个 JWT 或者更改它的权限的话,并不会立即生效,通常需要等到有效期过后才可以。再比如说,当用户 Logout 的话,JWT 也还有效。除非,我们在后端增加额外的处理逻辑比如将失效的 JWT 存储起来,后端先验证 JWT 是否有效再进行处理。
      • 有效避免了 CSRF 攻击
        • CSRF(Cross Site Request Forgery) 一般被翻译为 跨站请求伪造,属于网络攻击领域范围。相比于 SQL 脚本注入、XSS 等安全攻击方式,CSRF 的知名度并没有它们高。但是,它的确是我们开发系统时必须要考虑的安全隐患。就连业内技术标杆 Google 的产品 Gmail 也曾在 2007 年的时候爆出过 CSRF 漏洞,这给 Gmail 的用户造成了很大的损失。JWT 不会存在这种问题的原因是使用 JWT 进行身份验证不需要依赖 Cookie ,因此可以避免 CSRF 攻击。一般情况下我们使用 JWT 的话,在我们登录成功获得 JWT 之后,一般会选择存放在 localStorage 中。前端的每一个请求后续都会附带上这个 JWT,整个过程压根不会涉及到 Cookie。因此,即使你点击了非法链接发送了请求到服务端,这个非法请求也是不会携带 JWT 的,所以这个请求将是非法的

          • 不过,这样也会存在 XSS 攻击的风险。为了避免 XSS 攻击【常见的避免 XSS 攻击的方式是过滤掉请求中存在 XSS 攻击风险的可疑字符串。】,你可以选择将 JWT 存储在标记为httpOnly 的 Cookie 中。但是,这样又导致了你必须自己提供 CSRF 保护,因此,实际项目中我们通常也不会这么做。
          • 在 Spring 项目中,我们一般是通过创建 XSS 过滤器来实现的。
      • 适合移动端应用
        • 使用 Session 进行身份认证的话,需要保存一份信息在服务器端,而且这种方式会依赖到 Cookie(需要 Cookie 保存 SessionId),所以不适合移动端。但是,使用 JWT 进行身份认证就不会存在这种问题,因为只要 JWT 可以被客户端存储就能够使用,而且 JWT 还可以跨语言使用
      • 单点登录友好
        • 使用 Session 进行身份认证的话,实现单点登录,需要我们把用户的 Session 信息保存在一台电脑上,并且还会遇到常见的 Cookie 跨域的问题。但是,使用 JWT 进行认证的话, JWT 被保存在客户端,不会存在这些问题
    • 基于 JWT 进行身份验证
    • 如何防止 JWT 被篡改?
      • 有了签名之后,即使 JWT 被泄露或者解惑,黑客也没办法同时篡改 Signature 、Header 、Payload。因为服务端拿到 JWT 之后,会解析出其中包含的 Header、Payload 以及 Signature 。服务端会根据 Header、Payload、密钥再次生成一个 Signature。拿新生成的 Signature 和 JWT 中的 Signature 作对比,如果一样就说明 Header 和 Payload 没有被修改。不过,如果服务端的秘钥也被泄露的话,黑客就可以同时篡改 Signature 、Header 、Payload 了。黑客直接修改了 Header 和 Payload 之后,再重新生成一个 Signature 就可以了密钥一定保管好,一定不要泄露出去。JWT 安全的核心在于签名,签名安全的核心在密钥
    • JWT 本质上就是一组字串,通过(.)切分成三个为 Base64 编码的部分:

      • Header : 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。
      • Payload : 用来存放实际需要传递的数据
      • Signature(签名) :服务器通过 Payload、Header 和一个密钥(Secret)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成
  • 负载均衡算法有哪些:多台服务器以对称的方式组成一个服务器集合,每台服务器都具有等价的地位,能互相分担负载。
    • 轮询法:将请求按照顺序轮流的分配到服务器上。大锅饭,不能发挥某些高性能服务器的优势。
    • 随机法:随机获取一台,和轮询类似
    • 哈希法:通过ip地址哈希化来确定要选择的服务器编号。好处是,每次客户端访问的服务器都是同一个服务器,能很好地利用session或者cookie。
    • 加权轮询:根据服务器性能不同加权。

PART1-3:SSO单点登陆:SSO 是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。那设计&实现一个 SSO 系统呢?

PART1-4:

  • 子网掩码是一串与**IP地址长度相同的32比特数字**,

    • 子网掩码的左边一半都是1,子网掩码为1的部分代表网络号
    • 右边一半都是0,子网掩码为0的部分代表主机号
  • IP地址的主机号:
    • 全0代表整个子网
    • 全1代表向子网上的所有设备发送包,也就是广播

PART2:其他应用层协议:

巨人的肩膀:
https://www.javalearn.cn/
网络是怎样连接的
moon聊技术
小林coding
javaguide

java基础巩固-宇宙第一AiYWM:为了维持生计,四大基础之计网_Part_1-2(HTTP1.0、1.1、2.0、3.0【谁比谁牛,牛在哪】;HTTP(S)、会话和饼干、权限)整起相关推荐

  1. java基础巩固-宇宙第一AiYWM:为了维持生计,四大基础之计网_Part_2(在浏览器中输入www.baidu.com后执行的全部过程、DNS的域名<->IP地址、OS协议栈的样子、CDN)整起

    可以说计算机网络,就是玩那几层中的那些协议们,本层玩,本层玩完了跨层玩,跨层玩,跨层玩完了本层玩- PART1:在浏览器中输入网站网址后执行的全部过程? 0.服务器在 80 端口等待客户的请求. se ...

  2. java基础巩固-宇宙第一AiYWM:为了维持生计,做项目经验之~SSM项目错误集锦Part3(项目蹦+pg数据库坏+100%-->线上故障排查经验【业务bug第一步一定是先看日志,写好日志】)~整起

    项目中遇到的一个问题:项目忽然蹦了,用我们的域名登陆不上去了. 根据之前的经验,一般比如我们项目登不上去了或者数据库不上数据了(数据不更新),直接在Xshell上远程reboot一下,再重启一下tom ...

  3. java基础巩固-宇宙第一AiYWM:为了维持生计,Redis基础Part2(Redis的数据结构)~整起

    PART1:Redis的数据结构:5+3数据类型<----------------->数据结构[未来随着 Redis 新版本的发布,可能会有新的数据结构出现,通过查阅 Redis 官网[[ ...

  4. java基础巩固-宇宙第一AiYWM:为了维持生计,多高(多线程与高并发)_Part9~整起(单双列集合们、ArrayList 的扩容机制、HashMap、ConcurrentHashMap )

    再进入正文之前,先看看集合相关操作的时间复杂度: 本故事源自于~ 开唠: PART0: 为什么突然蹦出集合这个玩意,就是因为咱们基础那里学的"数组"不够用~: 数组一般用来保存一组 ...

  5. java基础巩固-宇宙第一AiYWM:为了维持生计,四大基础之计网_Part_1-1(计算机网络体系_七层模型五层模型TCP/IP四层模型、TCPUDPIP的故事【TCP三握四挥】)整起

    PART1:计算机网络体系可以大致分为一下三种, 每一层有自己对应的协议,每一层都是向上一层提供服务,每个分层中所有的协议都称为协议栈 协议:网络中传输信息时的规范和规则 各层一些重要的协议 网络:通 ...

  6. java基础巩固-宇宙第一AiYWM:为了维持生计,四大基础之OS_Part_1整起(进程线程协程并发并行、进程线程切换进程间通信、死锁\进程调度策略、分段分页、交换空间、OS三大调度机制)

    PART0:OS,这货到底是个啥? OS,是个啥? OS的结构们: 存储器: 存储器的层次结构: 内存:我们的程序和数据都是存储在内存,我们的程序和数据都是存储在内存,每一个字节都对应一个内存地址.内 ...

  7. java基础巩固-宇宙第一AiYWM:为了维持生计,Redis基础Part6(Redis的应用场景、Redis是单线程的速度还快、Redis线程模型:Reactor模式、事件、发布订阅、管道)~整起

    PART1-1:为什么Redis是单线程的 Redis单线程是指: Redis的网络IO和键值对读写是由一个线程来完成的.这也是 Redis 对外提供键值存储服务的主要流程.Redis的其他功能,比如 ...

  8. java基础巩固-宇宙第一AiYWM:为了维持生计,架构知识+分+微序幕就此拉开之Docker(Docker概念:容器、镜像、仓库)、操作命令、Docker网络、分层、K8S<->Docker~整起

    架构知识+分+微序幕就此拉开之Docker 一.为什么要搞这个Docker,咱们为啥要学,盖房子? 二.Docker的镜像与容器 1.预备知识:虚拟(机).容器(化) 2.Docker.镜像.容器 3 ...

  9. java基础巩固-宇宙第一AiYWM:为了维持生计,四大基础之OS_Part_2整起~IO们那些事【包括五种IO模型:(BIO、NIO、IO多路复用、信号驱动、AIO);零拷贝、事件处理及并发等模型】

    PART0.前情提要: 通常用户进程的一个完整的IO分为两个阶段(IO有内存IO.网络IO和磁盘IO三种,通常我们说的IO指的是后两者!):[操作系统和驱动程序运行在内核空间,应用程序运行在用户空间, ...

  10. java基础巩固-宇宙第一AiYWM:为了维持生计,Redis基础Part7(Redis常见使用(部署)方式:单机模式、主从模式、哨兵模式、集群模式)~整起

    Redis持久化:RDB.AOF是针对存储在一台服务器上的数据由于存储过程被打断而发生丢失的情况的.此时,咱们肯定要考虑到,所有鸡蛋都放在一个篮子里是会出问题的. 如果服务器发生了宕机,由于数据恢复是 ...

最新文章

  1. linux vi 强制退出_linux的编辑大法
  2. 计算机网络-TCP运输连接管理
  3. 用Reflector和FileDisassembler配合反编译.net Windows程序
  4. Altium Designer 09 (Protel)总线使用方法(解决导入PCB无网络标号问题)
  5. 卷积网络和卷积神经网络_卷积神经网络的眼病识别
  6. 列出搜索过的数据(类似京东顶部搜索框)
  7. 21天Jmeter打卡day16参数传递token传递,接口关联
  8. 一年级下册健康教育教案
  9. Android 长截屏原理
  10. 机器学习如何帮助Caesars大涨邮件绩效
  11. NDK开发Android端RTMP直播推流程序
  12. 如何生成随机验证码图片
  13. python 正则表达式 匹配任意长度英文字母
  14. CC2430基础——IAR的安装及配置
  15. PMP 风险应对措施 :规避和减轻的区别
  16. uncode-schedule 学习
  17. Arduino应用开发——通过小爱同学控制灯光
  18. 华为应用市场APP上架流程
  19. Google benchmark使用手册及范例
  20. 转杨毅:火箭输得有谱了!

热门文章

  1. 台式机CentOS7安装GitLab11.10.4搭建(5)Mac通过终端安装VNC
  2. 蒙氏计算机教育目的,蒙氏数学领域基础理论及教育目的
  3. windows下基于wvp-GB28181-pro+ZLMediaKit实现的GB28181媒体流服务+实现ssl证书配置实现https访问
  4. 旧金山oracle park,周末玩什么?我们来告诉你!旧金山湾区活动汇总
  5. ssh爆破获取用户密码
  6. Outlook 使用anywhere 提示安全证书上的名称无效或与网站的名称不相符
  7. Android流量监控论文,Android平台流量监控软件的设计与实现
  8. 快捷方式小盾牌如何取消
  9. 网络设备上常用的安全技术
  10. 01组团队项目-Beta冲刺-2/5