@Secretmm
2023-02-02T02:34:44.000000Z
字数 12551
阅读 612
p6必备
https://juejin.cn/post/6935232082482298911#heading-14
又名:从URL
输入到页面展现到底发生什么?
https://juejin.cn/post/7061588533214969892
https://zhuanlan.zhihu.com/p/29418126涉及到强缓存没命中,开始接下来的步骤
1.DNS
解析:将域名解析成IP
地址
2.TCP
连接:三次握手
3. 发送HTTP
请求
4. 服务器处理请求并返回HTTP
报文
5. 客户端解析渲染界面
6.TCP
连接断开:四次挥手
`http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument`
http://
;www.
;example.com
;:80
;/path/to/myfile.html
;?key1=value1&key2=value2
;#SomewhereInTheDocument
url
变化的方式hashchange
:通过hash
改变了url
,会触发hashchange
事件,只要在window
上监听hashchange
事件,就能捕获到通过hash
改变url
的行为。popstate
:History.back()
,History.forward()
、History.go()
、浏览器中点击后退和前进按钮会触发popstate
事件,在window
上监听popstate
事件能捕获此类变化。history
模式使用History.pushState()
和History.replaceState()
更改路径,不会触发事件,可以通过创建新的用户事件,重写pushState
和replaceState
,在其中触发事件来实现监听;HTTP
使用统一资源标识符(URI
)来传输数据和建立连接。
URI
:Uniform Resource Identifier
统一资源标识符
URL
:Uniform Resource Location
统一资源定位符
URL
就是用定位的方式实现的URI
, 所以URL
是URI
的子集
总是要问:为什么需要三次握手,两次不行吗?其实这是由
TCP
的自身特点可靠传输决定的。客户端和服务端要进行可靠传输,那么就需要确认双方的接收和发送能力。第一次握手可以确认客服端的发送能力,第二次握手,确认服务端的接收能力和发送能力,所以第三次握手才可以确认客户端的接收能力。不然容易出现丢包的现象。https://juejin.cn/post/6992433321435201573
四次挥手:
1. a向b发送连接释放请求
2. b收到请求,告诉a已释放;【此时,a只接收数据,b只发送数据】
3. b向a发送释放请求
4. a收到请求并应答。
HTTP
协议是超文本传输协议的缩写,英文是Hyper Text Transfer Protocol
是一个基于TCP/IP
通信协议来传递数据的协议,传输的数据类型为HTML
文件,、图片文件, 查询结果等。
1.
DNS
域名解析成服务器IP
;
2.发起tcp
请求,3
次握手建立连接;
3.http
请求;
4.http
响应;
http
协议支持客户端/服务端模式,也是一种请求/响应模式的协议。GET
、HEAD
、POST
。HTTP
允许传输任意类型的数据对象。传输的类型由Content-Type
加以标记。http
状态的技术,一个叫做Cookie
,一个叫做Session
(下文有解释)。请求报文构成
URL
、协议/版本Request Header
)响应报文构成
GET
:请求指定的页面信息,并返回实体主体。
HEAD
:类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
POST
:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST
请求可能会导致新的资源的建立和/或已有资源的修改。
PUT
:从客户端向服务器传送的数据取代指定的文档的内容。
DELETE
:请求服务器删除指定的页面。
CONNECT
:建立连接隧道,用于代理服务器
TRACE
:追踪请求-响应的传输路径
get
获取资源,参数放在url
中,规范上不应该对服务器上的内容产生作用,幂等,产生一个TCP
数据包,会被浏览器缓存,参数只接受ASCII
字符post
提交数据,数据放在body
中,无法直接看到内容,更安全,长度没限制。幂等:执行相同的操作,结果也是相同的
访问一个网页时,浏览器会向web服务器发出请求。此网页所在的服务器会返回一个包含HTTP状态码的信息头用以响应浏览器的请求。
5XX - 服务器错误,服务器在处理请求的过程中发生了错误。
常见状态码:
200 OK - 客户端请求成功
根据 Expires和Cache-Control是否过期判断是否使用本地缓存
版本:http1.0
来源:响应头
语法:Expires: Wed, 22 Nov 2019 08:41:00 GMT
类型:绝对时间戳
缺点:服务器的时间和浏览器的时间可能并不一致导致失效
版本:http1.1
来源:响应头和请求头
语法:Cache-Control:max-age=3600
类型:相对时间戳
缺点:时间最终还是会失效
协商缓存就是强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
协商缓存是在DNS解析之后的
Last-Modified
(响应头),If-Modified-Since
(请求头)
eTag
(响应头)、If-None-Match
(请求头) 【http/1.1】浏览器第一次请求,服务器返回
etag
字段,浏览器二次发生请求,会从缓存中取出etag
,作为If-None-Match
传给服务器,服务器根据If-None-Match
去判断浏览器的缓存资源是否与当前资源一致,如果一致, 返回304
;如果不一致则返回新的资源和一个新的etag
;
ETag
实体标签: 一般为资源实体的哈希值,即ETag
就是服务器生成的一个标记,用来标识返回值是否有变化。且Etag
的优先级高于Last-Modified
。
缓存处理,在HTTP1.0
中主要使用header
里的If-Modified-Since
,Expires
来做为缓存判断的标准,HTTP1.1
则引入了更多的缓存控制策略例如Etag
,If-Unmodified-Since
, If-Match
, If-None-Match
等更多可供选择的缓存头来控制缓存策略。
长连接,HTTP1.1
支持长连接(PersistentConnection
)和请求的流水线(Pipelining
)处理,在一个TCP
连接上可以传送多个HTTP
请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1
中默认开启Connection
: keep-alive
,弥补了1.0
每次请求都要创建连接的缺点。
带宽优化及网络连接的使用,HTTP1.1
则在请求头引入了range
头域,允许只请求资源的某个部分,返回码206
。
HTTP
的生命周期通过Request
来界定,也就是一个Request
一个Response
,那么在HTTP1.0
中,这次HTTP
请求就结束了。在HTTP1.1
中进行了改进,使得有一个keep-alive
,也就是说,在一个HTTP
连接中,可以发送多个Request
,接收多个Response
。但是请记住Request = Response
, 在HTTP
中永远是这样,也就是说一个request
只能有一个response
。而且这个response
也是被动的,不能主动发起。
keep-alive
开启长连接,只能实现在一个tcp上串行请求和响应,后一个请求必须在前一个请求响应后发起。但是请求流水线/管道化Pipelining
可以实现并发请求,后一个请求不必等待前一个请求的响应即可连续发送,但是服务器响应必须按序进行,前一个响应是会阻塞后一个响应的,而且管道中的请求必须是幂等请求,防止中途断线。但是浏览器并不默认开启Pipelining
,服务器也不一定支持。
错误通知管理,在HTTP1.1
中新增了24
个错误状态响应码,如409(Conflict
)请求与资源当前状态冲突;410(Gone)
资源被删除。
Host
头处理,HTTP1.1
的请求消息和响应消息都应支持Host
头域,且请求消息中如果没有Host
头域会报告一个错误(400 Bad Request)
。
多路复用,允许单一的HTTP/2
连接同时发起多重的请求-响应消息,且是并行执行,互不阻塞(1.1
长连接是顺序收发,可能阻塞);
头部压缩,1.1
中状态行和头部没有经过任何压缩,直接以纯文本传输,比较浪费;
服务器推送,HTTP/1.x中每一个资源都必须明确地请求;HTTP/2
引入了server push
,允许服务端在浏览器明确地请求之前,推送资源给浏览器。一个服务器经常知道一个页面需要很多附加资源,在它响应浏览器第一个请求的时候,可以开始推送这些资源。【资源在请求之后就堆在浏览器缓存里,之后浏览器需要数据的话,直接从缓存里面取】
为了数据传输的安全,
HTTPS
在HTTP
的基础上加入了SSL
协议,SSL/TLS
依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
第一步:客户端向服务端发送请求
客户端发送数据:
(1)客户端生成的随机数R1;
(2)客户端支持的加密算法;
第二步:服务器向客户端响应证书
服务端操作:
(1)服务端生成随机数R2;
(2)从客户端支持的加密算法中选择一种双方都支持的加密算法作为会话密钥算法;
服务端发送数据:
(3)[CA证书]、[会话密钥生成算法]、[随机数R2];【CA证书包含:公钥,企业信息,域名过期时间,摘要算法】
第三步:客户端协商共享秘钥
客户端操作:
(1)验证服务端证书
(2)生成一个随机数R3。
(3)根据会话秘钥算法使用R1、R2、R3生成共享秘钥。
客户端发送数据
(4)[【用服务端证书的公钥加密的】随机数R3]、[客户端证书(单项验证可省略)]
验证服务端证书流程
(1)验证证书的可靠性【先用CA的公钥解密被加密过后的证书,能解密则说明证书没有问题,然后通过证书里提供的摘要算法进行对数据进行摘要,然后通过自己生成的摘要与服务端发送的摘要比对】
(2)验证证书合法性,包括证书是否吊销、是否到期、域名是否匹配,通过后则进行后面的流程
(3)获得证书的公钥、会话密钥生成算法、随机数R2
服务端接收数据之后
服务端操作:
(1)验证客户端证书(单项验证可省略)
(2)服务器用私钥解密客户端发过来的随机数R3
(3)根据会话秘钥算法使用R1、R2、R3生成会话秘钥
第四步:客户端与服务端进行加密会话
客户端操作:
(1)发送数据:用会话秘钥加密数据发送给服务端;
(2)接收数据:用会话秘钥解密服务端发送过来的数据;
服务端操作:
(1)发送数据:用会话秘钥加密数据发送给客户端;
(2)接收数据:用会话秘钥解密客户端发送过来的数据;
1.多次握手(12次),加载慢,开销大
2.ssl
证书要钱,ssl
安全算法消耗服务器资源
1.https
需要证书;
2.http
明文,https
加密认证
3.http
基于tcp
,https基于SSL/TLS
【SSL/TLS
基于tcp
】
4.http
端口号80
,https
端口号443
双向通信,持久连接,数据帧有序,基于
http
来握手建立连接,使用upgrade
头字段升级协议,然后复用握手的tcp
连接。
Upgrade: websocket
Connection: Upgrade
都是基于TCP
协议的应用层协议;都可以传输数据;
websocket
双向通信、持久连接、数据帧 有序【先发先到】。
http
无状态无连接【非持久连接】
websocket
是基于http
来握手建立连接的,使用upgrade
头字段升级协议,然后复用握手的tcp
连接。
tcp三次握手,四次挥手
http1.1
默认是长连接,http
长连接是在一个request/response
结束后不立即关闭tcp
连接,后续继续使用这个tcp
连接收发数据,;但是一个长连接中的数据收发仍然是以一个个的request/response
对的形式,客户端要更新服务器状态还是需要进行轮询【客户端发起一次请求,服务器就响应一次返回】,开销较大。
long poll
与ajax
轮询的区别在于采用了阻塞模型【客户端发起连接后,如果没消息,就一直不返回Response
给客户端。直到有消息才返回,返回完之后,客户端才再次建立连接,周而复始】
websocket
则是真正的双向通信协议,只是连接的建立由客户端发起,连接建立后双方可以随时互发信息。
Server-Sent Events
:SSE
是利用http
协议变通实现服务器向浏览器推送信息的一种方法,就是服务器向客户端声明,接下来要发送的是流信息(streaming
)。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流,视频播放就是这样的例子。
SSE
与 WebSocket
作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。
WebSocket
更强大和灵活, 是全双工通道,可以双向通信;SSE
是单向通道,只能服务器向浏览器发送,因为流信息本质上就是下载。如果浏览器向服务器发送信息,就变成了另一次 HTTP
请求。SSE
使用 HTTP
协议,现有的服务器软件都支持。WebSocket
是一个独立协议。SSE
属于轻量级,使用简单;WebSocket
协议相对复杂。SSE
默认支持断线重连,WebSocket
需要自己实现。SSE
一般只用来传送文本,二进制数据需要编码后传送,WebSocket
默认支持传送二进制数据。SSE
支持自定义发送的消息类型。https://juejin.cn/post/6844903569087266823
浏览器会把
HTML
解析成DOM
,把CSS
解析成CSSOM
【CSS Object Model
】,DOM
和CSSOM
合并就产生了RenderTree
。有了RenderTree
,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。【css
不会阻塞dom
的解析,但会阻塞dom
的渲染】
回流Reflow【位置变化】:
会引起元素位置变化的就会reflow
回流,如窗口大小改变、字体大小改变、以及元素位置改变,都会引起周围的元素改变他们以前的位置;重绘 【位置无变化】:
不会引起位置变化的,只是在以前的位置进行改变背景颜色等,只会repaint
重绘;
回流必将引起重绘,重绘不一定引起回流,回流比重绘的代价更高
页面首次渲染
浏览器窗口大小发生改变
元素尺寸或位置发生改变
元素内容变化(文字数量或图片大小等等)
元素字体大小变化
添加或者删除可见的DOM元素
激活CSS伪类(例如::hover)
查询某些属性或调用某些方法
浏览器会维护1
个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会刷新队列,进行一个批处理。
但是!当你获取布局信息的操作的时候,会强制队列刷新,比如当你访问以下属性或者使用以下方法:
offsetTop
、offsetLeft
、offsetWidth
、offsetHeight
scrollTop
、 scrollLeft
、scrollWidth
、scrollHeight
clientTop
、clientLeft
、clientWidth
、clientHeight
getComputedStyle()
getBoundingClientRect()
: 元素相对于视口的位置
table
布局。DOM
树的最末端改变class
。CSS
表达式(例如:calc()
)。 常见的触发硬件加速的css属性:transform
、opacity
、filters
、Will-change
缺点:
为太多元素使用css3硬件加速,会导致内存占用较大,有性能问题
在GPU渲染字体会导致抗锯齿无效。这是因为GPU
和CPU
的算法不同。因此如 果你不在动画结束的时候关闭硬件加速,会产生字体模糊。
GPU加速的原因:
在合成的情况下,会直接跳过布局和绘制流程,直接进入非主线程处理的部分,即直接交给合成线程处理。交给它处理有两大好处:
1.能够充分发挥GPU的优势。合成线程生成位图的过程中会调用线程池,并在其中使用GPU进行加速生成,而GPU 是擅长处理位图数据的。
2.没有占用主线程的资源,即使主线程卡住了,效果依然能够流畅地展示。
css
类名修改或通过 cssText
修改
//css类名修改
const el = document.getElementById('test');
el.className += ' active';
//cssText修改
const el = document.getElementById('test');
el.style.cssText += 'border-left: 1px; border-right: 2px; padding: 5px;';
DOM
元素离线修改:
使元素脱离文档流
=>
对其进行多次修改将元素=>
带回到文档中。方法如下:
- 使用文档片段(
document fragment
)在当前DOM
之外构建一个子树,再把它拷贝回文档。- 为元素设置
display: none
,操作结束后再把它显示出来。- 将原始元素拷贝到一个脱离文档的节点中,修改节点后,再替换原始的元素
避免频繁读取会引发回流/重绘的属性,
1.需要多次使用的属性用一个变量缓存起来
2.对于resize
、scroll
等进行防抖/节流处理
1.css
半阻塞,不会影响浏览器对dom
的解析,但是会影响dom
的渲染。css
前置时,浏览器渲染的时候,会把html
解析为dom
树,把css
解析为cssom
树,等全解析完之后,再一起生成渲染树,通过渲染树把界面展示出来。css
后置时,相当于空白的cssom
与dom
结合,生成了一个裸奔的渲染树,此时界面没有样式,等加载到css
时,浏览器又会根据css
的内容对界面进行重绘。
2.js
全阻塞,js
前置时,浏览器会等js
执行完毕才会开始dom
的解析和渲染。如果js
包含dom
的修改,就会失效
小问题:为什么
dom
可以一边解析一边渲染,而css
却要等到解析完成之后才渲染呢?
猜测:css
样式存在覆盖情况,只有解析完了,才能拿到准确的样式
跨域问题的产生:浏览器同源策略;【域名、协议、端口都要相同,否则就是跨域】
跨域请求实际能够发送,服务端也能返回,但是默认会被浏览器拦截报错
跨域问题的解决:
1.【接口请求】:
JSONP
解决get
请求;- 空
iframe
加form
解决post
请求;window.name
- 跨域资源共享
CORS
;- 服务端代理 【
Nginx
配置,node
手动开发代理功能】
2.【dom查询】:
1.
postMessage
2.domain
【主域名相同,但子域名不同的iframe
跨域】【给两个页面指定一下document.domain
即document.domain = crossdomain.com
就可以访问各自的window
对象了】
解决canvas图片跨域问题:
https://www.zhangxinxu.com/wordpress/2018/02/crossorigin-canvas-getimagedata-cors/
利用了浏览器允许跨域引用
js
资源,使用<script>
标签,网页可以得到从其他来源动态产生的JSON
数据。JSONP
请求一定需要对方的服务器做支持才可以。
ajax属于同源策略,JSONP属于非同源策略,可跨域请求
简单兼容性好,只支持get
,可能会受到xss
攻击
1.声明一个回调函数,其函数名(如show
)当做参数值,函数形参为服务器返回的data
;
2.创建一个 <script src=>
标签 ,把那个跨域的接口地址,赋值给script
的src
,
3.还要在这个地址中向服务器传递该函数名(可以通过问号传参?callback=show
)。
4.服务器把准备的数据通过HTTP
协议返回给客户端,客户端再调用执行之前声明的回调函数(show)
,对返回的数据进行操作。
cors
是一种机制,它使用额外的HTTP
头部告诉浏览器可以让一个web
应用进行跨域资源请求,浏览器将CORS
请求分成两类:
1.简单请求(simple request
)
2.非简单请求(not-so-simple request
)
一个请求满足以下所有条件
1.使用的方法:head
、get
、post
之一
2.手动设置的头部只能是:Accept
,Accept-Language
,Content-Language
,Content-Type
3.Content-Type
的值只能为:application/x-www-form-urlencoded
【表】,multipart/form-data
【带文件的表单】,text/plain
【纯文本格式】
未写,太多
CORS
预检请求发生在实际请求之前,用于检查服务器是否支持CORS
,以判断实际请求发送是否安全。预检请求使用的方式是OPTIONS
。
当一个请求不是“简单请求”时,即应该先发送预检请求,比如:
1.这个请求的请求方式不是GET
、HEAD
、POST
2.这个请求设置了自定义的头部字段,比如X-xxx
3.这个请求的Content-Type
值不是application/x-www-form-urlencoded
、multipart/form-data
、text/plain
,等等
攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
a.com
,并保留了登录凭证(Cookie)
。b.com
。b.com
向 a.com
发送了一个请求:a.com/act=xx
。浏览器会默认携带a.com
的Cookie
。a.com
接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。a.com
以受害者的名义执行了act=xx
。 a.com
执行了自己定义的操作。Cookie
等信息,只是使用。 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
URL
、超链接、CORS
、Form
提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。Origin
和 Referer
验证)。Token
验证 或者 双重Cookie
验证 以及配合Samesite Cookie
。get
类型:通过http
请求
<img src="http://bank.example/withdraw?amount=10000&for=hacker" >
在受害者访问含有这个img的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker
发出一次HTTP
请求。bank.example
就会收到包含受害者登录信息的一次跨域请求。
post
类型: 通过一个自动提交的表单来完成攻击
用户访问一个黑客上传的一个带有
form
表单的页面后,表单会自动提交,相当于模拟用户完成了一次POST
操作。
需要用户点击链接才会触发
攻击者往Web
页面里插入恶意js
代码,当用户浏览该页之时,嵌入其中Web
里面的js
代码会被执行,从而达到恶意攻击用户的目的。”
攻击者对客户端网页注入的恶意脚本一般包括 js
,有时也会包含 HTML
和 Flash
。有很多种方式进行 XSS 攻击,但它们的共同点为:将一些隐私数据像 cookie
、session
发送给攻击者,将受害者重定向到一个由攻击者控制的网站,在受害者的机器上进行一些恶意操作。
流量劫持、盗用cookie
,配合csrf
完成恶意请求
<script>
、<img>
、<a>
等标签进行过滤。<>
在输入的时候要对其进行转换编码,这样做浏览器是不会对该标签进行解释执行的,同时也不影响显示效果。xss
攻击要能达成往往需要较长的字符串,因此对于一些可以预期的输入可以通过限制长度强制截断来进行防御。限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
1.
Cookie
:在客户端记录信息确定用户身份;
2.Session
:是服务器端使用的一种记录客户端状态的机制;
3.【HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话】,为了跟踪该会话,引入的一种机制;
服务端执行session
机制时候会生成session
的id
值,这个id
值会发送给客户端,客户端每次请求都会把这个id
值放到http
请求的头部发送给服务端,而这个id
值在客户端会保存下来,保存的容器就是cookie
cookie
数据存放在客户的浏览器(客户端)上,session
数据放在服务器上,但是服务端的session
的实现对客户端的cookie
有依赖关系的;cookie
不是很安全,别人可以分析存放在本地的COOKIE
并进行COOKIE
欺骗,考虑到安全应当使用session
;session
会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用cookie
;cookie
在客户端的限制是4K
,就是说一个站点在客户端存放的cookie
不能超过4K
;根据请求的URL来匹配cookies的domain、path属性,如果都符合才会发送;
带有secure选项的cookie只会在https请求中携带;
跨域请求时需要根据credential相关字段来决定是否携带
过期了会被删除
每条cookie有个属性httpOnly,如果为true,则不能被浏览器js读取到