前端面试题 - 计算机网络与浏览器相关

系列文章目录

vue常见面试题总结

html+css 面试题总结附答案

初级前端面试题总结(html, css, js, ajax,http)

js基础面试题整理(包含ES5,ES6)


文章目录


总结这篇文章的目的不是单纯的为了面试,其实也在梳理自己的知识体系,以后也打算再单独出一篇关于浏览器工作原理相关的文章,另外最近也在看《图解HTTP》这本书,觉得很不错,比如下方第一大类的网络协议相关内容书中都有介绍过。

一、网络协议相关

1. 从浏览器地址栏输入url到显示页面的步骤

  1. 浏览器解析输入的 URL,提取出其中的协议、域名和路径等信息。
  2. 浏览器向 DNS 服务器发送请求,DNS服务器通过多层查询将该域名解析为对应的IP地址,然后将请求发送到该IP地址上,与服务器建立连接和交换数据。(寻找哪台机器上有你需要的资源,根据域名找IP)
  3. 浏览器与服务器建立 TCP 连接。
  4. 浏览器向服务器发送 HTTP 请求,包含请求头和请求体。
  5. 服务器接收并处理请求,并返回响应数据,包含状态码、响应头和响应体。
  6. 浏览器接收到响应数据,解析响应头和响应体,并根据状态码判断是否成功。
  7. 如果响应成功,浏览器解析渲染页面 -》浏览器便开始下载网页,HTML,CSS,JS文件后依次渲染
  8. 连接结束,断开TCP连接 四次挥手

详细可参考:超详细讲解页面加载过程

2. HTTP请求的完整过程

发起一个 HTTP 请求之后,浏览器首先查找缓存,如果缓存没有命中,那么继续发起 DNS 请求获取 IP 地址,然后利用 IP 地址和服务器端建立 TCP 连接,再发送 HTTP 请求,等待服务器响应;不过,如果服务器响应头中包含了重定向的信息,那么整个流程就需要重新再走一遍。这就是在浏览器中一个 HTTP 请求的基础流程。

在这里插入图片描述

3. 三次握手,说明每次握手都发送什么信息?四次挥手

三次握手是TCP协议用于建立可靠连接的过程,具体过程如下:

  1. 客户端向服务器发送一个 SYN(synchronize同步)报文。其中随机生成一个初始序列号,表示客户端准备发送数据。
  2. 服务器接收到SYN报文后,回复一个 SYN ACK(同步确认)报文,表示我收到了。其中确认号为客户端的序列号+1,同时随机生成一个初始序列号,表示服务器准备接收数据。
  3. 客户端接收到SYN ACK报文后,向服务器发送一个 ACK(确认)报文,表示我知道了,握手结束。其中确认号为服务器的序列号+1,表示客户端准备发送数据。服务器接收到ACK报文后,连接建立成功,双方开始进行数据传输。

直白理解:

客户端:hello,你是server么?
服务端:hello,我是server,你是client么 ?
客户端:yes,我是client
建立成功之后,接下来就是正式传输数据。

三次握手的目的是为了确保客户端和服务器之间的通信是可靠的,同时也可以防止已经失效的连接请求报文段再次传到服务器,导致错误。

四次挥手:即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。

直白理解:

主动方:我已经关闭了向你那边的主动通道了,只能被动接收了
被动方:收到通道关闭的信息
被动方:那我也告诉你,我这边向你的主动通道也关闭了
主动方:最后收到数据,之后双方无法通信

可参考:一文搞懂TCP的三次握手和四次挥手

TCP三次握手、四次挥手时序图

4. TCP三次握手,握手是根据ip和端口来握手的吗?

是的。
在TCP三次握手过程中,交换IP地址和端口号信息的具体步骤如下:

  1. 客户端向服务器发送一个SYN包,其中包含客户端的IP地址和端口号信息。
  2. 服务器接收到SYN包后,向客户端回复一个SYN-ACK包,其中包含服务器的IP地址和端口号信息。
  3. 客户端再向服务器发送一个ACK包,确认建立连接,并携带客户端的IP地址和端口号信息。
    通过这样的交互过程,客户端和服务器就可以互相了解对方的IP地址和端口号信息,从而建立一条可靠的数据传输通道。

5. 那为什么要三次握手呢?两次、四次不行吗?

为了确认双方的 接收能力发送能力 都正常。

为什么不是两次?

根本原因: 无法确认客户端的接收能力。

如果是用两次握手,则会出现下面这种情况:
如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,此时客户端共发出了两个连接请求报文段。
其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络节点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误以为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手;只要服务端发出确认,就建立新的连接了。此时客户端忽略服务端发来的确认,也不发送数据,则服务端一直等待客户端发送数据,浪费了资源。

为什么不是四次?

三次握手的目的是确认双方发送和接收的能力,那四次握手可以嘛?
当然可以,100 次都可以。但为了解决问题,三次就足够了,再多用处就不大了。

6. 三次握手过程中可以携带数据么?

第三次握手的时候,可以携带。前两次握手不能携带数据。
如果前两次握手能够携带数据,那么一旦有人想攻击服务器,那么他只需要在第一次握手中的 SYN 报文中放大量数据,那么服务器势必会消耗更多的时间和内存空间去处理这些数据,增大了服务器被攻击的风险。
第三次握手的时候,客户端已经处于ESTABLISHED状态,并且已经能够确认服务器的接收、发送能力正常,这个时候相对安全了,可以携带数据。

7. 为什么是四次挥手而不是三次?

因为服务端在接收到FIN, 往往不会立即返回FIN, 必须等到服务端所有的报文都发送完毕了,才能发FIN。因此先发一个ACK表示已经收到客户端的FIN,延迟一段时间才发FIN。这就造成了四次挥手。
如果是三次挥手会有什么问题?
等于说服务端将ACKFIN的发送合并为一次挥手,这个时候长时间的延迟可能会导致客户端误以为FIN没有到达客户端,从而让客户端不断的重发FIN

8. http的文本传输和流传输?使用场景

HTTP协议有两种主要数据传输方式:文本传输流传输

  1. 文本传输:这种方式数据作为文本字符串发送,因此易于阅读、解析和处理。同时,这种方式具有一定的可读性,便于诊断错误。主要应用场景是传输小型文本数据,例如通过POST方法提交表单数据。由于文本类型数据通常较小,因此使用文本传更方便和高效。

  2. 流传输:这种方式将数据以2进制流的方式传输,允许客户端和服务器在数据传输过程中即时处理。这一特性对于处理大型文件、下载,二进制图像、视频音频等需求非常实用,在数据体积大、网络环境不稳定且延迟高的情况下表现尤佳。使用流传输可以使数据更快地到达接收方,同时减少网络上的数据传输时间和额外开销。

使用场景:
如果需要传输的数量比较小或需要直接查看或审查数据,则文本传输可能比较合适。相反,如果数据规模较大或者需要自动处理梳理而无详细检查数据,则流传输可能更适宜。

9. HTTP请求报文都有什么组成?

主要由三个部分组成:请求行、请求头和请求体。具体如下:

请求行:包含请求方法URIHTTP协议版本。例如:GET /index.html HTTP/1.1。
请求头(Header): 包含了客户端向服务器发送的附加信息,例如浏览器类型、字符编码、认证信息等。请求头以键值对的形式存在,多个键值对之间以换行符分隔。例如:Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7。
请求体(Body): 存放请求参数,即浏览器向服务器传输数据的实体部分。常用于POST方法提交请求时,发送表单数据、JSON数据等类型的数据。

需要注意的是,并不是所有的HTTP请求都必须带有请求体,像GET请求通常不需要发送请求体。

在这里插入图片描述

为什么 HTTP 报文中要存在 “空行”?
因为 HTTP 协议并没有规定报头部分的键值对有多少个。空行就相当于是 “报头的结束标记”, 或者是 “报头和正文之间的分隔符”。
HTTP 在传输层依赖 TCP 协议, TCP 是面向字节流的. 如果没有这个空行, 就会出现 “粘包问题”

10. HTTP协议各版本的区别

HTTP协议的版本历经多次更新迭代,主要包括 HTTP/1.0HTTP/1.1HTTP/2等版本,它们之间的主要区别如下:

1)HTTP/1.0:

  1. 浏览器与服务器只保持短连接,浏览器的每次请求都需要与服务器建立一个TCP连接,都要经过三次握手,四次挥手。
  2. 由于浏览器必须等待响应完成才能发起下一个请求,造成 “队头阻塞”
    如果某请求一直不到达,那么下一个请求就一直不发送。(高延迟–带来页面加载速度的降低)

2)HTTP/1.1:目前使用最广泛的版本

  1. 支持长连接,通过Connection: keep-alive保持HTTP连接不断开,避免重复建立TCP连接。
  2. 管道化传输,通过长连接实现一个TCP连接中同时处理多个HTTP请求;目前浏览器中对于同一个域名,默认允许同时建立 6 个 TCP 持久连接。服务器会按照请求的顺序去返回响应的内容,无法存在并行响应。(http请求返回顺序按照服务器响应速度来排序,这里也会引入promise.then 和 async await 来控制接口请求顺序)
  3. 新增了一些请求方法,新增了一些请求头和响应头(如下)
  4. 支持断点续传, 新增 Range 和 Content-Range 头表示请求和响应的部分内容
  5. 加入缓存处理(响应头新字段Expires、Cache-Control)
  6. 增加了Host字段;为了支持多虚拟主机的场景,使用同一个IP地址上可以托管多个域名,访问的都是同一个服务器,这样服务器就可以根据不同的 Host 值做不同的处理。
  7. 并且添加了其他请求方法:put、delete、options…

备注:
http/1.1中的一个tcp链接同时只能发起一个http请求!

浏览器会让每个域名同时最多建立6个tcp链接,也就是说同一个域名同时能支持6个http请求!

缺点:

  1. HTTP/1.1对带宽的利用率却并不理想,很难将带宽用满。主要是由以下三个原因导致的
    1)TCP 的慢启动。
    2)同时开启了多条 TCP 连接,那么这些连接会竞争固定的带宽。有的 TCP 连接下载的是一些关键资源,而有的 TCP 连接下载的是普通的资源文件,但是多条 TCP 连接之间又不能协商让哪些关键资源优先下载,这样就有可能影响那些关键资源的下载速度了。
    3)HTTP/1.1 队头阻塞的问题

  2. 无状态通信模型(巨大的HTTP头部),也就是服务器端不保存客户端请求的任何状态信息。这样会造成一些需求频繁交互的应用程序难以实现,需要通过其他机制来保证状态的一致性等。

  3. 明文传输–不安全

  4. 不支持服务端推送

3)HTTP/2.0:

  1. 通过引入二进制分帧层,实现了 HTTP 的多路复用技术。在同一个TCP连接上同时传输多条消息;不用按照顺序一一发送,这样就避免了"队头堵塞"的问题。HTTP/2.0 中一个域名只使用一个 TCP 长连接来传输数据,这样整个页面资源的下载过程只需要一次慢启动,同时也避免了多个 TCP 连接竞争带宽所带来的问题。
  2. 可设置请求优先级。HTTP/2 提供了请求优先级,可以在发送请求时,标上该请求的优先级,这样服务器接收到请求之后,会优先处理优先级高的请求。
  3. 使用 HPACK 算法报头压缩,数据体积小了,传输就会更快。(一方面,头信息使用 gzip 或 compress 压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就能提高速度了)
  4. 服务器推送,支持服务器未经请求主动将相关静态资源预测性地推送给客户端,以减少后续的请求和延迟。(例如 HTML、CSS、JavaScript、图像和视频等静态资源)。需要注意的是http2.0下服务器主动推送的是静态资源,和WebSocket向客户端发送即时数据的推送是不同的。

缺点:

  1. TCP的队头阻塞问题并没有解决,只是解决了http的队头阻塞。
    1)因为不管http/1还是http/2都是基于 TCP 协议的,而 TCP 协议依然存在数据包级别的队头阻塞问题。
    2)TCP包传输也是按照顺序的,一个阻塞了,会影响到其它数据包的接收。
    3)关于TCP的队头阻塞,TCP传输过程中也是把一份数据分为多个数据包的。当其中一个数据包没有按照顺序返回,接收端会一直保持连接等待数据包返回,这时候就会阻塞后续请求。
  2. TCP 建立连接的延时。
    1)在建立 TCP 连接的时候,需要和服务器进行三次握手来确认连接成功
    2)进行 TLS 连接,也需要花费1~2 个 RTT
  3. TCP 协议僵化(中间设备的僵化、操作系统内核更新问题)

多路复用的实现:

从图中可以看出,HTTP/2 添加了一个二进制分帧层,那我们就结合图来分析下 HTTP/2 的请求和接收过程。

在这里插入图片描述

  • 首先,浏览器准备好请求数据,包括了请求行、请求头等信息,如果是 POST 方法,那么还要有请求体。
  • 这些数据经过二进制分帧层处理之后,会被转换为一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器。
  • 服务器接收到所有帧之后,会将所有相同 ID 的帧合并为一条完整的请求信息。
  • 然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。
  • 同样,二进制分帧层会将这些响应数据转换为一个个带有请求 ID 编号的帧,经过协议栈发送给浏览器。
  • 浏览器接收到响应帧之后,会根据 ID 编号将帧的数据提交给对应的请求。

从上面的流程可以看出,通过引入二进制分帧层,就实现了 HTTP 的多路复用技术

拓展:

  • HTTP1.1到HTTP2解决的是Http层面上的队首阻塞,是同一个长链接上的多个http请求之间的队首阻塞,只有前面的请求完事儿才轮到后面的请求;
  • 并不等同于TCP层面的队首阻塞, tcp的队首阻塞是数据包层面的,一个请求被分成有序的多个小的数据包,如果在数据传输的过程中,有一个数据因为网络故障或者其他原因而丢包了,那么整个 TCP 的连接就会处于暂停状态,需要等待丢失的数据包被重新传输过来,由于单个数据包的丢失而造成的阻塞称为 TCP 上的队头阻塞

4)HTTP3.0

是 HTTP/3 中的底层支撑协议,该协议基于 UDP,又取了 TCP 中的精华,实现了即快又可靠的协议。

  1. 运输层由TCP改成使用UDP 协议,基于 UDP 实现了类似于 TCP 的多路数据流、传输可靠性等功能,我们把这套功能称为 QUIC 协议
  2. 队头堵塞问题的解决更为彻底;
  3. 升级新的压缩算法
  4. 快速握手:由于基于 UDP,可以实现使用 0 ~ 1 个 RTT 来建立连接。

在这里插入图片描述
通过上图我们可以看出,HTTP/3 中的 QUIC 协议集合了以下几点功能。

  • 实现了类似 TCP 的流量控制、传输可靠性的功能。虽然 UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。
  • 集成了 TLS 加密功能。目前 QUIC 使用的是 TLS1.3,相较于早期版本 TLS1.3 有更多的优点,其中最重要的一点是减少了握手所花费的 RTT 个数。
  • 实现了 HTTP/2 中的多路复用功能。和 TCP 不同,QUIC 实现了在同一物理连接上可以有多个独立的逻辑数据流(如下图)。实现了数据流的单独传输,就解决了 TCP 中队头阻塞的问题
    在这里插入图片描述
  • 实现了快速握手功能。由于 QUIC 是基于 UDP 的,所以 QUIC 可以实现使用 0-RTT 或者 1-RTT 来建立连接,这意味着 QUIC 可以用最快的速度来发送和接收数据,这样可以大大提升首次打开页面的速度。

HTTP/3 面对的挑战:

  • 服务器和浏览器端都没有对 HTTP/3 提供比较完整的支持。
  • 部署 HTTP/3 也存在着非常大的问题。因为系统内核对 UDP 的优化远远没有达到 TCP 的优化程度,这也是阻碍 QUIC 的一个重要原因。
  • 中间设备僵化的问题。这些设备对 UDP 的优化程度远远低于 TCP,据统计使用 QUIC 协议时,大约有 3%~7% 的丢包率。

11. TCP 和 UDP 的区别

1)基本区别:

  • TCP 是一个面向连接的、可靠的、基于字节流的传输层协议。

  • UDP 是一个面向无连接的传输层协议。(就这么简单,其它TCP的特性也就没有了)。

2)面向连接。

所谓的连接,指的是客户端和服务器的连接,在双方互相通信之前,TCP 需要三次握手建立连接,而 UDP 没有相应建立连接的过程。

3)可靠性和排序机制

对于浏览器请求,或者邮件这类要求数据传输可靠性(reliability)的应用,如果使用 UDP 来传输会存在两个问题:

  • 数据包在传输过程中容易丢失;
  • 大文件会被拆分成很多小的数据包来传输,这些小的数据包会经过不同的路由,并在不同的时间到达接收端,而 UDP 协议并不知道如何组装这些数据包,从而把这些数据包还原成完整的文件。

基于这两个问题,我们引入 TCP 了。TCP 有下面两个特点:

  • 对于数据包丢失的情况,TCP 提供重传机制;
  • TCP 引入了数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件。提供了用于排序的序列号,以便接收端通过序号来重排数据包。

4)面向字节流

UDP 的数据传输是基于数据报的,这是因为仅仅只是继承了 IP 层的特性,而 TCP 为了维护状态,将一个个 IP 包变成了字节流。

12. HTTP状态码的含义

区分状态码
1××开头 - 信息性状态码,表示HTTP请求已被接收,需要进一步处理。
2××开头 - 成功状态码,表示请求已成功处理完成。
3××开头 - 重定向状态码,表示请求需要进一步的操作以完成。
4××开头 - 客户端错误状态码,表示请求包含错误或无法完成。
5××开头 - 服务器错误状态码,表示服务器无法完成有效的请求。

常见状态码
200 - 请求成功,从客户端发送给服务器的请求被正常处理并返回

301 - 表示被请求的资源已经被永久移动到新的URI(永久重定向)
302 - 表示被请求的资源已经被临时移动到新的URI(临时重定向)
304 - 表示服务器资源未被修改;通常是在客户端发出了一个条件请求,服务器通过比较资源的修改时间来确定资源是否已被修改

400 - 服务器不理解请求,请求报文中存在语法错误
401 - 请求需要身份验证
403 - 服务器拒绝请求(访问权限出现问题)
404 - 被请求的资源不存在
405 - 不允许的HTTP请求方法,意味着正在使用的HTTP请求方法不被服务器允许

500 - 服务器内部错误,无法完成请求
502 -(错误网关)服务器作为网关或代理,从上游服务器收到无效响应
503 - 服务器当前无法处理请求,一般是因为过载或维护
504 -(网关超时)服务器作为网关或代理,但是没有及时从上游服务器收到请求

关于返回403 Forbidden错误的原因

一开始我以为返回403 Forbidden错误的原因可能与浏览器向DNS服务器发送请求,解析域名返回ip地址,是ip地址不符合访问导致的,于是去寻找答案,了解到解析出的IP地址实际是服务器的IP地址,跟我们计算机上的ipv4无关。下文就是返回403 原因的解释。

返回403 Forbidden错误的原因通常不是DNS解析返回的IP地址与访问不匹配。实际上,当您尝试访问一个网站时,浏览器会首先从 DNS服务器 获取该域名对应的IP地址,并将其用于与服务器建立连接和交换数据。如果域名解析成功且找到了正确的IP地址(服务器地址),但仍然返回403 Forbidden错误,则表示服务端可能禁止了您的访问。
403 Forbidden错误通常是由服务器的访问控制规则、文件权限设置、安全策略等问题引起的。例如,服务器可能禁止您访问某个特定的目录或文件,或者拒绝来自您当前IP地址或浏览器的请求。在这种情况下,您可以通过联系网站管理员或升级您的访问权限来解决此问题。

13. HTTP与HTTPS的区别

先说一下什么是HTTP??HTTP是基于TCP/IP的关于数据如何在万维网中如何通信的协议。

1. 安全性:HTTPS 基于SSL/TLS 加密传输协议,通过在传输层加密数据可以提供更高的安全性。相反,HTTP 不提供任何安全保障,明文传输容易被窃听。
2. 加密方式: HTTPS 通过 SSL/TLS 协议使用非对称加密(公钥加密)和对称加密(私钥加密)的结合方式来保护数据。HTTP 传输的数据都是明文的。
3. 连接方式:HTTP 协议连接很简单,是无状态的;HTTPS 协议是有 SSL 和 HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 更加安全。
4. 端口:HTTP 使用 80 端口,HTTPS使用 443 端口。
5. 费用:HTTPS 协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。

综上所述,HTTPS 提供了更高的安全性,适合传输敏感信息的数据,如银行卡信息、用户密码等。而 HTTP 则适合一些不需要保密的信息传输,如浏览某些公开网站,获取新闻资讯等。

14. 介绍下HTTPS

HTTPS 是身披 SSL 外壳的 HTTP。
HTTPS 并非是应用层的一种新协议。只是 HTTP 通信接口部分用 SSL 和 TLS协议代替而已。
通常,HTTP 直接和 TCP 通信。当使用 SSL 时,演变成先和 SSL 通信了。简言之,所谓HTTPS,其实就是身披 SSL 外壳的 HTTP。

在这里插入图片描述
在采用SSL后,HTTP就拥有了HTTPS的加密、证书和完整性保护这些功能。
SSL是独立于HTTP的协议,所以不光是HTTP协议,其他运行在应用层的 SMTP 和 TeInet等协议均可配合SSL协议使用。可以说SSL是当今世界上应用最为广泛的网络安全技术。

总的来说, HTTP + SSL/TLS + 证书 + 报文完整性 = HTTPS

对于浏览器来说,数字证书有两个作用:

  • 通过数字证书向浏览器证明服务器的身份;
  • 另一个是数字证书里面包含了服务器公钥。

15. HTTPS的加密过程

HTTPS 是一种通过加密保护数据传输的安全版本的HTTP协议。

大致连接过程:

  • client => :443 端口 => server
  • server => 返回证书(也就是公钥) + server-random => client
  • client : 验证证书有效性 + 生成 client-random
  • client :生成随机数 pre-master(加密后的随机数)
  • client :公钥加密(pre-master)=> server
  • server::私钥解密(pre-master)
  • 两端通过 client-random + server-random + pre-master=> matersecret (对称会话密钥)进行对称加密通讯。

整体:

  • 建立链接时:公钥 + 私钥 => 非对称加密
  • 后续数据传输:matersecret 对称加密
  • 为什么安全》每一步劫持,都只能截取 matersecret ,没法解密,只能透传,转发。有效保护数据传输。

详细一些的连接过程:

  • 客户端发起连接请求:向服务器发起 https 连接请求,然后连接到服务器的 443 端口。
  • 服务器证书:服务器在响应客户端请求时,会将自己的数字证书发送给客户端(也就是公钥)。数字证书是由可信任的第三方证书颁发机构(Certificate Authority,CA)签名的文件,用于验证服务器身份的真实性。
  • 客户端验证证书: 客户端接收到服务器的数字证书后,会验证证书的有效性。验证包括检查证书的签名是否有效、证书是否在有效期内,以及证书中的域名与实际访问的域名是否匹配等。( 这部分工作由客户端的SSL/TLS来完成的,如果发现异常,弹出提示窗,提示证书存在的问题,否则就生成一个随机值,就是下方的 随机对称密钥 )
  • 生成会话密钥: 如果服务器的证书有效,客户端会生成一个成为“会话秘钥” 的 随机对称密钥该密钥将用于对后续的数据传输进行加密和解密
  • 用证书加密会话密钥:客户端使用服务器的公钥会话密钥进行加密,并将加密后的会话密钥发送给服务器。服务器使用自己的私钥对会话密钥进行解密,从而获取会话密钥。
  • 加密通信:客户端和服务器之间的通信使用会话密钥进行对称加密。这意味着数据在传输过程中使用相同的密钥进行加密和解密,从而保证了数据的机密性。
    通过以上步骤,HTTPS实现了数据的加密传输,确保了通信的安全性和隐私性。客户端和服务器之间的数据传输使用对称加密算法(如AES)进行加密和解密,而会话密钥则使用非对称加密算法(如RSA)进行加密和解密。这种结构可以确保通信内容的机密性,并防止中间人攻击等恶意行为。

客户端都会生成一个随机数,称为“临时会话密钥”,它的用处是:

  • 具体来说,每次客户端和服务器之间的连接建立时,客户端都会生成一个随机数,称为“临时会话密钥”,并将其发送给服务器。服务器使用自己的私钥对临时会话密钥进行解密,并使用它来加密和解密数据。
  • 由于每个会话都使用一个不同的临时会话密钥,这意味着即使攻击者能够获取服务器的长期私钥,他们也无法解密过去的通信记录。这提供了更好的安全性,因为即使长期私钥被泄露,攻击者也只能访问当前会话的数据,而不能访问早期会话的数据。

16. 浏览器如何验证CA证书的有效性

浏览器读取证书中的证书所有者、有效期等信息进行校验。

  • 校验 证书的网站域名 是否与 证书颁发的域名 一致;
  • 校验证书是否在 有效期 内;
  • 浏览器查找操作系统中已内置的受信任的证书发布机构,与服务器发来的证书中的颁发者做比对,用于校验证书是否为合法机构颁发。

查看google浏览器里的证书

17. HTTPS绝对安全吗?

不是,可以通过在用户机器上安装假的 HTTPS 根证书来欺骗浏览器。
只要拿到系统权限,就能随意安装根证书
之前百度升级到https之后,很多劫持就是采用这种方式来干的,在操作系统安装假的根证书,然后劫持整个站点!
所以让黑客在你电脑上安装了根证书,https也会变得不安全了!

18. 介绍一下DNS (DNS 协议是什么?)

DNS服务器通过多层查询将解析域名为IP地址

域名劫持:是指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能访问访问的是假网址


二、浏览器相关

1. 浏览器渲染机制

详细请点击 浏览器渲染机制
浏览器渲染 — 渲染过程讲的很详细 — 很适合学习

1)处理 HTML 并构建 DOM 树。
2)处理 CSS 构建 CSSOM 树(样式树)。
3)将 DOMCSSOM 合并成一个 渲染树
4)计算渲染树中每个节点位置。这个过程会发生回流和重绘。
5)调用 GPU 绘制,合成图层,显示在屏幕上

第4步和第5步是最耗时的部分,这两步合起来,就是我们通常所说的渲染

注意:

1)浏览器工作流程:构建DOM -> 构建CSSOM -> 构建渲染树 -> 布局 -> 绘制。
2)CSSOM会阻塞渲染,只有当CSSOM构建完毕后才会进入下一个阶段构建渲染树。
3)通常情况下DOM和CSSOM是并行构建的,但是当浏览器遇到一个script标签时,DOM构建将暂停,直至脚本完成执行。因为JavaScript可以修改DOM,导致后续HTML资源白白加载,所以需要等DOM构建完毕后再执行JS。
4)如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,建议将 script 标签放在 body 标签底部。

在这里插入图片描述

2. 浏览器在渲染时的两种现象

重排重绘,重排也叫也叫回流。

重排:当 DOM 结构发生变化或者元素样式发生改变时,浏览器需要重新计算元素的几何属性并重新布局,这个过程比较消耗性能。
重绘:指元素的外观样式发生变化(比如改变 color 就叫称为重绘),但是布局没有变,此时浏览器只需要重新绘制元素就可以了,比重排消耗的性能小一些。

重排必定会发生重绘,重绘不一定会引发重排。重排所需的成本比重绘高的多,改变深层次的节点很可能导致父节点的一系列重排

3. 渲染页面时常见哪些不良现象?

由于浏览器的渲染机制不同,在渲染页面时会出现两种常见的不良现象 — 白屏问题FOUS(无样式内容闪烁)

FOUC:由于浏览器渲染机制(比如firefox),在CSS加载之前,先呈现了HTML,就会导致展示出无样式内容,然后样式突然呈现的现象;
白屏:有些浏览器渲染机制(比如chrome)要先构建DOM树和CSSOM树,构建完成后再进行渲染,如果CSS部分放在HTML尾部,由于CSS未加载完成,浏览器迟迟未渲染,从而导致白屏;也可能是把js文件放在头部,脚本会阻塞后面内容的呈现,出现白屏问题。

4. 简单请求和复杂请求

简单请求和复杂请求是指在发送跨域请求时,根据请求方式头部信息等因素区分的两种请求类型。
简单请求:使用常见的GET、POST、HEAD方式中的一种,不包含自定义头部字段,且请求方法不会对服务器状态产生影响。这种请求不需要预检请求(OPTIONS),直接发出即可。
复杂请求:使用常见的请求方式(如PUT、DELETE)或者包含自定义头部字段,且请求方法可能对服务器状态产生影响。这种请求需要向发送预检请求(OPTIONS),已确认服务器是否允许真正的请求。预检请求成功后才能发出真正的请求。

复杂请求过程:

  1. 在发送复杂请求前,浏览器会先发送一个预检请求(OPTIONS方法),该请求包含了一些额外的头部字段,如 Access-Control-Request-MethodAccess-Control-Request-Headers 等。
  2. 服务器收到预检请求后,检查 Origin 字段是否在允许的跨域访问白名单中。如果在白名单中,则在响应头中添加 Access-Control-Allow-Origin 字段,并设置为允许的源,表示该源允许跨域访问。
  3. 服务器还需要检查请求中的 Access-Control-Request-MethodAccess-Control-Request-Headers 是否被允许。如果被允许,服务器会在响应头中添加相应的字段。
  4. 浏览器接收到预检请求的响应后,会检查 Access-Control-Allow-OriginAccess-Control-Request-MethodAccess-Control-Request-Headers 字段的值。
  5. 如果这些字段的值与请求的要求匹配,则浏览器继续发送实际的请求。
  6. 如果这些字段的值与请求的要求不匹配,则浏览器会抛出跨域或者请求失败的错误。

5. get和post的区别

  1. 针对数据操作的类型不同。GET对数据进行查询,POST主要对数据进行增删改!简单说,GET是只读,POST是写。

  2. 参数大小不同。GET请求在URL中传送的参数是有长度的限制,一般在2000个字符;而POST没有限制(GET请求参数的限制是来源与浏览器或web服务器限制了url的长度)

  3. 安全性不同。 GET参数通过URL传递,会暴露,不安全;POST放在Request Body中,相对更安全

  4. 浏览器回退表现不同。 GET在浏览器回退时是无害的,而POST会再次提交请求

  5. 浏览器对请求地址的处理不同 。GET请求地址会被浏览器主动缓存,而POST不会,除非手动设置

  6. 浏览器对响应的处理不同 。GET请求参数会被完整的保留在浏览器历史记录里,而POST中的参数不会被保留

在这里插入图片描述

6. 什么叫跨域?什么叫同源策略?

所谓同源策略是浏览器的一种安全机制,来限制不同源的网站不能通信。同源就是域名、协议、端口一
致。
域名、协议、端口有一个不一致就会导致跨域。

7. 如何解决跨域问题?

最初做项目的时候,使用的是 jsonp,但存在一些问题,使用 get 请求不安全,携带数据较小,后来通过了解和学习发现使用 proxy 代理使用比较方便–在开发中使用 proxy,在生产上使用 nginx 代理,这样开发过程中彼此都方便,效率也高;现在 h5 新特性还有 windows.postMessage()

1)JSONP
ajax 请求受同源策略影响,不允许进行跨域请求,而 <script> 标签 src 属性中的链接却可以访问跨域的 js 脚本,利用这个特性,服务端不再返回 JSON 格式的数据,而是 返回一段调用某个函数的 js 代码,在 src 中进行了调用,这样实现了跨域。

步骤:

  1. 去创建一个 script
  2. script 的 src 属性设置接口地址
  3. 接口参数,必须要带一个自定义函数名,要不然后台无法返回数据
  4. 通过定义函数名去接受返回的数据

纯JS实现:

//动态创建 script
var script = document.createElement('script');

// 设置回调函数
function getData(data) {
    console.log(data);
}

//设置 script 的 src 属性,并设置请求地址
script.src = 'http://localhost:3000/?callback=getData';

// 让 script 生效
document.body.appendChild(script);

缺点:
JSON 只支持 get,因为 script 标签只能使用 get 请求; JSONP 需要后端配合返回指定格式的数据。

vue中使用jsonp(下载vue-jsonp插件)
Vue项目中发送JSONP请求:(使用vue-jsonp发送请求)

import { jsonp } from 'vue-jsonp'
function getAddressInfo({ lat, lng }) {
  jsonp('https://apis.map.qq.com/ws/geocoder/v1/?', {
    location: lat + ',' + lng,
    key: '',
    output: 'jsonp'
  }).then(res => {
    console.log(res)
  }).catch((err) =>{
    console.log() )
  })
}

2)CORS

使用额外的 HTTP 头来告诉 浏览器 让运行在一个 origin 上的Web应用被准许访问来自不同源服务器上的指定的资源。服务器设置对CORS的支持原理:服务器设置 Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许跨域请求。

推荐原因
这种方案对于前端来说没有什么工作量,工作量基本都在后端这里。
只要第一次配好了,之后不管有多少接口和项目复用就可以了,一劳永逸的解决了跨域问题,而且不管是开发环境还是正式环境都能方便的使用。
但总有后端觉得麻烦不想这么搞,那纯前端也是有解决方案的。

想进一步了解CORS可查阅 跨域资源共享 CORS 详解

3)proxy代理 + Nginx

nginx是一款极其强大的web服务器,其优点就是轻量级、启动快、高并发。
跨域问题的产生是因为浏览器的同源政策造成的,但是服务器与服务器之间的数据交换是没有这个限制。

dev 开发模式下可以下使用 webpackproxy 使用也是很方便,参照 proxy配置文档 就会使用了。但这种方法在生产环境是不能使用的。在生产环境中需要使用 nginx 进行反向代理。不管是 proxy 和 nginx 的原理都是一样的,通过搭建一个中转服务器来转发请求规避跨域的问题。

可以通过 vue.config.js 中的 devServer.proxy 选项来配置。新增以下代码

module.exports = defineConfig({
{
  devServer: { //devServer 的意思其实就是通过 webpack 帮你在本地起一个 node 服务器
    proxy: {
      '/api': { // '/api'是代理标识,用于告诉node,url前面是 /api 的就是使用代理的
        target: 'http://dnny.net', // 请求的目标地址,一般是指后台服务器地址
        changeOrigin: true, //是否跨域(换源)
        pathRewrite: { //pathRewrite作用是把实际Request Url中 '/api' 用 ""代替
          '^/api': '' 
        }
      },
      '/foo': {
        target: '<other_url>'
      }
    }
  }
}
})

假如需要请求的接口url是’http://dnny.net/info’,代理配置成功后,可以在浏览器的开发者工具中发现请求的接口url却是http://localhost:8080/api/info,但实际的请求是http://dnny.net/info。

因为代理服务器会做以下转发:
http://localhost:8080/api/info => http://dnny.net/api/info => http://dnny.net/info

可参考:前端使用proxy解决跨域问题

8. 介绍一下HTTP缓存策略 (强缓存和协商缓存)

HTTP缓存策略缓存的是已经请求过的HTTP资源,包括HTML、CSS、JavaScript文件、图片等。当浏览器第一次请求某个资源时,服务器会返回资源的内容以及相关的缓存控制参数(如缓存过期时间缓存标识符等)。浏览器在接收到这些信息后,会根据缓存策略来判断是否需要缓存该资源,并将其保存到本地缓存中。当下次请求同一个资源时,浏览器可以直接从本地缓存中获取该资源,而无需再向服务器发送请求,从而提高了页面加载速度和用户体验。

浏览器缓存的特点:

  • 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
  • 浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中

根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强缓存协商缓存

  1. 强缓存:使用强缓存策略时,如果缓存资源在过期时间内,是的话直接从本地缓存中读取资源,不与服务器进行通信。常见的缓存控制字段有Expires和Cache-Control。
  2. 协商缓存:如果强缓存失效后,客户端将向服务器发出请求,进行协商缓存。浏览器携带上一次请求返回的响应头中的 缓存标识 向服务器发起请求(如ETag、Last-Modified等),由服务器判断资源是否更新。如果资源没有更新,则返回状态码 304 Not Modified,告诉浏览器可以使用本地缓存;否则返回新的资源内容。强缓存优先级高于协商缓存,但是协商缓存可以更加灵活地控制缓存的有效性。
  3. 离线缓存:离线缓存可以使网站在没有网络连接的情况下仍然可以访问,他通过将网站的资源存储在本地缓存中,供客户端在没有网络连接时使用。离线缓存需要使用Service Worker来实现。

强缓存和协商缓存以及缓存标识详细讲解

9. 什么叫内存泄漏?知道哪些会导致内存泄漏?

在javaScript中,内存泄漏指的是程序分配的内存空间因为某些原因而无法被垃圾回收机制正确的释放。这通常是由于代码中持续引用着不需要的对象或者变量,或者存在未及时清除的定时器或者事件监听器等情况所致。如果内存泄漏问题长期存在,会导致浏览器卡顿或者崩溃,影响用户体验。

内存泄漏需满足两个前提条件:

  • 我确定不需要这块内存了
  • 无法被垃圾回收器回收

其他内存泄漏:

  1. 不规范的使用闭包:从而导致某些变量一直被留在内存当中。把不用的闭包相关数据(内存)释放 置为null。

  2. 没有清理定时器或回调函数:设置了 setInterval 定时器,忘记取消,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,无法被回收。

  3. 互相引用:如果两个对象相互引用,但是没有其他地方引用它们,那么它们就不能被垃圾收集器回收,导致内存泄漏。

  4. 意外的全局变量:由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收。

// bar 被添加到 window 对象上了,如果 bar 指向一个巨大的对象或 DOM 节点,那就是安全隐患。
function foo(arg) {
	bar = "this is a hidden global variable";
}
  1. 脱离 DOM 的引用:获取一个 DOM 元素的引用,而后面这个元素被删除,由于一直保留了对这个元素的引用,所以它也无法被回收。
// 在对象中引用DOM
var elements = {
	button: document.getElementById("button")
};
function doStuff() {
	button.click();
}
function removeButton() {
	// 将body中的btn移除, 也就是移除 DOM树中的btn
	document.body.removeChild(document.getElementById("button"));
	// 但是此时全局变量elements还是保留了对btn的引用, btn还是存在于内存中,不能被GC回收
}

解决方法:手动删除,elements.btn = null

10. 浏览器垃圾回收机制

JavaScript 的垃圾回收机制是自动垃圾回收,它的主要工作就是定期扫描内存中的对象并清除不再使用的对象所占用的内存空间,以避免内存泄漏和浪费。

具体来说,JavaScript 引擎会在变量不再有用时(即没有被任何其他变量或函数引用)将其标记为“可回收”对象。然后,垃圾回收器会定期扫描内存,找到这些可回收对象,并释放他们所占的内存空间。垃圾回收器采用的算法包括标记-清除算法引用计数算法分代回收算法等。

需要注意的是,垃圾回收器只能回收动态分配内存,而不能处理静态分配内存,例如全局变量和闭包等。因此,在编写 JavaScript 代码时,我们应该尽可能避免创建过多的全局变量和闭包,同时及时处理掉不再使用的变量和对象,以便垃圾回收器能够更好的完成垃圾回收工作。

可参考:简单了解 JavaScript 垃圾回收机制
深入理解JavaScript——垃圾回收机制

11. 什么是v8引擎,它的回收机制是什么呢?

先了解下什么是v8引擎。
V8是一种开源的JavaScript引擎,由Google公司开发。它负责将JavaScript代码编译和执行为机器码,并在浏览器(例如Chrome)中高效地运行JavaScript应用程序。

V8引擎垃圾回收机制

V8引擎使用 分代回收策略 来实现垃圾回收。

在分代回收策略中,V8会将堆内存分为新生代老生代两部分,新生代中的对象生命周期短暂,通常只支持 1~8M 的容量,因此采用基于Scavenge算法的标记-复制方式;新生代内存回收频率很高,速度也很快,但是空间利用率很低,因为有一半的内存空间处于"闲置"状态。老生代中的对象寿命较长,因此采用基于Mark-Sweep算法Mark-Compact算法的混合方式进行回收。前者标记并清除非活跃对象,后者在清除之后进行空间整理(到一边),这样空间就大了。通过这些技术,V8可以高效地回收不再使用的内存,从而提高程序性能和稳定性。

新生代和老生代使用两个不同的垃圾回收器。

  • 副垃圾回收器,主要负责新生代的垃圾回收。
  • 主垃圾回收器,主要负责老生代的垃圾回收。

副垃圾回收器 (新生代垃圾回收):
如下图所示:

在这里插入图片描述

  • 新生代中用 Scavenge 算法来处理。所谓 Scavenge 算法,是把新生代空间对半划分为两个区域,一半是对象区域,一半是空闲区域
  • 新加入的对象都会存放到对象区域,当对象区域快被写满时,就需要执行一次垃圾清理操作。
  • 在垃圾回收过程中,首先要对对象区域中的垃圾做标记;标记完成之后,就进入垃圾清理阶段,副垃圾回收器会把这些存活的对象 复制空闲区域 中,同时它还会把这些对象有序地排列起来,所以这个复制过程,也就相当于完成了内存整理操作,复制后空闲区域就没有内存碎片了。
  • 完成复制后,对象区域与空闲区域进行角色翻转,也就是原来的对象区域变成空闲区域,原来的空闲区域变成了对象区域。这样就完成了垃圾对象的回收操作,同时这种角色翻转的操作还能让新生代中的这两块区域无限重复使用下去。

由于新生代中采用的 Scavenge 算法,所以每次执行清理操作时,都需要将存活的对象从对象区域复制到空闲区域。但复制操作需要时间成本,如果新生区空间设置得太大了,那么每次清理的时间就会过久,所以为了执行效率,一般新生区的空间会被设置得比较小。

主垃圾回收器(老生代垃圾回收):

也正是因为新生区的空间不大,所以很容易被存活的对象装满整个区域。为了解决这个问题,JavaScript 引擎采用了对象晋升策略,也就是经过两次垃圾回收依然还存活的对象,会被移动到老生区中。

除了新生区中晋升的对象,一些大的对象会直接被分配到老生区。因此老生区中的对象有两个特点,一个是对象占用空间大,另一个是对象存活时间长

由于老生区的对象比较大,若要在老生区中使用 Scavenge 算法进行垃圾回收,复制这些大的对象将会花费比较多的时间,从而导致回收执行效率不高,同时还会浪费一半的空间。因而,主垃圾回收器是采用标记 - 清除(Mark-Sweep)标记 - 整理(Mark-Compact)的算法进行垃圾回收的。

算法原理:

  • 递归遍历这组根元素,标记垃圾数据。
  • Mark-Sweep算法 标记活跃对象并清除非活跃对象。
  • Mark-Compact算法 清除标记后产生大量不连续内存,需要进行空间整理(到一边),这样空间就大了。由于是移动对象,它的执行速度不可能很快,事实上也是整个过程中最耗时间的部分。

用图来解释会更清晰:

在这里插入图片描述

在这里插入图片描述

增量标记

由于JS的单线程机制,V8 在进行垃圾回收的时候,都需要将正在执行的 JavaScript 脚本暂停下来,待垃圾回收完毕后再恢复脚本执行。我们把这种行为叫做全停顿
倘若老生代的垃圾回收任务很重,那么耗时会非常可怕,严重影响应用的性能。
那这个时候为了避免这样问题,V8 采取了增量标记的方案,即将一口气完成的标记任务分为很多小的部分完成,每做完一个小的部分就"歇"一下,就js应用逻辑执行一会儿,然后再执行下面的部分,如果循环,直到标记阶段完成才进入内存碎片的整理上面来。其实这个过程跟React Fiber的思路有点像。
经过增量标记之后,垃圾回收过程对JS应用的阻塞时间减少到原来了1 / 6, 可以看到,这是一个非常成功的改进。

关于React Fiber的思路展开一下:
Fiber 的做法是:分片。 把一个很耗时的任务分成很多小片,每一个小片的运行时间很短,虽然总时间依然很长,但是在每个小片执行完之后,都给其他任务一个执行的机会,这样唯一的线程就不会被独占,其他任务依然有运行的机会。而维护每一个分片的数据结构, 就是Fiber。

总结 - 新生代 VS 老生代

1.新生代垃圾回收是临时分配的内存,存活时间短;老生代垃圾回收是常驻内存,存活时间长
2.新生代垃圾回收由副垃圾回收器负责;老生代垃圾回收由主垃圾回收器负责
3.新生代采用 Scavenge 算法;老生代采用标记 - 清除(Mark-Sweep)标记 - 整理(Mark-Compact)的算法进行垃圾回收。
1)Scavenge 算法:将空间分为两半,一半是对象区域,一半是空闲区域。新加入的对象会放在 对象区域,当空间快满时,执行垃圾清理;再角色调换,再当调换完后的 对象区域 快满时,再执行垃圾清理,如此反复。
2)标记-清理-整理:此为两个算法,「标记-清理」算法和 「标记-整理」算法
标记-清理:标记活动对象,清除非活跃对象
标记-整理:清理完内存后,会产生不连续的内存空间,为节省空间,整理算法会将内存排序到一处空间,空间就变大了

可参考:V8内存管理及垃圾回收机制
深入理解JavaScript——垃圾回收机制

12. cookie和session 的区别

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上。
  2. cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
    考虑到安全应当使用session。
  3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
    考虑到减轻服务器性能方面,应当使用COOKIE。
  4. 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
  5. 所以个人建议:

将登陆信息等重要信息存放为 session
其他信息如果需要保留,可以放在 cookie 中

13. cookie、sessionStorage和localStorage的区别和使用场景

相同点:

  • 存储在客户端

不同点:

1)与服务器交互

  • cookie 是网站为了标示用户身份而储存在用户本地终端上的数据(通常经过加密)

  • cookie 始终会在同源 http 请求头中携带(即使不需要),在浏览器和服务器间来回传递

  • sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存

    2)存储大小

  • cookie 数据根据不同浏览器限制,大小一般不能超过 4k

  • sessionStorage 和 localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大

    3)有效时间

  • localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据

  • sessionStorage 数据在当前浏览器窗口关闭后自动删除

  • cookie 设置的cookie过期时间之前一直有效,与浏览器是否关闭无关

应用场景:

  • 标记用户与跟踪用户行为的情况,推荐使用 cookie
  • 适合长期保存在本地的数据(令牌),推荐使用 localStorage
  • 敏感账号一次性登录,推荐使用 sessionStorage

14. 浏览器常见的攻击方式,存在的原因、防御的方法?

浏览器页面安全问题的主要原因,就是浏览器为同源策略开的两个“后门”:

  • 一个是在页面中可以任意引用第三方资源;
  • 一个是通过 CORS 策略让 XMLHttpRequest 和 Fetch 去跨域请求资源。

然后有了被攻击的机会,攻击方式有:XSS跨站脚本攻击(Cross Site Scripting)、 CSRF跨站请求伪造( Cross-site request forgery )

15. XSS跨站脚本攻击

什么是XSS攻击?

XSS 全称是 Cross Site Scripting,为了与“CSS”区分开来,故简称 XSS,翻译过来就是“跨站脚本”。XSS 攻击是指浏览器中执行恶意脚本(无论是跨域还是同域),从而拿到用户的信息并进行操作。

这些操作一般可以完成下面这些事情:

  1. 窃取 Cookie 信息:恶意 javaScript 通过 document.cookie获取 Cookie 信息。
  2. 监听用户行为: 通过 addEventListener 接口来监听键盘事件,比如输入账号密码后直接发送到黑客服务器。
  3. 修改 DOM 伪造假的登录窗口
  4. 在页面内生成浮窗广告:这些广告会严重地影响用户体验。

通常情况下,XSS攻击的实现方式有三种:存储型 XSS 攻击反射型 XSS 攻击基于 DOM 的 XSS 攻击,都是通过注入恶意脚本来实现的攻击。

1. 存储型 XSS 攻击

存储型的 XSS 攻击将脚本存储到了服务端的数据库,然后在客户端执行这些脚本,从而达到攻击的效果。

常见的场景是留言评论区提交一段脚本代码,如果前后端没有做好转义的工作,那评论内容存到了数据库,在页面渲染过程中直接执行, 相当于执行一段未知逻辑的 JS 代码,是非常恐怖的。这就是存储型的 XSS 攻击。

2. 反射型 XSS 攻击

反射型 XSS 攻击指的是,恶意 JavaScript 脚本属于用户发送给网站请求中的一部分,随后网站又把恶意脚本返回给用户。当恶意 脚本在用户页面中被执行时,黑客就可以利用该脚本做一些恶意操作。

比如浏览器中输入下面这段url:

http://localhost:3000/?xss=<script>alert('你被xss攻击了')</script>

这样,在服务器端会拿到xss参数,然后将内容返回给浏览器端,浏览器将这些内容作为HTML的一部分解析,发现是一个js脚本,直接执行,这样就被攻击了。在现实生活中,黑客经常会通过 QQ 群或者邮件等渠道诱导用户去点击这些恶意链接,所以对于一些链接我们一定要慎之又慎。

之所以叫反射型,是因为恶意脚本是通过作为网络请求的参数,经过服务器,然后再反射到HTML文档中,执行解析。
另外需要注意的是,Web 服务器不会存储反射型 XSS 攻击的恶意脚本,这是和存储型 XSS 攻击不同的地方。

3. 基于 DOM 的 XSS 攻击

基于 DOM 的 XSS 攻击是不牵涉到服务器的,而是作为中间人的角色,在数据传输过程劫持到网络数据包,然后修改里面的 html 文档
这样的劫持方式包括WIFI路由器劫持或者本地恶意软件等。

防范措施

通过上面3种类型的 XSS 攻击,发现它们都有一个共同点,那就是首先往浏览器中注入恶意脚本,然后再通过恶意脚本将用户信息发送至黑客部署的恶意服务器上。
那么要防范XSS攻击,就要避免这些恶意脚本的执行。

1. 前端和服务器对输入脚本进行过滤或转码

千万不要相信任何用户的输入!
不管在前端还是后端,都要对用户的输入进行过滤转码,比如最典型的:

code:<script>alert('你被xss攻击了')</script>

这段代码过滤关键词 script 标签 后,只留下了:

code:

除了过滤之外,服务器还可以对这些内容进行转码,还是上面那段代码,经过转码之后,效果如下所示:

code:&lt;script&gt;alert(&#39;你被xss攻击了&#39;)&lt;/script&gt;

被转码后,即使这段脚本返回给页面,页面也不会执行这段脚本。

2. 充分利用 CSP

CSP,即浏览器中的内容安全策略,它的核心思想就是服务器决定浏览器加载哪些资源,具体来说可以完成以下功能:

  • 限制加载其他域下的资源文件。
  • 禁止向第三方域提交数据,这样用户数据也不会外泄。
  • 提供上报机制,能帮助我们及时发现 XSS 攻击。
3. 使用 HttpOnly 属性

由于很多 XSS 攻击都是来盗用 Cookie 的,因此还可以通过使用 HttpOnly 属性来保护我们 Cookie 的安全,这样就不能通过document.Cookie 来读取了。
需要在服务器端设置,HTTP 响应头是这样的:

set-cookie: NID=189=M8q2FtWbsR8RlcldPVt7qkrqR38LmFY9jUxkKo3-4Bi6Qu_ocNOat7nkYZUTzolHjFnwBw0izgsATSI7TZyiiiaV94qGh-BzEYsNVa7TZmjAYTxYTOM9L_-0CN9ipL6cXi8l6-z41asXtm2uEwcOC5oh9djkffOMhWqQrlnCtOI; expires=Sat, 18-Apr-2020 06:52:22 GMT; path=/; domain=.google.com; HttpOnly

总结

  • XSS 攻击是指浏览器中执行恶意脚本, 然后拿到用户的信息进行操作。
  • 主要分为存储型反射型文档型
  • 防范的措施包括:对输入内容转码或者过滤,让其不可执行、利用 CSP,利用 Cookie 的 HttpOnly 属性。

16. CSRF跨站请求伪造

什么是CSRF攻击?

CSRF 英文全称是 Cross-site request forgery,所以又称为“跨站请求伪造”。攻击者诱导用户进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用用户在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。例如转账、修改密码等。
简单来讲,CSRF攻击就是黑客利用了用户的登录状态,并通过第三方站点来做一些坏事。

引用网上的一张图便于理解。

在这里插入图片描述

从上图可以看出,发起 CSRF 攻击的三个必要条件:

  1. 目标站点(受信任网站A)一定要有 CSRF 漏洞;
  2. 用户要登录过目标站点,并在浏览器上保持该站点的登录状态Cookie。
  3. 在不登出A的情况下,访问第三方危险网站B,可以是黑客的站点,也可以是一些论坛。

满足以上三个条件之后,黑客就可以对用户进行 CSRF 攻击了。其最关键的一点是要能找到服务器的漏洞,所以说对于 CSRF 攻击我们主要的防护手段是提升服务器的安全性。

通常当用户打开了黑客的页面后,黑客有三种方式去实施 CSRF 攻击。

1. 自动发 GET 请求

黑客网页html里面可能有一段这样的代码:

 <img src="https://受攻击网站xxx.com/info?user=tiechui&number=100">

进入页面后自动发送 get 请求,值得注意的是,这个请求会自动带上关于 xxx.com 的 cookie 信息(这里是假定你已经在 xxx.com 中登录过)
假如服务器端没有相应的验证机制,它可能认为发请求的是一个正常的用户,因为携带了相应的 cookie,然后进行相应的各种操作,可以是转账汇款以及其他的恶意操作。

2. 自动发起 POST 请求

黑客可能自己填了一个表单,写了一段自动提交的脚本。

 <form id='hacker-form' action="https://受攻击网站xxx.com/info" method=POST>  
   <input type="hidden" name="user" value="tiechui" />   
   <input type="hidden" name="number" value="100" /> 
 </form> 
 <script> document.getElementById('hacker-form').submit(); </script>

同样也会携带相应的用户 cookie 信息,让服务器误以为是一个正常的用户在操作,让各种恶意的操作变为可能。

3. 引诱用户点击链接

在黑客的网站上,可能会放上一个链接,驱使你来点击:

<div>
  <img width=150 src=http://images.xuejuzi.cn/1612/1_161230185104_1.jpg> </img>
  <a href="https://受攻击网站xxx.com/info?user=tiechui&number=100" taget="_blank">
    点击下载美女照片
  </a>
</div>

点击后,自动发送 get 请求,接下来和自动发 GET 请求部分同理。
csrf 一般是通过 img form 等构造请求发送的,因为这些请求不受跨域限制。

这就是CSRF攻击的原理。和XSS攻击对比,CSRF 攻击并不需要将恶意代码注入用户当前页面的html文档中,而是跳转到新的页面,利用服务器的验证漏洞和用户之前的登录状态来模拟用户进行操作

以上三种就是黑客经常采用的攻击方式。可以看出CSRF攻击存在的原因:

利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。

以上三种CSRF 攻击方式可能就会有疑问了,在浏览器打开第三方站点是如何拿到cookie的?第三方站点和目标站点不同,存在同源策略,那么CSRF是如何攻击的呢?

在第三方站点向目标服务器发起请求的时候,如果你曾经登录过目标站点,浏览器中存储这目标站点的cookie,浏览器会自动帮你把这些cookie带上的;黑客拿不到但是可以利用cookie,像是浏览器的这个cookie机制,帮助了csrf的攻击。
另外a标签,img、iframe src或者表单请求,这些请求不受跨域限制。

防范措施

1. 充分利用好 Cookie 的 SameSite 属性

CSRF攻击中重要的一环就是自动发送目标站点下的 Cookie,然后就是这一份 Cookie 模拟了用户的身份。因此在Cookie上面下文章是防范的不二之选。
恰好,在 Cookie 当中有一个关键的字段,可以对请求中 Cookie 的携带作一些限制,这个字段就是SameSite
SameSite可以设置为三个值,StrictLaxNone

  • Strict模式下,浏览器完全禁止第三方请求携带Cookie。比如请求baidu.com网站只能在baidu.com域名当中请求才能携带 Cookie,在其他网站请求都不能。
  • Lax模式,就宽松一点了,在跨站点情况下,但是只能在 get 方法提交表单或者a 标签发送 get 请求的情况下可以携带 Cookie,其他情况均不能。
  • None模式下,也就是默认模式,请求会自动携带上 Cookie。
2. 验证请求的来源站点

在服务器端验证请求来源的站点。由于 CSRF 攻击大多来自于第三方站点,因此服务器可以禁止来自第三方站点的请求。

这就需要要用到请求头中的两个字段: OriginReferer

其中,Origin只包含域名信息,而Referer包含了具体的 URL 路径。

当然,这两者都是可以伪造的,通过 Ajax 中自定义请求头即可,安全性略差。

3. CSRF Token

首先,在浏览器向服务器发起请求时,服务器生成一个 CSRF Token。CSRF Token 其实就是服务器生成的字符串,然后将该字符串植入到返回的页面中。
然后浏览器如果要发送请求,就必须带上这个字符串,然后服务器来验证是否合法,如果不合法则不予响应。这个字符串也就是CSRF Token,通常第三方站点无法拿到这个 token, 因此也就是被服务器给拒绝。

4. 重要接口加验证参数

如短信验证码、谷歌验证码验证。即使它发起请求了,没有用户本身的手机验证码、谷歌验证码也通过不了这次请求。

总结:

  • CSRF(Cross-site request forgery), 即跨站请求伪造,指的是黑客诱导用户点击链接,打开黑客的网站,然后黑客利用用户目前的登录状态发起跨站请求。
  • CSRF攻击一般会有三种方式:自动 GET 请求自动 POST 请求诱导点击链接发送 GET 请求
  • 防范措施:利用 Cookie 的 SameSite 属性、验证来源站点(origin/referer)CSRF Token重要接口加验证参数

15. CSRF 和 XSS 的区别

区别一:

  • CSRF :需要用户先登录受攻击网站 A ,获取 cookie
  • XSS :不需要登录。

区别二:(原理的区别)

  • CSRF :是利用受攻击网站 A 本身的漏洞,去请求网站 Aapi
  • XSS :是向受攻击网站 A 注入 JS 代码,然后执行 JS 里的代码,篡改网站 A 的内容。

区别三:攻击的目标不同

  • CSRF 攻击的目标是应用程序
  • XSS 攻击的目标是用户

本质上讲,XSS 是代码注入问题,CSRF 是 利用用户的登录状态 问题。 XSS 是内容没有过滤导致浏览器将攻击者的输入当代码执行。CSRF 则是因为浏览器在发送 HTTP 请求时候自动带上 cookie,而一般网站的 session 都存在 cookie里面(Token验证可以避免)。

可参考:
XSS 攻击和 CSRF 攻击各自的原理是什么?两者又有什么区别?以及如何防范?
XSS攻击与CSRF攻击

16. 对虚拟DOM的理解和优缺点?

虚拟DOM的实现原理与优缺点

理解

虚拟 DOM 就是为了解决浏览器性能问题而被设计出来的
它是将整个页面抽象为一个 JavaScript 对象树(虚拟DOM),当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异把所记录的差异应用到真正的 dom 树上,视图就更新了。利用DOM diff算法减少不必要的DOM操作和页面重绘,提高性能和用户体验。

虚拟DOM也可以方便实现组件化开发,使得前端代码更具可维护性和可复用性。

优点

1)快速渲染:虚拟 DOM 可以直接操作 JavaScript 对象,无需访问真实浏览器的 DOM。
2)减少不必要的 DOM操作:虚拟 DOM 通过 diff 算法比较前后两个状态的差别,只更新需要改变的部分,减少大量不必要的 DOM 操作,提升性能。
3)跨平台:虚拟 DOM 不依赖具体的浏览器实现,可以在不同的平台上使用,例如服务器渲染,移动端开发等。
4)提高开发效率:虚拟 DOM 可以简化组件的编写和维护,开发效率提高。

缺点

1)需要额外的内存开销:虚拟 DOM 需要创建一颗以 JavaScript 对象表示的虚拟 DOM 树,在一些场景下可能会占用过多的内存。
2)性能瓶颈:虚拟 DOM 在一些复杂场景下可能会导致性能瓶颈,例如大量的列表渲染、频繁的样式变化等。

17. 操作虚拟DOM真的比真实DOM方便吗?

很多人说虚拟dom操作回避原生dom更快,也不全面。比如,首次渲染或者所有节点都需要进行更新的时候,这个时候采用虚拟dom会比直接操作原生dom多一层构建虚拟dom的动作,会占用更多的内存以及延长渲染时间。
总之,

  • 虚拟DOM不一定会比操作原生DOM更快。
  • 虚拟DOM的优势在于节点进行改动的时候尽量减少开销。
  • 我们用vue等框架的本质是提升开发效率,让我们的注意力更集中于数据;我们使用框架做出的一切行为,都会被框架转化为对原生dom的操作。

可参考:虚拟dom比真实dom还快吗?90%回答掉坑里了


三、Ajax相关

1. 什么是ajax?

Ajax是全称是Asynchronous JavaScript and XML,即异步JavaScript和xml,用于在Web页面中实现异步数据交互,实现页面局部刷新

2. ajax原理??(创建ajax过程??)

1)创建一个XMLHttpRequest对象,用于向服务器发送请求和接收响应。
2)设置XHR对象的callback函数,该函数会在服务器响应返回后被调用。
3)使用XHR对象发送请求,并传递必要的参数(如请求的URL、请求类型、请求头、请求体等)
4)callback函数中处理服务器响应,通常是解析响应数据并更新网页内容。

以下是一个使用jQuery的Ajax示例代码:

$.ajax({
  url: "example.com/data",
  type: "GET",
  dataType: "json",
  success: function(data) {
    // 处理响应数据
  },
  error: function(jqXHR, textStatus, errorThrown) {
    // 处理请求错误
  }
});
// 该代码会向"example.com/data"发送一个GET请求,请求数据类型为JSON。
// 当服务器响应成功返回时,success函数会被调用,可以在该函数中处理响应数据。
// 如果请求出现错误,error函数会被调用,可以在该函数中处理错误情况。

总结一句话就是:
创建一个XHR对象,并发送异步请求,接着监听服务器响应结果,并把它渲染在页面上

3. ajax优缺点?

优点:

  1. 提升用户体验:可以在不刷新整个页面的情况下更新部分内容(局部内容更新),可以更快、更流畅的浏览网页
  2. 减少服务器负载:由于ajax只更新部分内容,因此可以减少服务器的负载和带宽消耗,提高网站性能和可扩展性
  3. 支持异步通信:支持异步通信,可以在后台向服务器发送请求,不打断用户的操作
  4. 界面和应用相分离(ajax将界面和应用分离也就是数据与呈现相分离)

缺点:

  1. 对搜索引擎不友好:由于ajax动态更新页面内容,搜索引擎可能无法索引所有内容,影响网站SEO效果。
  2. 安全问题: 由于ajax可以向服务器发送异步请求,可能会导致跨站点脚本攻击(XXS)和跨站点请求伪造(CSRF)等安全性问题。
  3. 对浏览器兼容性要求高:不同浏览器对ajax的支持程度不同,需要编写兼容多种浏览器的代码。
  4. 可维护性差:由于ajax将数据和处理逻辑分散在多个文件中,代码结构复杂,可维护性较差。
  5. 难以调试:由于ajax是异步通信,调试时可能需要使用特殊工具和技术,难度较大。

持续更新中。。。

本文参考:
极客时间- 浏览器工作原理与实践

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁锤妹妹@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值