浏览器
localStorage和
sessionStorage区别
localStorage
和 sessionStorage
都是 Web Storage API 的一部分,用于在浏览器中存储数据。
1. 存储期限
Cookie:
- 可以设置过期时间,过期后自动删除。若不设置过期时间,则在浏览器关闭时被清除(会话 cookie)。
localStorage:
- 数据永久存储,直到显式删除或用户手动清除浏览器缓存。
- 适合需要长期保存的数据,如用户偏好设置。
sessionStorage:
- 数据存储在当前会话中,浏览器窗口或标签页关闭后,数据会被清除。
- 适合一次会话需要的数据,如临时表单输入。
2. 作用域
Cookie:
- 可以在同源的多个窗口和标签页之间共享。可以指定 cookie 的作用域(路径和域)。
localStorage:
- 数据在同源(同域名、同端口、同协议)的所有窗口和标签页之间共享。
sessionStorage:
- 数据在同源的同一窗口或标签页之间共享,但不同的窗口或标签页(即使同源)之间不共享。
3. 存储大小限制
每个 cookie 大小限制为 4KB 左右,总的 cookie 数量和大小会受到浏览器限制(通常每个域名最多可存储 20-50 个 cookie)。
localStorage和sessionStorage:两者的存储大小限制通常为 5-10MB,具体取决于浏览器。
4. API 方法
Cookie:
- 通过 HTTP 请求发送,通常在请求头中传递。可通过 JavaScript 使用
document.cookie
访问和修改。
localStorage 和 sessionStorage:
- 两者都支持
setItem()
,getItem()
,removeItem()
, 和clear()
方法。
5. 使用场景
Cookie:
Cookie:通常用于存储用户认证信息、跟踪用户会话、跟踪用户行为等。
localStorage:适用于需要长期存储的数据,如用户主题偏好、购物车内容等。
sessionStorage:适用于一次性操作的数据,如步骤表单输入、临时设置等。
总结
cookie
适合需要在服务器和客户端之间传递的小量数据,localStorage
和 sessionStorage
适合存储较大的客户端数据,localStorage
用于长期存储,而 sessionStorage
用于一次性会话数据。选择合适的存储方式取决于具体需求和数据的生命周期。
浏览器缓存机制介绍与缓存策略剖析
强缓存是利用 http
头中的 Expires
和 Cache-Control
两个字段来控制的。
no-store 与 no-cache
no-cache
绕开了浏览器:我们为资源设置了no-cache
后,每一次发起请求都不会再去询问浏览器的缓存情况,而是直接向服务端去确认该资源是否过期(即走我们下文即将讲解的协商缓存的路线)。no-store
比较绝情,顾名思义就是不使用任何缓存策略。在no-cache
的基础上,它连服务端的缓存确认也绕开了,只允许你直接向服务端发送请求、并下载完整的响应。
协商缓存
服务端 Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT
客户端 If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT
问题
- 我们编辑了文件,但文件的内容没有改变。服务端并不清楚我们是否真正改变了文件,它仍然通过最后编辑时间进行判断。因此这个资源在再次被请求时,会被当做新资源,进而引发一次完整的响应——不该重新请求的时候,也会重新请求。
- 当我们修改文件的速度过快时(比如花了
100ms
完成了改动),由于If-Modified-Since
只能检查到以秒为最小计量单位的时间差,所以它是感知不到这个改动的——该重新请求的时候,反而没有重新请求了。
服务段: ETag: W/"2a3b-1602480f459"
客户端:If-None-Match: W/"2a3b-1602480f459"
Etag
的生成过程需要服务器额外付出开销,会影响服务端的性能,这是它的弊端。因此启用 Etag
需要我们审时度势。正如我们刚刚所提到的——Etag
并不能替代 Last-Modified
,它只能作为 Last-Modified
的补充和强化存在。 Etag 在感知文件变化上比 Last-Modified 更加准确,优先级也更高。当 Etag 和 Last-Modified 同时存在时,以 Etag 为准。
浏览器输入 URL 到渲染页面的过程。
- DNS 解析:将 URL 中的域名解析为对应的 IP 地址。如果浏览器中有缓存的 DNS 记录,则可以直接使用缓存中的结果;否则会向 DNS 服务器发出请求进行解析。
- TCP 连接:使用 HTTP 协议的客户端与服务器进行 TCP 连接,进行三次握手建立连接。
- 发送 HTTP 请求:客户端向服务器发送 HTTP 请求,包括请求行(请求方式、URL、协议版本)、请求头(例如浏览器的 User-Agent、Accept 等信息)和请求体(例如 POST 请求中提交的数据)。
- 服务器响应:服务器收到请求后,会根据请求内容生成相应的响应,包括响应行(状态码、协议版本等)、响应头(例如 Content-Type、Cache-Control 等)和响应体(例如 HTML、CSS、JS 文件等)。
- 接收响应内容:浏览器接收到服务器响应后,开始接收响应体中的内容。如果响应体是 HTML 文件,那么浏览器会进行解析,并向服务器发出进一步的请求获取 HTML 文件中引用的其他资源(例如 CSS、JS 文件、图片等)。
- 解析 HTML 文件:浏览器解析 HTML 文件,生成 DOM 树。在解析过程中,如果遇到样式表和脚本文件等资源,则会异步请求这些资源并继续解析。
- 构建渲染树:根据 DOM 树和 CSS 样式信息构建渲染树,渲染树只包括需要显示的节点,例如可见的文本、图像等。
- 布局:根据渲染树中每个节点的大小、位置等信息,计算它们在屏幕上的位置,并将它们进行布局。
- 绘制:根据渲染树和布局信息,将每个节点绘制到屏幕上。
- 加载 JS 脚本:如果 HTML 文件中引用了 JS 脚本文件,那么浏览器会异步加载这些脚本文件。JS 文件加载完成后,浏览器会执行这些脚本。
- 页面交互:当用户和页面进行交互时,例如点击链接、滚动页面等操作,浏览器会根据操作进行相应的处理,例如加载新的页面、触发滚动事件等。
DNS解析
- 顶级域名 .com 、
- ⼆级域名 .com.cn 、 三级域名 ww.baidu.com.cn , 有多少个点就是⼏级域名
访问过程:我们访问 ww.baidu.com.cn
- 操作系统⾥会对 DNS 解析结果做缓存,如果缓存中有直接返回 IP 地址查找
C:\WINDOWS\system32\drivers\etc\hosts
如果有直接返回 IP 地址 - 通过 DNS 服务器查找离⾃⼰最近的根服务器,通过根服务器找到 .cn 服务器,将 ip 返回给 DNS 服务器
- DNS 服务器会继续像此 ip 发送请求,去查找对应 .cn 下 .com 对应的 ip ...
- 获取最终的 ip 地址。缓存到 DNS 服务器上
TCP和UDP
- 连接性:TCP是面向连接的协议,UDP是无连接的协议。TCP在数据传输前需要建立连接,而UDP不需要。
- 可靠性:TCP是一种可靠的协议,它能够确保数据的完整性和可靠性。当数据包传输失败时,TCP会自动重传数据,直到数据被正确接收。而UDP则不能保证数据传输的可靠性,当数据包丢失或损坏时,UDP不会自动重传数据。
- 速度:UDP比TCP快,因为UDP没有TCP的确认、流量控制和重传机制等,所以它的传输速度更快。但UDP在传输过程中可能会出现数据丢失、重复和乱序等问题。
- 数据量:TCP可以传输大量的数据,而UDP每次只能传输较小的数据包。
- 适用场景:TCP适用于对数据传输可靠性要求较高的场景,比如文件传输、电子邮件等;而UDP适用于对数据传输速度要求较高、数据可靠性要求较低的场景,比如视频、语音等实时数据传输。
HTTP
GET和POST区别
- GET用于获取资源,而POST用于提交资源;
- GET请求参数以查询字符串形式附在URL后面,而POST请求参数在请求体中;
- GET请求的参数长度限制受到URL长度限制的影响,而POST请求则没有限制;
- GET请求是幂等的,即多次请求得到的结果相同;POST请求是非幂等的,即多次请求得到的结果不同;
- GET请求可以被缓存,POST请求不会被缓存。
0.9
特点:
- 只有一个请求行;
- 服务器仅返回数据,没有响应头。
瓶颈:
- 仅支持 HTML,无法传输其他类型文件;
- 文件编码格式过少,仅局限于 ASCII。
- 如果请求的页面不存在,也不会返回任何错误码。
HTTP/1.0
特点:
- 引入请求头和响应头(数据类型、语言版本、编码类型、用户代理);
- 数据压缩;
- 引入状态码;
- 提供了 Cache缓存机制(head 里的缓存头:If-Modified-Since/Last-Modified 、Expires)。
瓶颈:
- 仅支持短连接,对于包含多个请求的文件,会大大增加开销;
- 串行文件传输,一个请求没有及时返回,会引起队头阻塞;
- 一个服务器仅支持一个域名;
- 因为在响应头中需要指定数据大小,因此无法接收动态生成的数据;
- 服务器只能传递完整的数据,而不能满足“只想要数据的一部分”这样的需求,会导致带宽浪费;
- 不支持断点续传。
- 每次数据传输,在 TCP 建立连接时,三次握手都会有1.5 个 RTT(round-trip time)的延迟。
HTTP/1.1
特点
- ⻓连接(持久连接)
TCP 的连接和关闭⾮常耗时间,所以我们可以复⽤TCP 创建的连接(最多 6 个)。HTTP/1.1 响应中默认会增加Connection:keep-alive
2. 管线化(已弃用)
如果值创建⼀条 TCP 连接来进⾏数据的收发,就会变成 "串⾏"模式,如果某个请求过慢就会发⽣阻塞问题。 Head-of-line blocking 管线化就是不⽤等待响应亦可直接发送下⼀个请求。
这样就能够做到同时并⾏发送多个请求
同⼀个域名有限制,那么我就多开⼏个域名 域名分⽚
3. host 字段
http1.1 中还新增了 host 字段,用来指定服务器的域名。
引入虚拟主机技术,让一个服务器可以支持多个域名;
引入 range 头域(支持断点续传)
body(gzip压缩)
引入 Cookie与安全机制;
优化缓存策略
- Expires / Cache-Control
- if-Modified-Since/Last-modified (最后修改时间) if-None-Match/Etag(指纹)
请求方法和状态码
http1.1 相对于 http1.0 还新增了很多请求方法,如 PUT、HEAD、OPTIONS 等。
http1.1 相对于 http1.0 还新增了 24状态码,如 409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
瓶颈:
- TCP 慢启动导致小文件建立连接过慢;
- 资源下载机制不完善,无法实现资源下载时的优先级调整;
- 一个 TCP 连接只能处理一个请求,请求头易阻塞。
HTTP/1.1
中只优化了body(gzip压缩
)并没有对头部进⾏处理- 当我们请求某个网址的时候,服务器能不能提前将页面需要的重要资源推送过来,而不是等待浏览器扫描 html 后再去加载?
- 既然多个 TCP 链接存在竞争关系,我们能不能让浏览器将针对同一个域名的所有 http 请求都基于同一个 tcp 链接呢?这样既减少了竞争,也减少了 tcp 链接的耗时操作。
HTTP1.1和HTTP2的区别?
HTTP1.1和HTTP2是两个不同版本的HTTP协议,它们在以下方面有所不同:
- 多路复用:HTTP2支持一个连接中的多个请求和响应,这称为多路复用。HTTP1.1需要为每个请求和响应建立单独的连接。
- 二进制传输:HTTP2采用二进制协议,可以更快地解析和传输,而HTTP1.1则采用文本协议。
- 首部压缩:HTTP2使用HPACK算法对头部信息进行压缩,减少了数据传输的大小,提高了性能。
- 服务器推送:HTTP2支持服务器推送,这使得服务器可以在客户端请求之前将其他资源推送到客户端,从而提高了性能。
- 优先级控制:HTTP2支持请求优先级控制,可以让客户端设置请求的优先级,从而更快地获取重要资源。
- 改进的安全性:HTTP2要求使用TLS进行加密,从而提高了安全性。
总的来说,HTTP2相对于HTTP1.1在性能方面有很大的改进。多路复用、二进制传输和头部压缩等功能使得HTTP2更加高效,服务器推送和优先级控制则使得网站的性能更加优秀
HTTP2
特点
1. 多路复⽤
在⼀条 TCP 链接上可以乱序收发请求和响应,多个请求和响应之间不再有顺序关系
同域下采⽤⼀个 TCP 链接传输数据
引入二进制分帧层
HTTP/1.1 采⽤的是纯⽂本需要处理空⾏、⼤⼩写等。⽂本的表现形式有多样性,⼆进制则只有 0 和 1 的组合不在有歧义⽽且体积更⼩。把原来的 Header+body 的⽅式转换为⼆进制帧
HTTP/2虚拟了流的概念(有序的帧),给每帧分配⼀个唯⼀的流 ID,这样数据可以通过 ID 按照顺序组合起来
可以设置请求优先级;
2. 头部压缩
使⽤HPACK 算法压缩 HTTP 头
废除起始⾏,全部移⼊到 Header 中去,采⽤静态表的⽅式压缩字段
如果是⾃定义 Header,在发送的过程中会添加到静态表后,也就是所谓的动态表
对内容进⾏哈夫曼编码来减⼩体积
3.服务端推送
服务端可以提前将可能会⽤到的资源主动推送到客户端。
瓶颈:
- 单个数据包丢失会导致 TCP 上的队头阻塞;
- 握手产生的延时。
HTTP/3.0
- 零 RTT 建立连接
- . 连接迁移
- 队头阻塞/多路复用
- 拥塞控制
- 流量控制
HTTP 中的优化
- 减少⽹站中使⽤的域名域名越多,DNS 解析花费的时间越多。
- 减少⽹站中的重定向操作,重定向会增加请求数量。
- 选⽤⾼性能的 Web 服务器 Nginx 代理静态资源 。
- 资源⼤⼩优化:对资源进⾏压缩、合并(合并可以减少请求,也会产⽣⽂件缓存问题), 使⽤ gzip/br 压缩。
- 给资源添加强制缓存和协商缓存。
- 升级 HTTP/1.x 到 HTTP/2
- 付费、将静态资源迁移⾄ CDN
队头阻塞有什么优化
- 并行下载:浏览器可以同时发起多个请求,不必等待上一个请求的响应再发起下一个请求。
- 持久连接(HTTP Keep-Alive):浏览器和服务器之间可以建立持久的连接,使得多个请求可以共享同一个连接,减少建立连接的开销,提高请求响应效率。
- 域名分片(Domain Sharding):将资源分散到多个子域名下,可以增加并行下载的数量,提高页面加载速度。但是需要注意的是,域名分片也有一些负面影响,比如增加了 DNS 查询的开销,可能会导致 CDN 的缓存失效等问题。
- HTTP2:HTTP2 支持多路复用,可以在一个连接上同时传输多个请求和响应,避免了队头阻塞的问题,提高了请求响应效率。同时,HTTP2 还支持头部压缩、二进制传输等特性,进一步优化了性能。
简单请求和复杂请求
简单请求:请求方式只能是 GET、HEAD、POST 中的一种;
非简单请求:
- 请求方式为 PUT、DELETE、OPTIONS 以及 Content-Type 不属于上述三种之一;
- 请求头信息包含自定义字段。
非简单请求的特点是:浏览器会在正式请求之前先发出一个 OPTIONS 的试探性请求,服务器返回的响应中需要包含 Access-Control-Allow-Methods、Access-Control-Allow-Headers、Access-Control-Max-Age 等头信息。如果服务器返回的响应表明允许请求,则浏览器才会发出正式请求,否则将抛出异常。
状态码
1xx(信息性状态码):表示服务器已接收到客户端请求,正在进一步处理中。
- 100 Continue:表示服务器已经接收到请求头,并且客户端应该继续发送请求体。
- 101 Switching Protocols: 升级协议 websocker
- 102 Processing: 这个状态码表示服务器已经收到请求并且正在处理,但是响应还没有准备好发送。
2xx(成功状态码):表示请求已经被服务器接收、理解、并成功处理了。
- 200 OK:表示请求已成功,请求所希望的响应头或数据体将随此响应返回。
- 201 Created:表示请求已经被成功处理,并创建了新的资源。
- 204 No Content:表示请求已经成功处理,但响应报文中不包含实体的主体部分。
- 206 范围请求
3xx(重定向状态码):表示需要客户端进一步操作才能完成请求。
- 301 Moved Permanently:永久重定向
- 302 Found:临时重定向 302状态码则明确表示客户端应该使用新的URL发送一个GET请求。
- 304 Not Modified:协商缓存
- 307 临时 post
4xx(客户端错误状态码):表示客户端发送的请求有错误。
- 400 Bad Request:表示客户端发送的请求有语法错误,服务器无法识别。
- 401 Unauthorized:表示客户端请求未经授权,需要通过登录等方式进行身份验证。
- 403 Forbidden:表示客户端请求被拒绝,服务器理解请求但拒绝执行该请求。
- 404 Not Found:表示服务器无法根据客户端的请求找到资源。
5xx(服务器错误状态码):表示服务器处理请求出错。
- 500 Internal Server Error:表示服务器内部错误,无法完成请求。
- 502 Bad Gateway:表示服务器作为网关或代理角色时,从上游服务器接收到无效的响应。
- 503 Service Unavailable:表示服务器暂时无法提供服务,可能是由于过载或者维护。
握手
三次握手
第三次握手是可以携带数据的
那么为什么要三次握手呢?两次不行吗?
为了防止服务器端开启一些无用的连接增加服务器开销
客户端发起了 SYN=1 的第一次握手,服务器端就直接创建了这个连接并返回包含 SYN、ACK ,数据包丢失了,
客户端因超时重新发出请求时,服务器就会重新开启一个端口连接。
防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。 第一个延迟,新的发出后旧的到了,响应了旧的
“三次握手”是指在TCP(Transmission Control Protocol)协议中,建立一个可靠连接时,客户端与服务器之间的通信过程。这个过程确保了双方都准备好了进行数据传输,并且能够正确同步它们的初始序列号,以便后续的数据传输顺序正确。三次握手是保证TCP连接可靠性的核心机制之一。
三次握手的过程
第一次握手(SYN):
- 客户端向服务器发送一个SYN(同步序列号)报文,表明客户端希望发起连接。这是建立连接的请求。
- 在这个报文中,客户端选择一个随机的初始序列号
seq = x
,并将这个序列号放在SYN报文中。
状态变化:客户端进入
SYN_SENT
状态。第二次握手(SYN-ACK):
- 服务器收到客户端的SYN报文后,服务器知道了客户端希望建立连接,于是服务器向客户端发送一个SYN-ACK报文。这个报文有两个作用:
- 确认(ACK)客户端的SYN报文,确认号
ack = x + 1
表示已经收到客户端的SYN并准备建立连接。 - 服务器自己也发送一个SYN报文,表示希望与客户端建立连接,并且指定自己的初始序列号
seq = y
。
- 确认(ACK)客户端的SYN报文,确认号
状态变化:服务器进入
SYN_RECEIVED
状态。- 服务器收到客户端的SYN报文后,服务器知道了客户端希望建立连接,于是服务器向客户端发送一个SYN-ACK报文。这个报文有两个作用:
第三次握手(ACK):
- 客户端收到服务器的SYN-ACK报文后,知道服务器已同意建立连接。客户端再发送一个确认报文ACK给服务器,确认号
ack = y + 1
,表示已收到服务器的SYN报文,双方可以正式传输数据。 - 这个报文可以携带数据,也可以不携带数据。
状态变化:客户端进入
ESTABLISHED
状态,服务器收到这个ACK报文后也进入ESTABLISHED
状态。- 客户端收到服务器的SYN-ACK报文后,知道服务器已同意建立连接。客户端再发送一个确认报文ACK给服务器,确认号
三次握手的目的
- 确认双方发送和接收能力:通过三次握手,客户端和服务器双方都确认对方可以接收和发送数据。
- 防止重复连接的建立:三次握手可以防止旧的连接请求报文突然又传送到服务器,导致错误的连接建立。
- 同步初始序列号:确保双方都同步好序列号,为后续的可靠数据传输奠定基础。
为什么不是两次握手或四次握手?
两次握手不足:如果采用两次握手,服务器在收到客户端的第一次SYN报文后直接建立连接,但客户端可能因为网络延迟等原因并没有收到服务器的确认,这样就可能导致服务器建立了无效连接,浪费资源。
四次握手冗余:三次握手已经能够确保双方都同意建立连接并且同步了序列号,第四次握手会带来额外的网络开销,而没有提供额外的可靠性保障。
总结
三次握手是TCP协议中建立可靠连接的关键步骤,确保了数据传输前,客户端和服务器双方已经同步了彼此的状态,准备好进行数据交换。通过三次握手,TCP能有效防止旧连接的干扰,并保证数据传输的可靠性和顺序性。
四次挥手
HTTPS
HTTPS = HTTP + SSL/TLS , SSL 安全套接层, 发展到 v3 时改名为 TLS 传输层安全,主要的⽬的是提供数据的完整性和保密性
位于TCP/IP上的应用层协议 供数据的完整性和保密性
HTTPS如何保证安全性
HTTPS(Hyper Text Transfer Protocol Secure)是一种安全的HTTP协议,用于在网络上安全地传输数据。HTTPS的安全性主要通过以下几个方面保证:
- SSL/TLS协议:HTTPS使用SSL/TLS协议进行加密通信,SSL/TLS协议通过在通信的两端加密数据来保证数据传输的安全。SSL/TLS协议使用非对称加密算法和对称加密算法结合的方式来进行加密通信,非对称加密算法用于交换对称加密算法的密钥,对称加密算法用于加密通信过程中的数据。
- 数字证书:为了保证通信的安全性,服务器需要提供数字证书,证书中包含服务器的公钥和证书的签名信息。当客户端向服务器发起HTTPS请求时,服务器会将证书返回给客户端。客户端会验证证书的合法性,验证通过后,客户端会使用证书中的公钥加密数据,并发送给服务器。服务器使用自己的私钥解密数据,完成通信过程。
- 对称加密算法:HTTPS使用对称加密算法来加密通信过程中的数据,对称加密算法加密和解密速度都很快,但密钥的安全性容易受到攻击。为了解决这个问题,HTTPS使用了一种称为“会话密钥”的技术,即在客户端和服务器之间建立一个临时的密钥来加密通信过程中的数据,通信结束后,这个密钥会被销毁。
- 安全套接字层:HTTPS使用安全套接字层(SSL/TLS)来确保通信的安全性。安全套接字层提供了加密、认证和完整性保护等多重安全机制,可以有效地保护数据在传输过程中的安全。
总之,HTTPS通过SSL/TLS协议、数字证书、对称加密算法和安全套接字层等多重安全机制,来保证数据在传输过程中的安全性。
握手过程
tcp 的三次连接
客户端发送 client_hello
解释说明:客户端发送 client_hello,包含以下内容(请自行对照上图) 1. 包含 TLS 版本信息 2. 随机数(用于后续的密钥协商)random_C 3. 加密套件候选列表 4. 压缩算法候选列表 5. 扩展字段 6. 其他
服务端发送 server_hello
解释说明:服务端收到客户端的 client_hello 之后,发送 server_hello,并返回协商的信息结果 1. 选择使用的 TLS 协议版本 version 2. 选择的加密套件 cipher suite 3. 选择的压缩算法 compression method 4. 随机数 random_S 5. 其他
服务端发送证书
解释说明:服务端发送完 server_hello 后,紧接着开始发送自己的证书
服务端发送 Server Key Exchange
对于使用 DHE/ECDHE 非对称密钥协商算法的 SSL 握手,将发送该类型握手
服务端发送 Server Hello Done
:通知客户端 server_hello 信息发送结束
客户端发送.client_key_exchange+change_cipher_spec+encrypted_handshake_message
\1. client_key_exchange,合法性验证通过之后,向服务器发送自己的公钥参数,这里客户端实际上已经计算出了密钥 2. change_cipher_spec,客户端通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信 3. encrypted_handshake_message,主要是用来测试密钥的有效性和一致性
服务端发送 New Session Ticket
服务器给客户端一个会话,用处就是在一段时间之内(超时时间到来之前),双方都以协商的密钥进行通信。
服务端发送 change_cipher_spec
服务端解密客户端发送的参数,然后按照同样的算法计算出协商密钥,并通过客户端发送的 encrypted_handshake_message 验证有效性,验证通过,发送该报文,告知客户端,以后可以拿协商的密钥来通信了
- 第十步:服务端发送 encrypted_handshake_message
- 完成密钥协商,开始发送数据
安全
CSRF
(Cross-site request forgery
):跨站请求伪造。
攻击条件
- 登录受信任网站
A
,并在本地生成Cookie
。(如果用户没有登录网站A
,那么网站B
在诱导的时候,请求网站A
的api
接口时,会提示你登录) - 在不登出
A
的情况下,访问危险网站B
(其实是利用了网站A
的漏洞)。
防御
- token验证
- 隐藏令牌 放header上
- referer验证
- 添加验证码
XSS
XSS(Cross Site Scripting)
:跨域脚本攻击
类型
- 反射性 (基于后端) type
- DOM-Based(不基于后端) 输入框
- 存储型(恶意脚本存储到服务器) 评论功能
防御
- 编码 过滤 矫正
区别
区别一:
CSRF
:需要用户先登录网站A
,获取cookie
XSS
:不需要登录。
区别二:(原理的区别)
CSRF
:是利用网站A
本身的漏洞,去请求网站A
的api
。XSS
:是向网站A
注入JS
代码,然后执行JS
里的代码,篡改网站A
的内容。
V8 内存管理
新生代(new space)
- 新生代内存用于存放一些生命周期比较短的对象数据
老生代(old space)
- 老生代内存用于存放一些生命周期比较长的对象数据
- 当
new space
的对象进行两个周期的垃圾回收后,如果数据还存在new space
中,则将他们存放到old space
中 - Old Space 使用标记清除和标记整理的方式进行垃圾回收
新生代垃圾回收
新生代内存有两个区域,分别是对象区域(from) 和 空闲区域(to)
新生代内存使用
Scavenger 算法
来管理内存,垃圾回收的入口
- 广度优先遍历 From-Space 中的对象,从根对象出发,广度优先遍历所有能到达的对象,把存活的对象复制到 To-Space
- 遍历完成后,清空 From-Space
- From-Space 和 To-Space 角色互换
复制后的对象在 To-Space 中占用的内存空间是连续的,不会出现碎片问题
这种垃圾回收方式快速而又高效,但是会造成空间浪费(有 To-Space 空闲区域)
新生代的 GC 比较频繁
新生代的对象转移到老生
代称为
晋升 Promote
,判断晋升的情况有两种
- 经过一次 GC 还存活的对象
- 对象复制到 To-Space 时,To-Space 的空间达到一定的限制(超过 25%)
老生代的垃圾回收
V8 在老生代中的垃圾回收策略采用Mark-Sweep(标记清除)和 Mark-Compact(标记整理)相结合
Mark-Sweep(标记清除)
- 标记清除分为标记和清除两个阶段
- 在标记阶段需要遍历(深度优先遍历)堆中的所有对象,并标记那些活着的对象,然后进入清除阶段。在清除阶段总,只清除没有被标记的对象
- V8 采取的是黑色和白色来标记数据,垃圾收集之前,会把所有的数据设置为白色,用来标记所有的尚未标记的对象,然后会从 GC 根出发,以深度优先的方式把所有的能访问到的数据都标记为黑色,遍历结束后黑色的就是活的数据,白色的就是可以清理的垃圾数据
- 由于标记清除只清除死亡对象,而死亡对象在老生代中占用的比例很小,所以效率较高
- 标记清除有一个问题就是进行一次标记清楚后,内存空间往往是不连续的,会出现很多的内存碎片。如果后续需要分配一个需要内存空间较多的对象时,如果所有的内存碎片都不够用,就会出现内存溢出的问题
Mark-Compact(标记整理)
- 标记整理正是为了解决标记清除所带来的内存碎片的问题
- 标记整理在标记清除的基础进行修改,将其的清除阶段变为紧缩极端
- 在整理的过程中,将活着的对象向内存区的一段移动,移动完成后直接清理掉边界外的内存
- 紧缩过程涉及对象的移动,所以效率并不是太好,但是能保证不会生成内存碎片,一般 10 次标记清理会伴随一次标记整理
优化
JavaScript执行 垃圾标记、垃圾清理、垃圾整理 JavaScript执行
-------------- ---------------->
Parallel(并行执行)
新生代的垃圾回收采取并行策略提升垃圾回收速度,它会开启多个辅助线程来执行新生代的垃圾回收工作
增量标记 黑白灰
Write-barrier(写屏障)
Lazy Sweeping(惰性清理)
Lazy Sweeping(惰性清理)
浏览器渲染过程
HTML 转变为 DOM 树型结构 (先拆解为token 出栈入栈的形式)
CSS 转 stylesheet(来源可能有 link 标签、style 标签和 style 行内样式)
计算出 DOM 节点的样式(根据 CSS 的继承和层叠规则计算 DOM 节点的样式)
创建布局树
计算各个元素的布局
根据布局树生成分层树(渲染引擎需要为某些节点生成单独的图层,并组合成图层树--z-index 绝对定位和固定定位-)
根据分层树进行生成绘制步骤(图层会拆分成多个绘制指令,这些指令组合在一起成为绘制列表)
把绘制步骤交给渲染进程中的合成线程进行合成
合成线程将图层分成图块(tile)
合成线程会把分好的图块发给栅格化线程池,栅格化线程会把图片(tile)转化为位图
栅格化线程在工作的时候会把栅格化的工作交给 GPU 进程来完成,最终生成的位图就保存在了GPU
内存中
当所有的图块都光栅化之后合成线程会发送绘制图块的命令给浏览器主进程
浏览器主进程然后会从 GPU 内存中取出位图显示到页面上
资源加载
- CSS 加载不会影响 DOM 解析,不会阻塞 JS 加载,但是会阻塞 JS 执行
- JS 会依赖 CSS 加载,JS 会阻塞 DOM 解析