计算机网络面经(前端)
目录
5.1 URL加载的过程
5.2 Http
5.2.1 发展
5.2.2 请求|Option
5.2.3 请求方法
5.2.4 缓存
5.2.5 tcp udp
5.3 TCP三次握手与四次挥手
5.4 Cookie
5.5 OSI七层模型
5.6 Http状态码
5.7 CDN
5.9 JWT
5.11 网站攻击
5.12 WebSocket
5.13 跨域和同源
5.14 网站性能
5.15 加密
5.16 DNS
5.18 白屏问题
5.20 Storage
5.21 标签间通信
5.22 网站指标
5.1 URL加载的过程
1)首先,在浏览器地址栏中输入url
如果为非url结构的字符串,交给浏览器默认引擎去搜索改字符串;若为url结构的字符串,浏览器主进程会交给 网络进程,开始干活。
2)浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。
网络进程会先看看是否存在本地缓存,如果有就直接返回资源给浏览器进程,无则下一步 DNS-> IP -> TCP。
3)在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。
网络进程拿到url后,先会进行DNS域名解析得到IP地址。如果请求协议是HTTPS,那么还需要建立TLS连接。
4)浏览器向服务器利用IP地址和服务器建立TCP连接。,与浏览器建立tcp三次握手。
5)握手成功后,浏览器向服务器发送http请求,请求数据包。
连接建立之后,向服务器发送请求。服务器收到请求信息后,会根据请求信息生成响应行、响应头、响应体,并发给网络进程。网络进程接受了响应信息之后,就开始解析响应头的内容。
6)服务器处理收到的请求,将数据返回至浏览器
默认情况,每个页面一个渲染进程。但若处于同一站点(同根域名+协议),那么渲染进程就会复用。
7)浏览器收到HTTP响应
8)读取页面内容,浏览器渲染,解析html源码
渲染进程准备好后,浏览器进程发出“提交文档的消息”,渲染进程接受了消息之后,会跟网络进程简历传输数据的管道。等数据传输完成了,渲染进程会告诉浏览器进程,确认文档提交,这时候浏览器会更新页面,安全状态,url,前进后退的历史。
9)渲染进程接受到数据,生成Dom树、解析css样式、js交互,渲染显示页面。
同步构建DOM树和CSSOM树,当CSSOM生成结束执行js。浏览器会先从DOM树的根节点开始遍历每个可见节点,并把这些节点添加到渲染树中。不可见的节点不会添加到渲染树,比如css设置了display为none 属性的节点。根据生成的渲染树,进行布局(也可以叫做回流),得到各个节点在页面中的确切位置和大小。生成分层树,页面都是一层一层叠加在一起形成的。比如一些复杂的css动画,z-index等,渲染引擎会为他们生成专用的图层,并生成对应的图层树。
5.2 Http
5.2.1 发展
0.9 |
html文件传输 |
确定了客户端请求,服务器响应的通信流程 |
1.0 |
不同类型文件传输 |
设立头部字段 |
1.1 |
创建/断开TCP连接开销大 |
建立长连接进行复用 |
2 |
并发数有限 |
二进制分帧 |
3 |
TCP丢包阻塞 |
采用UDP协议 |
对头阻塞:
头部阻塞是 TCP中的一个问题,当一个 TCP 流中的一个数据包丢失时,整个流都会被阻塞,直到丢失的数据包被重新发送和接收。HTTP/1.1 时代建立一个 TCP 连接,三个请求组成一个队列发出去,服务器接收到这个队列之后会依次响应,一旦前面的请求阻塞,后面的请求就会无法响应。
HTTP/2 并没有解决 TCP 的队首阻塞问题,它仅仅是通过多路复用解决了以前 HTTP1.1 管线化请求时的队首阻塞。HTTP/2 是通过分帧并且给每个帧打上流的 ID 去避免依次响应的问题,对方接收到帧之后根据 ID 拼接出流,这样就可以做到乱序响应从而避免请求时的队首阻塞问题。但是 TCP 层面的队首阻塞是 HTTP/2 无法解决的(HTTP 只是应用层协议,TCP 是传输层协议),TCP 的阻塞问题是因为传输阶段可能会丢包,一旦丢包就会等待重新发包,阻塞后续传输,这个问题虽然有**滑动窗口(Sliding Window)**这个方案,但是只能增强抗干扰,并没有彻底解决。
HTTP/3 通过使用基于 UDP 的 QUIC 协议来解决这个问题。在 QUIC 中,流是独立的,如果一个流中的数据包丢失,它不会影响其他的流。这就意味着,即使在一个流中发生了数据包丢失,其他的流仍然可以继续传输数据。这样就消除了头部阻塞问题。
长连接与管道:
在 HTTP/0.9 版本中,HTTP 请求是以短连接进行的,因此在发送完 HTTP 的响应之后,服务器就会断开 TCP 连接。可是这样是一件很耗资源、很耗时间的事情,所以在 1.0 版本中,新增了 keep-alive 字段,让长连接被 HTTP 支持了(此时默认还是不会开启长连接)。所谓长连接,就是完成这个 HTTP 请求之后,不要断开 HTTP 请求使用的 TCP 连接。好处是连接可以被重新使用,之后发送 HTTP 请求的时候就不需要重新建立 TCP 连接了,以及如果维持连接,那么 SSL 的开销也可以避免。
好处如此之多,所以 HTTP/1.1 就把 Connection: keep-alive 头写进了标准,并且默认开启持久连接(两小时,心跳检测 5次)。
必须在请求中声明:Connection: close 才会让每次 HTTP 请求都重新建立 TCP 连接。
- 如果是「短连接」,那么一次 TCP 连接就只能对应一次 HTTP 请求;
- 如果是「长连接」,那么一次 TCP 连接就可以发送多个 HTTP 请求了。
管道是 HTTP/1.1 规范中的字段,能将多个 HTTP 请求整批提交,在发送过程中不需先等待服务器的回应。因为该技术存在很多问题:
- 一些代理服务器不能正确的处理 HTTP Pipelining;
- 正确的流水线实现是复杂的;
- Head-of-line Blocking 连接头阻塞:在建立起一个 TCP 连接之后,假设客户端在这个连接连续向服务器发送了几个请求。按照标准,服务器应该按照收到请求的顺序返回结果,假设服务器在处理首个请求时花费了大量时间,那么后面所有的请求都需要等着首个请求结束才能响应。
HTTP2 提供了 Multiplexing 多路传输特性,让我们可以在一个 TCP 连接中同时完成多个 HTTP 请求。(可以将数据拆成包,给每个包打上标签。到了服务器在进行拼接即可,本质上还是管道)
连接上限:
浏览器允许我们对同一 host 开启多个 TCP 连接,每个浏览器的数量是不一样的。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。
Http和Https的区别:
HTTP协议也就是超文本传输协议,是一种使用明文数据传输的网络协议。一直以来HTTP协议都是最主流的网页协议,HTTP协议被用于在Web浏览器和网站服务器之间传递信息,以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息。
为了解决HTTP协议的这一缺陷,需要使用另一种协议:安全套接字层超文本传输协议HTTPS,为了数据传输的安全,HTTPS在HTTP的基础上加入了SSL/TLS协议,SSL/TLS依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。HTTPS协议可以理解为HTTP协议的升级,就是在HTTP的基础上增加了数据加密。在数据进行传输之前,对数据进行加密,然后再发送到服务器。这样,就算数据被第三者所截获,但是由于数据是加密的,所以你的个人信息仍然是安全的。
具体过程为:客户端发起 SSL orTLS握手 -> 服务端将证书发送给客户端 -> 客户端检查是否为 CA (双方约定可信任证书签发机构)-> 服务端检查客户端 CA 证书 ;
Http2和Http3区别:
HTTP2协议虽然大幅提升了HTTP/1.1的性能,然而,基于TCP实现的HTTP2遗留下3个问题:
- 有序字节流引出的队头阻塞(Head-of-line blocking),使得HTTP2的多路复用能力大打折扣;
- TCP与TLS叠加了握手时延,建链时长还有1倍的下降空间;
- 基于TCP四元组确定一个连接,这种诞生于有线网络的设计,并不适合移动状态下的无线网络,这意味着IP地址的频繁变动会导致TCP连接、TLS会话反复握手,成本高昂。
HTTP3协议解决了这些问题:
- HTTP3基于UDP协议重新定义了连接,在QUIC层实现了无序、并发字节流的传输,解决了队头阻塞问题(包括基于QPACK解决了动态表的队头阻塞);
- HTTP3重新定义了TLS协议加密QUIC头部的方式,既提高了网络攻击成本,又降低了建立连接的速度(仅需1个RTT就可以同时完成建链与密钥协商);
- HTTP3 将Packet、QUIC Frame、HTTP3 Frame分离,实现了连接迁移功能,降低了5G环境下高速移动设备的连接维护成本。
Https发展
背景:早期的数据在网络传输中使用的http协议,这种协议采取的是明文传输的方式。从一个结点到另一个结点传输的过程中会存在一些不法分子从中窃取信息。早起的运营商也会利用职务之便进行数据劫持,在web里插入代码显示广告。在20世纪90年代中期,当人们意识到互联网应用越来越广泛,所传递的信息价值越来越高时,便不得不考虑对网络进行安全性处理。最早吃螃蟹的是当时最大的网景公司,在1994年对http1.1进行了升级。https发展:最早采用的方法便是加密,加密和解密采用相同的密钥,如凯撒加密,恩格码机等,这种加密方式就是对称加密。但是要想让传输双方进行解密,那在传递的过程中需要把密钥一起传递,这种加密方式就失去了意义。于是产生了非对称加密,利用公钥和私钥。服务器先将自己的公钥发送给浏览器。浏览器生成一个随机的数据,用服务器的公钥加密然后发送给服务器,服务器利用自己的私钥进行解密,于是就产生了一份相同的数据。这份数据用作双方传递的密钥进行加密传输。这是一套独立于http协议的流程,被称为安全套接字层(secure socket layer-ssl)后来ssl进行了三次升级,最后一次升级后被冠以TSL进行正式发布。所以TSL1.0也被叫做ssl3.1。升级过程是对加密方式的升级,比如舍弃了md5采用sha-256。但是如果有人将服务器传递给浏览器的公钥进行窃取然后更换成自己的公钥发送给浏览器,依旧会存在安全性问题。因此引入了CA的概念,ca会进行第三方加密以验证服务器身份,这就是TsL证书。这些ca机构会被保存在客户端本地以供浏览器需要。前几年有些网站自己给自己颁发证书,会存在不被认可的问题,12306。但是ca机构的权利过于集中,一旦ca机构出现问题,导致的问题不可估量。比如google和赛门铁克,还有棱镜门利用虚假的证书来窃听用户隐私。因此,引入了证书透明化,ct。但是这种套娃的操作并不能很好的解决该类问题。因此我认为去中心化才是核心。区块链给人们最大的启示就是任何中心化的技术都是不被信任的,无论他如何权威。ct中的日志服务采用了区块链中的默克尔树进行防篡改实现。这是一种类似于归并去计算每一层hash的方法,将根hash保存在每一个客户端上。
HTTPS 握手过程中,客户端如何验证证书的合法性
校验证书的颁发机构是否受客户端信任。 2. 通过 CRL 或 OCSP 的方式校验证书是否被吊销。 3. 对比系统时间,校验证书是否在有效期内。 4. 通过校验对方是否存在证书的私钥,判断证书的网站域名是否与证书颁发的域名一致。 证书包含:公钥、公钥拥有者名称、CA的数字签名、有效期、授权中心名称、证书序列号等信息。
怎么通过数字证书验证服务器身份
- 客户端发起连接请求:客户端向服务器发起连接请求,例如使用HTTPS协议访问一个网站。
ssl握手过程中,浏览器会通过证书链层层验证,直至操作系统上的根证书,根证书存储在客户端本地【C:\Windows\System32
】,其余的存储在服务器上。
- 服务器发送数字证书:服务器将其数字证书发送给客户端。数字证书是由可信任的证书颁发机构(CA)颁发的,其中包含了服务器的公钥以及其他相关信息。
- 客户端验证数字证书的合法性:客户端会使用内置的根证书颁发机构列表(或者操作系统提供的信任存储)来验证服务器发送的数字证书的合法性。客户端会检查证书的签名是否有效、证书是否过期、证书是否被吊销等。
以下三步:向服务器发送一个随机数,从证书中获取服务器端的公钥,对随机数加密;编码改变通知,表示随后信息都将使用双方协定的加密方法和密钥发送;客户端握手结束通知。
- 公钥提取:如果数字证书通过验证,客户端会从证书中提取出服务器的公钥。
- 生成随机密钥:客户端会生成一个随机的对称密钥,用于加密通信过程中的数据。
- 使用服务器的公钥加密对称密钥:客户端使用服务器的公钥对随机生成的对称密钥进行加密,然后将加密后的对称密钥发送给服务器。
服务器端对数据解密得到随机数,发送消息:编码改变通知,表示随后信息都将使用双方协定的加密方法和密钥发送。
- 服务器使用私钥解密对称密钥:服务器使用自己的私钥解密收到的加密对称密钥。
- 建立加密通道:客户端和服务器双方现在都拥有相同的对称密钥,它们可以使用该密钥来进行加密和解密通信内容,建立安全的加密通道。
SSL和TLS区别:
SSL:(Secure Socket Layer,安全套接字层),位于可靠的面向连接的网络层协议和应用层协议之间的一种协议层。SSL通过互相认证、使用数字签名确保完整性、使用加密确保私密性,以实现客户端和服务器之间的安全通讯。该协议由两层组成:SSL记录协议和SSL握手协议。
TLS:(Transport Layer Security,传输层安全协议),用于两个应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS记录协议和TLS握手协议。
SSL协议提供的服务主要有:
1)认证用户和服务器,确保数据发送到正确的客户机和服务器;
2)加密数据以防止数据中途被窃取;
3)维护数据的完整性,确保数据在传输过程中不被改变。
TLS 记录协议提供的连接安全性具有两个基本特性:
私有――对称加密用以数据加密(DES 、RC4 等)。对称加密所产生的密钥对每个连接都是唯一的,且此密钥基于另一个协议(如握手协议)协商。记录协议也可以不加密使用。
可靠――信息传输包括使用密钥的MAC进行信息完整性检查。安全哈希功能( SHA、MD5 等)用于 MAC 计算。记录协议在没有 MAC 的情况下也能操作,但一般只能用于这种模式,即有另一个协议正在使用记录协议传输协商安全参数。
参考:
- HTTP发展史,HTTP1.1与HTTP2.0的区别 https://juejin.cn/post/7079936383925616653
- https://www.cnblogs.com/xhyccc/p/14392670.html
- https://segmentfault.com/q/1010000005167289
5.2.2 请求|Option
1 客户端请求消息**客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。
GET /hello.txt HTTP/1.1 //HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。 //HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。 User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 Host: www.example.com Accept-Language: en, mi
request header
1.Accept
作用: 浏览器端可以接受的媒体类型, 例如: Accept: text/html 代表浏览器可以接受服务器回发的类型为 text/html 也就是我们常说的html文档,如果服务器无法返回text/html类型的数据,服务器应该返回一个406错误(non acceptable)
2.Accept-Encoding:
作用: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate),(注意:这不是只字符编码); 例如: Accept-Encoding: zh-CN,zh;q=0.8
4.Connection
Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
8.Cache-Control
Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。
2 服务器响应消息HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
HTTP/1.1 200 OK // 当前的GMT时间。 Date: Mon, 27 Jul 2009 12:28:53 GMT //服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。 Server: Apache //文档的最后改动时间。 Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT // 指纹,比较两次请求是否变化,允许缓存更有效并节省带宽 ETag: "34aa387-d-1568eb00" Accept-Ranges: bytes //表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。 Content-Length: 51 //过期时间 Expires: Set-cookie: Vary: Accept-Encoding //用于定义网络文件的类型和网页的编码: //text/html : HTML格式 /plain :纯文本格式 /xml : XML格式 /png:png图片格式 //application/xhtml+xml :XHTML格式 /json: JSON数据格式 /pdf:pdf格式 Content-Type: text/plain //Content-Type 标头告诉客户端实际返回的内容的内容类型。一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些 PHP 网页点击的结果却是下载一个文件或一张图片的原因。 /* text/html : HTML格式 text/plain :纯文本格式 text/xml : XML格式 image/jpeg :jpg图片格式 png gif图片格式 application/xhtml+xml :XHTML格式 application/xml: XML数据格式 application/atom+xml :Atom XML聚合格式 application/json: JSON数据格式 application/pdf:pdf格式 application/msword : Word文档格式 application/octet-stream : 二进制流数据(如常见的文件下载) */
response header
1.刷新和延时跳转
一秒刷新页面一次 response.setHeader(“refresh”,“1”);
二秒跳到其他页面 response.setHeader(“refresh”,“2;URL=otherPagename”);
2.没有缓存
response.setHeader(“Pragma”, “No-cache”);
response.setHeader(“Cache-Control”, “no-cache”);
3.设置过期的时间期限
response.setDateHeader(“Expires”, System.currentTimeMillis()+自己设置的时间期限);
4.设置请求文件最后修改时间
response.setDateHeader(“Last-Modified”, System.currentTimeMillis());
5.访问别的页面(重定向)
response.setStatus(302);
response.setHeader(“location”,“url”);
3 OPTIONS
在CORS机制一个域名A要访问域名B的服务,在一些特殊的复杂请求下(简单请求并不会进行预请求),浏览器必须先使用OPTIONS请求进行一个预检请求(preflight request)来获取B服务是否允许跨域请求,服务进行确认之后,才会发起真正的HTTP请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。
简单请求:
- http方法是以下之一:GET | HEAD | POST
- HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language | Content-Language
- Content-Type (需要注意额外的限制)
- Content-Type 的值为 text/plain
请求情况:
- withCredentials为true不会产生预请求
- 请求头Content-Type为application/json会产生预请求
- 设置了用户自定义请求头会产生预检请求
- delete方法产生预检请求
预检请求不一定每一次都会产生
这个因为浏览器会对预检请求进行缓存,同时通过服务器端设置 Access-Control-Max-Age 字段来设置缓存时间。
那么当第一次请求该 URL 时会发出 OPTIONS 请求,浏览器会根据返回的 Access-Control-Max-Age 字段缓存该请求的 OPTIONS 预检请求的响应结果。
5.2.3 请求方法
以资源为基础 :资源可以是一个图片、音乐、一个XML格式、HTML格式或者JSON格式等网络上的一个实体,除了一些二进制的资源外普通的文本资源更多以JSON为载体、面向用户的一组数据(通常从数据库中查询而得到)。统一接口: 对资源的操作包括获取、创建、修改和删除,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。换言而知,使用RESTful风格的接口但从接口上你可能只能定位其资源,但是无法知晓它具体进行了什么操作,需要具体了解其发生了什么操作动作要从其HTTP请求方法类型上进行判断。具体的HTTP方法和方法含义如下:
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)。
- PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)。
- DELETE(DELETE):从服务器删除资源。
URI指向资源:URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。URI包括URL和URN,在这里更多时候可能代指URL(统一资源定位符)。RESTful是面向资源的,每种资源可能由一个或多个URI对应,但一个URI只指向一种资源。
无状态:服务器不能保存客户端的信息, 每一次从客户端发送的请求中,要包含所有必须的状态信息,会话信息由客户端保存, 服务器端根据这些状态信息来处理请求。 当客户端可以切换到一个新状态的时候发送请求信息, 当一个或者多个请求被发送之后, 客户端就处于一个状态变迁过程中。 每一个应用的状态描述可以被客户端用来初始化下一次的状态变迁。
其他方法:
CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。OPTIONS HTTP1.1 允许客户端查看服务器的性能。TRACE HTTP1.1 回显服务器收到的请求,主要用于测试或诊断。PATCH HTTP1.1 是对 PUT 方法的补充,用来对已知资源进行局部更新 。
post一定安全吗?
只要拦截到了传递的数据体,用户名和密码就能轻松获取。MD5是一种常用的加密方法,它是一种散列函数,利用MD5对用户信息进行加密,会增加用户信息安全性。但是依旧可以利用一些方法破解(cmd5网),因此可以在此之上加盐,在密码后面接一组乱码同时加密
幂等性
HTTP 方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。说白了就是,同一个请求,发送一次和发送 N 次效果是一样的!幂等性是分布式系统设计中十分重要的概念,而 HTTP 的分布式本质也决定了它在 HTTP 中具有重要地位。
1.GET 方法用于获取资源,不应有副作用,所以是幂等的。
- DELETE 方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和 N 次对系统产生的副作用是相同的,即删掉 id 为 4231 的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。
3.PUT 方法用于创建或更新操作,有副作用,与 DELETE 相同,对同一资源无论调用一次还是多次,其副作用是相同的,因此也满足幂等性。比如:PUT http://www.forum/articles/4231 的语义是创建或更新 ID 为 4231 的帖子。对同一 URI 进行多次 PUT 的副作用和一次 PUT 是相同的;因此,PUT 方法具有幂等性。
4.POST 方法与 PUT 方法的区别主要在于幂等性,POST 不具备幂等性,因为 POST 请求每次都会创建一个文件,而 PUT 方法会在服务器验证是否有 ENTITY,若有则更新该 ENTITY 而不是重新创建。比如:POST http://www.forum.com/articles 的语义是在 http://www.forum.com/articles 下创建一篇帖子,HTTP 响应中应包含帖子的创建状态以及帖子的 URI。两次相同的 POST 请求会在服务器端创建两份资源,它们具有不同的 URI;所以,POST 方法不具备幂等性。
如何防范 POST 重复提交
HTTP POST 操作既不是安全的,也不是幂等的(至少在 HTTP 规范里没有保证)。当我们因为反复刷新浏览器导致多次提交表单,多次发出同样的 POST 请求,导致远端服务器重复创建出了资源。
所以,对于电商应用来说,第一、对应的后端 WebService 一定要做到幂等性,第二、服务器端收到 POST 请求,在操作成功后必须 302 跳转到另外一个页面,这样即使用户刷新页面,也不会重复提交表单。
在前端开发中,GET 和 POST 是两种常用的 HTTP 请求方法,它们的主要区别在于数据传输的方式和用途:
- 数据传输的方式:GET 方法:GET 请求通常用于请求数据,并将请求参数附加到 URL 中。请求的数据会被视为查询字符串,并在 URL 中可见。这意味着 GET 请求的 URL 中包含了所有需要的信息。这也意味着你不能通过 GET 请求发送大量的数据,因为 URL 的长度是有限制的。get比post快两倍。POST 方法:POST 请求通常用于发送数据,并将请求的数据放在请求体中。请求的数据不会在 URL 中可见,可以发送大量的数据。
- 用途:GET 方法:通常用于获取(或查询)数据,比如获取用户列表、获取某篇文章等。根据 HTTP 规范,GET 请求应该是只读的,并且没有副作用。POST 方法:通常用于发送(或提交)数据,比如创建一个新用户、发布一篇新文章等。POST 请求可能会改变服务器上的数据。
- 缓存: GET 方法:GET 请求能被浏览器缓存。 POST 方法:POST 请求不会被缓存。
- 历史记录: GET 方法:GET 请求会被浏览器保存在历史记录中。 POST 方法:POST 请求不会被保存在历史记录中。
- 书签: GET 方法:可以被添加为书签。POST 方法:不能被添加为书签。
- 传参:get方法:从服务器获取数据,效率比POST高.GET请求能够被缓存在 HTTP 协议定义中,没有对GET请求的数据大小限制,不过因为浏览器不同一般限制在 2~8K 之间.GET发送请求时,URL中除了资源路径以外,所有的参数(查询字符串)也包装在URL中参数格式在资源路径末尾添加 ? 表示追加参数.每一个变量及值按照 变量名=变量值 方式设定,不能包含空格或者中文.多个参数使用 & 连接.注意 : URL 字符串中如果包含空格或者中文,需要添加百分号转义post方法:
向服务器发送数据,也可以获得服务器处理之后的结果,效率不如GET.
POST请求不能被缓存.
POST提交数据比较大,大小靠服务器的设定值限制,PHP通常限定 2M.
POST发送请求时,URL中只有资源路径,但不包含参数,服务器日志不会记录参数,相对更安全.
参数被包装成二进制的数据体,格式与 GET 基本一致,只是不包含 ?.
注意 : 所有涉及到用户隐私的数据(密码,银行卡号)一定记住使用 POST 方式传递.
7. GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。
- 对于 GET 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);
- 而对于 POST,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)。
axios.get('https://api.example.com/users', { params: { userId: 123 } }) export let getStats = (a) => { return axios({ url: "/login", method: "get", // 传参 params: { user: '123123' } }); axios.post('https://api.example.com/users', { name: 'John Doe', email: 'john@example.com' }) .then(function (response) { // handle success console.log(response.data); }) .catch(function (error) { // handle error console.log(error); }) .finally(function () { // always executed });
5.2.4 缓存
浏览器缓存指在本地使用的计算机中开辟一个内存区,同时也开辟一个硬盘区作为数据传输的缓冲区,然后用这个缓冲区来暂时保存用户以前访问过的信息。
HTTP 缓存主要是通过请求和响应报文头中的对应 Header 信息,来控制缓存的策略。
HTTP缓存可以缩短网页请求资源的距离,减少延迟,节省网络流量,并且由于缓存文件可以重复利用,降低网络负荷,提高客户端响应。缺点是服务端更改内容不能及时同步到客户端。
根据是否需要重新向服务器发起请求,可分为强缓存和协商缓存
1 强缓存
定义:当命中强缓存的时候,客户端不会再请求服务器,直接从缓存中读取内容,并返回HTTP状态码200。
强制缓存,在响应头由 Expires、Cache-Control 和 Pragma控制
Expires:值为服务器返回的过期时间,浏览器再次加载资源时,如果在这个过期时间内,则命中强缓存。(HTTP1.0的属性,缺点是客户端和服务器时间不一致会导致命中误差)(绝对时间) Cache-Control:HTTP1.1属性,优先级更高,以下为常用属性 no-store: 禁用缓存 no-cache:不使用强缓存,每次需向服务器验证缓存是否失效 private/public:private指的单个用户,public可以被任何中间人、CDN等缓存 max-age=:max-age是距离请求发起的时间的秒数(相对时间) must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证 Pragma no-cache:效果和cache-control等no-cache一致。 优先级Pragma > Cache-Control > Expires
知道 from disk cache和from memory cache吗,他们都是什么时候会触发?当强缓存的时候会触发这个, 浏览器缓存是存储在磁盘和内存中,当需要使用到缓存的时候会先从内存查找,没有查找到就从磁盘中查找。如果还是找不到就向服务器请求,得到数据再存到内存和磁盘。
如何刷新强缓存从上面的强缓存知识中,知道如果缓存时间没有过,我们一直都是在缓存中拿数据的,那么当我们把服务器的数据更新,如何让强缓存也能拿到最新的数据。因为强缓存都是判断url来判断是从缓存中拿数据还是从服务器拿数据,所以只要我们更改了这个url就可以。例如我们在url的后面添加一个version版本或者使用hash来让原来的url改变就可以刷新浏览器的缓存了。
2 协商缓存
定义:向服务器发送请求,服务器会根据这个请求的请求头的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的响应头通知浏览器从缓存中读取资源。
协商缓存,响应头中有两个字段标记规则
Last-Modified / If-Modified-Since Last-Modified是浏览器第一个请求资源,服务器响应头字段,是资源文件最后一次更改时间(精确到秒)。 下一次发送请求时,请求头里的If-Modified-Since就是之前的Last-Modified 把浏览器端缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行对比。如果时间一致,那么返回304且不返回资源、不返回last-modify,客户端就直接使用本地缓存文件。如果时间不一致,就会返回200和新的文件内容。客户端接到之后,会丢弃旧文件,把新文件缓存起来,并显示在浏览器中. Etag / If-None-Match:Etag 的校验优先级高于 Last-Modified Etag是加载资源时,服务器返回的响应头字段,是对资源的唯一标记,值是hash码, 根据实体内容生成的一段hash字符串(类似于MD5或者SHA1之后的结果),可以标识资源的状态。 当资源发送改变时,ETag也随之发生变化。 浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到请求头里的If-None-Match里 服务器接受到If-None-Match的值后,会拿来跟该资源文件的Etag值做比较,如果相同,则表示资源文件没有发生改变,命中协商缓存。
缓存验证流程
1 ) 浏览器创建了一个请求, 首先请求到达的地方是在本地缓存, 当然是建立在有Cache-Control头的情况下如果在本地缓存里查找,如果找到,则直接返回给浏览器渲染页面这种情况下, 不会经过任何网络的传输,也就是from memory cache的效果2 ) 如果没有找到,就会去网络请求,在网络请求中,如果经过代理服务器(代理缓存)那么首先会在代理服务器上查找相关缓存信息, 如果找到就会返回给客户端经过本地缓存,再返回给浏览器渲染页面3 ) 如果在代理服务器上没有找到该缓存信息,那么就直接去源服务器上查找资源获取了新的内容之后,再逐级向下进行返回和二次缓存最终返回给浏览器进行页面的渲染
为什么还要使用ETag呢? 主要是为了解决Last-Modified 无法解决的一些问题:
- 某些服务器不能精确得到文件的最后修改时间, 这样就无法通过最后修改时间来判断文件是否更新了。
- 某些文件的修改非常频繁,在秒以下的时间内进行修改. Last-Modified只能精确到秒。
- 一些文件的最后修改时间改变了,但是内容并未改变。 我们不希望客户端认为这个文件修改了。
https://blog.csdn.net/Tyro_java/article/details/122952039
协商缓存失效怎么办?
- 服务端配置问题:确保服务端正确地设置了Etag或者Last-Modified响应头,且在收到含有If-None-Match或If-Modified-Since请求头的请求时,能正确地返回304状态码。
- 网络问题:一些网络设备或软件可能会修改或移除这些头部信息,导致协商缓存失效。在这种情况下,你可能需要联系你的网络服务提供商或检查你的网络设备和软件配置。
- 浏览器问题:不同的浏览器可能在处理协商缓存时有不同的行为。确保你的代码和配置在你的目标浏览器上可以正常工作。
如果协商缓存无法正常工作,你可以采取以下步骤进行调试:
- 查看网络请求:在浏览器的开发者工具中查看网络请求,检查请求和响应头部是否正确。查看服务器是否在响应中发送了Etag或Last-Modified,以及是否正确处理了If-None-Match或If-Modified-Since请求头。
- 查看服务器日志:服务器的日志可能包含关于请求和响应的有用信息。如果服务器支持,你也可以在服务器上开启详细的日志记录。
- 检查服务器配置:确保你的服务器配置正确,并且支持协商缓存。你可能需要查阅你的服务器文档,或者联系你的服务器供应商。
如果问题仍然无法解决,你可能需要寻求专业的帮助,或者考虑使用一种不同的缓存策略。
3 启发式缓存
只有在没有明确缓存策略时,会激活启发式缓存。所以要合理设置缓存,否则会因没有设置缓存时间等原因,导致内容缓存不刷新。
接口数据缓存在浏览器
缓存数据的场景分为两种:
- 与用户无关的数据
- 与用户相关的数据
需要使用缓存的接口是无参数且为get类型的请求
- 对于用户无关的数据,可以存储在localStorage中
- 对于用户相关的数据,可以存储在sessionStorage中
- 不修改原有的接口使用方法,创建一个新的接口调用函数,并使调用方式保持不变
- 调用该方法时,先创建用于保存的key,再在对应的storage中查找是否有该key的缓存值,有则返回一个伪造的axios请求的Promise结果对象
- 没有缓存时请求到数据后需要将响应数据保存在本地存储中,并且需注意的是要对请求结果做判断,只保存成功拿到数据的结果,否则一次失败后将无法再获取成功的结果
- 创建用于缓存数据到localStorage的key时,使用了LOCALSTORAGE_CACHE_VERSION常量,该常用是使用webpack.DefinePlugin插件注入的值,这样是为了让每次重新发版后可以自动刷新本地缓存的数据
- 创建sessionRequest方法来请求用户相关的数据,与localRequest的区别在于key的创建
- 关于session缓存用户相关的数据,如果没有userId可供使用,可以使用一个全局的key来代替,确保该key会随着页面的刷新而变化即可,比如可以用进入页面后的某个时间点的时间戳
- 清除旧的localStorage缓存,由于浏览器对localStorage的大小是有限制的,所以在发版后对于先前保存的数据应当予以清除
参考:
- 接口数据缓存在浏览器 https://juejin.cn/post/7086056735588220958
- https://juejin.cn/post/7074924039348699167
5.2.5 tcp|udp
HTTP、TCP 和 UDP 是网络通信中的三个重要协议,它们各自在网络通信的不同层次和环节起到了关键的作用。
HTTP(HyperText Transfer Protocol)是应用层协议,主要用于在Web上传输信息,如HTML文档。它可以运行在TCP之上,也可以运行在其他的网络协议上。HTTP定义了客户端(通常是Web浏览器)如何向服务器发送请求,以及服务器如何返回响应。
TCP(Transmission Control Protocol)是传输层协议,负责在网络中的两个主机之间提供可靠的、有序的和基于字节流的数据传输。TCP使用确认和重传机制来保证数据的可靠传输,并使用拥塞控制机制来避免网络拥塞。HTTP就是运行在TCP之上的一个应用层协议。
UDP(User Datagram Protocol)也是传输层协议,但它与TCP不同,它提供的是一种无连接的服务,数据的传输既不保证可靠,也不保证有序。由于UDP没有TCP那样的确认和重传机制,因此它的开销比TCP小,实时性更好,适合于对实时性要求高的应用,如VoIP(网络电话)和实时视频会议等。
以下是它们的主要区别:
- 可靠性:TCP提供了可靠的数据传输,保证了数据的有序和无误。而UDP不保证数据的可靠传输,数据可能会丢失或者乱序。HTTP运行在TCP之上,因此也是可靠的。
- 连接性:TCP是连接导向的,通信双方在传输数据之前需要先建立连接。而UDP是无连接的,每个数据报都是独立传输的。HTTP作为应用层协议,其连接性取决于底层的传输协议,通常情况下,HTTP会在TCP的基础上建立连接。
- 实时性:由于UDP没有TCP那样复杂的确认和重传机制,因此UDP的实时性更好,适合于对实时性要求高的应用。而HTTP和TCP则更适合于对可靠性要求高的应用。
- 头部开销:TCP的头部开销比UDP大,因为TCP需要包含更多的信息,如序列号、确认号等,以支持它的可靠性和连接性。HTTP的头部开销则取决于HTTP的版本,HTTP/1.1的头部开销比较大,而HTTP/2和HTTP/3采用了头部压缩技术,大大减小了头部开销。
- 使用场景:HTTP主要用于Web应用,如网页浏览、表单提交等。TCP则可以用于各种需要可靠传输的网络应用,如文件传输、电子邮件、远程登录等。UDP则适合于需要快速传输和对实时性要求高的应用,如网络电话、实时视频会议和在线游戏等。
TCP和 UDP 区别
TCP 是面向连接的、可靠的流协议。流就是指不间断的数据结构,当应用程序采用 TCP 发送消息时,虽然可以保证发送的顺序,但还是犹如没有任何间隔的数据流发送给接收端。TCP是面向面向字节流,虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。
TCP 为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具备“流控制(流量控制)”、“拥塞控制”、提高网络利用率等众多功能。
TCP有以下特点:
- TCP充分地实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在 UDP 中都没有。
- 此外,TCP 作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。
- 根据 TCP 的这些机制,在 IP 这种无连接的网络上也能够实现高可靠性的通信( 主要通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现)。
基于 TCP 的应用层协议:FTP(文件传输)、HTTP(万维网)、SMTP(电子邮件)
当网络拥塞时,减少数据的发送。发送方有拥塞窗口,发送数据前比对接收方发过来的接收窗口,取两者的最小值---慢启动、拥塞避免、拥塞发送、快速恢复
UDP
UDP是一个非连接的协议,传输数据之前源端和终端不建立连接, 当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。 在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、 计算机的能力和传输带宽的限制; 在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
UDP 是面向报文的,所谓面向报文,是指面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会是IP太小。
UDP 是不具有可靠性的数据报协议,细微的处理它会交给上层的应用去完成。在 UDP 的情况下,虽然可以确保发送消息的大小,却不能保证消息一定会到达。因此,应用有时会根据自己的需要进行重发处理。
UDP有以下特点:
- UDP 不提供复杂的控制机制,利用 IP 提供面向无连接的通信服务。
- 传输途中出现丢包,UDP 也不负责重发。
- 当包的到达顺序出现乱序时,UDP没有纠正的功能。
- 并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网络上的一种机制。即使是出现网络拥堵的情况,UDP 也无法进行流量控制等避免网络拥塞行为。
- 如果需要以上的细节控制,不得不交由采用 UDP 的应用程序去处理。
基于 UDP 的应用层协议:DNS(域名转换)、TFTP(文件传输)、NFS(远程文件服务器)
UDP
//UDP收包率低/丢包率高的原因分析 1 缓存太小,不能及时接收数据。 连续多个UDP包超过了UDP接收缓冲区大小 ,比如: 如:UDP包过大 || UDP发包速率过快,突发大数据流量超过了缓冲区上限 2 recvfrom()接收到数据之后处理速度太慢 如果数据接收和处理是连续进行的,那么可能由于数据处理过慢,两次recvfrom调用的时间间隔里发过来的包丢失。 //对应的解决方法 1 UDP包过大 解决方法:增加系统发送或接收缓冲区大小 2 发包速率过快 解决方法:增加应答机制,处理完一个包后,在继续发包 3 recvfrom()接收到数据之后处理速度太慢 服务器程序启动之出,开辟两个线程,一个线程专门用于接收数据包,并存放在应用层的缓存区;另外一个线程用于专门处理和响应数据包请求,避免因为处理数据造成数据丢包。其本质上还是增大了缓冲区大小,只是将系统缓冲区转移到了应用层自己的缓冲区。 4 最复杂的方式 在应用层实现丢包重发机制和超时机制,确保数据包不丢失。 //如果UDP编程的时候的数据大于64kb 会怎么样? 1、在应用层进行数据包的拆分和组合。 2、 大于64KB 时不处理,会交给TCP/IP协议去处理,在网络层进行分包和组包,但是这种方式不用,容易丢包,一旦丢包便整体舍弃,及其不稳定。 //基于UDP实现的协议 DNS(域名解析服务)
5.3 TCP三次握手与四次挥手
- 第一次握手: 客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
- 第二次握手: 服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手: 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
- 握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
与建立连接的“三次握手”类似,断开一个TCP连接则需要“四次握手”。
- 第一次挥手: 主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。
- 第二次挥手: 被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
- 第三次挥手: 被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
- 第四次挥手: 主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。
为什么需要四次挥手?其实是客户端和服务端的两次挥手,也就是客户端和服务端分别释放连接的过程.
关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
- 面试题24:三次握手和四次挥手(计算机网络) https://blog.csdn.net/qq_51066068/article/details/124439302
5.4 Cookie
cookie 和 token 都存放在 header 中,为什么不会劫持 token?
cookie:登录后服务端生成的sessionid,并在http请求里返回到客户端,同时服务端保存sessionid,以后客户端的每次http请求都带上cookie(sessionid),服务端会获取cookie(sessionid)然后验证用户的身份。所以拿到cookie就拿到了sessionid,就可验证通过。同时浏览器会自动携带cookie;
token:同样是登录后服务端返回一个token,客户端保存起来,在以后http请求里手动的加入到请求头里,服务端根据token 进行身份的校验。浏览器不会自动携带token。
token不是为了防止xss攻击的,以CSRF攻击为例:
cookie:用户点击了链接,cookie未失效,导致发起请求后后端以为是用户正常操作,于是进行扣款操作; token:用户点击链接,由于浏览器不会自动带上token,所以即使发了请求,后端的token验证不会通过,所以不会进行扣款操作;
相同域名不同端口的两个应用,cookie名字、路径都相同的情况下,后面的cookie会覆盖前面的cookie吗?
如果浏览器访问的服务是ip或localhost的话,会覆盖;如果浏览器访问的是域名(在HOST中配置)的话,不会。
Cookie的其他的重要作用:
- 会话管理:Cookies常常用于记录用户的登录状态。当用户登录一个网站后,服务器会返回一个包含用户ID的cookie,然后浏览器在后续的请求中将这个cookie包含在内,以便服务器知道用户的登录状态。
- 个性化设置:许多网站允许用户个性化他们的体验,例如更改布局、设置主题、设置语言等。这些设置可以被存储在cookie中,然后在用户下次访问时使用。
- 跟踪用户行为:Cookies可用于跟踪用户在网站上的行为。例如,网站可以记录用户访问过哪些页面,点击过哪些链接,以便了解用户的兴趣和行为习惯,然后提供个性化的内容或者广告。
- 状态保持:在没有Cookie的情况下,HTTP协议本身是无状态的,也就是说服务器无法区分两个连续的请求是否来自同一用户。通过使用Cookie,服务器可以在用户的每次请求中识别出用户,以保持用户的状态。
**为什么有些cookie客户端访问不到但是服务端可以?**因为设置了HttpOnly后不能被doc.cookie访问。
1.1)Cookie是什么
- cookie本身是由服务器产生的,生成之后发送给浏览器,并保存在浏览器。
- cookie就是浏览器存储本地目录的一小段文本。
- cookie是以key-value形式存储的。
- cookie大小有限制,为了保证cookie不占用太多磁盘空间,每个cookie大小一般不超过4KB。
- cookie默认在会话结束后直接销毁,此种cookie称之为会话cookie。
- cookie可以设置过期时间,此种cookie称之为持久cookie。
- 相同浏览器下,并且是同源窗口(协议、域名、端口一致),不同页面可以共享localStorage,Cookies值,通过跳转的页面可以共享sessionStorage值。
Cookie 是服务器发送到用户浏览器并保存在浏览器上的一种数据。它用于在浏览器和服务器间保持状态,例如用户登录信息。以下是一个 Cookie 的主要字段及其作用:
- Name:Cookie 的名称。每个 Cookie 必须有一个唯一的名称。
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
前端校招面经分享,包含CSS、JS、Vue、React、计算机网络、难点项目、手撕题等。这份面经总结了几乎大厂所有的面试题与牛客近几年公开的面经,可以说面试不会超出范围。 因为我只负责总结加一些个人见解,所以一开始免费开源。但互联网戾气真的重,很多人拿着面经还一副理所应当的样子质问我要语雀,还说网上同类的有很多??唉,分享不易,那我只好收费了233。当然也欢迎直接来找我要语雀,语雀会多一些内容。