# 网络

#

# 网络

# 1. 谈谈cookie, sessionStorage 和localStorage之间的区别.

  1. 存储位置:三者都是浏览器的本地存储,这也是它们的共同点。

  2. 写入方式:cookie是由服务器端写入的,sessionStorage和localStorage是由前端写入。

  3. 生命周期:cookie的生命周期是服务器端在写入时就设置好的。localStorage除非手动删除,否则会一直存在。sessionStorage是会话级别的存储,浏览器页面已关闭就自动清除。

  4. 存储大小:cookie存储空间大小约为4kB。localStorage和sessionStorage就比较大,大概有5M。

  5. 数据共享:三者都遵循同源规则。sessionStorage还限制必须是同一个页面。

  6. 发送时是否自动携带:cookie在前端想后端发送请求时会自动携带,但是另外两个不会。

  7. 应用场景:cookie一般用于存储登录验证信息如SessionID、token。localStorage用于存储不易变动的数据,从而减轻服务器压力。SessionStorage可以用来检测用户是否是刷新还是关闭窗口后进入页面,如音乐播放器恢复播放进度条的功能。

# 2.HTTP的特点有哪一些?

  • 简单快速 :客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  • 灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记
  • 无连接: 无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

# 3.HTTP请求方法有哪一些?

  • GET 请求指定的页面信息,并返回实体主体。
  • HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头。
  • POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
  • PUT 从客户端向服务器传送的数据取代指定的文档的内容。
  • DELETE 请求服务器删除指定的页面。
  • CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
  • OPTIONS 允许客户端查看服务器的性能或支持的方法。
  • TRACE 回显服务器收到的请求,主要用于测试或诊断。

# 4.HTTP状态码有哪一些?

  • 1xx:指示信息--表示请求已接收,继续处理

101:Continue,表示继续请求;102: Switch Protocal 表示切换协议

  • 2xx:成功--表示请求已被成功接收、理解、接受

200:请求成功,一般用在get post;204: No Content表示请求成功但没有返回内容;206:Particial Content,表示返回部分数据,例如发起范围请求时的响应码就是206;

  • 3xx:重定向--要完成请求必须进行更进一步的操作

301: Moved Permanently,永久重定向;308: Permanently Redirect, 永久重定向, 和301不同的是不允许将Post重定向到Get;

302: Found,临时重定向,允许各种请求方法;303: See Other,重定向的请求方法都是Get; 307: Temporary Redirect,临时重定向,和302一样,但是不能将Post重定向到Get

  • 4xx:客户端错误--请求有语法错误或请求无法实现

401:Unauthorized 请求要求用户的身份认证。

403:Forbidden    服务器理解请求客户端的请求,但是拒绝执行此请求。

404:Not Found 服务器无法根据客户端的请求找到资源(网页)

408:Request Time-out 服务器等待客户端发送的请求时间过长,超时。

  • 5xx:服务器端错误--服务器未能实现合法的请求

500:Internal Server Error 服务器内部错误,无法完成请求。

502:Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应。

503:Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中。

# 5.知道持久连接与管线化吗?

  • 持久连接

    什么是持久连接?对于HTTP协议而言,它是基于请求响应模型,Client向Server发请求时,先建立一条HTTP连接,Server给Client响应数据后,连接关闭。

    当Client发送下一个请求时,需要重新再建立HTTP连接,这种方式就是:一个请求响应需要占用一条HTTP连接。而持久连接就是:只需要建立一条连接,然后在这条连接上传输多个请求和响应。

    与持久连接相关的字段有:

    HTTP1.0中有一个Connection首部字段,它是一个逐跳首部字段。Connection:Keep-Alive,表示希望将此条连接作为持久连接。

    HTTP1.1中,建立的HTTP请求默认是持久连接的。当Client确定不再需要向Server发送数据时,它可以关闭连接,即在发送首部中添加Connection:Closed字段。

  • 管线化

    ①管线化机制通过持久连接完成,仅HTTP/1.1支持此技术

    ②只有GET和HEAD请求可以进行管线化,而POST会有所限制

    ③初次创建连接时不应启动管线机制,因为对方服务器不一定支持HTTP/1.1版本的协议

  • 比较

    持久连接的一个最大的好处是:大大减少了连接的建立以及关闭时延。

    持久的缺点:请求响应是顺序执行的。只有在请求1的响应收到之后,才会发送请求2,这就是持久连接与管道化连接不同的地方。类似于:

    请求1=>响应1=>请求2=>响应2
    

    管道化后类似于:

    请求1=>请求2=>响应1=>响应2
    

    管道化连接是需要持久连接支持的。管道化连接是在持久连接的基础上,以“流水线”的方式发送请求:不需要等到请求1的响应到达Client,就可以发送请求2....

# 6.HTTP 2.0与HTTP 1.1区别

https://www.cnblogs.com/frankyou/p/6145485.html

# 7.帧、报文、报文段、分组、包、数据报的概念区别

帧、报文、报文段、分组、包、数据报的概念区别 - stardsd - 博客园 (opens new window)

# 8. 网络模型有哪些?

网络模型有4层网络模型、5层网络模型和7层网络模型。

  • 7层网络模型是标准化组织指定的一个完善的计算机网络模型,即OSI网络模型,它总上到下分为7层:应用层、表示层、会话层、传输层、网络层、数据链路层和物理层。但是这是一个理论上的模型,在实际中并没有对应的实现。

  • 5层网络模型主要是出现在书籍和教学当中,比如《计算机网络自顶向下》中讲解的就是5层模型。它自顶向下分为:应用层、运输层、网络层、链路层和物理层。

  • 4层模型是我们实际应用的网络模型即TCP/IP模型。从上到下分为应用层、传输层、网络层、网络接口层。每一层都由一些协议组成,各层协议就构成了一个协议栈。每一层的功能如下:

    • 应用层包括了相应的应用程序和应用层协议、其中HTTP就是我们最常用的应用层协议,它规定了请求和响应报文的格式。应用层生成HTTP协议报文之后会交给下一层即传输层。

    • HTTP在传输层默认采用TCP协议,这是一个传输层协议,叫做传输控制协议,能够保证数据包被正确的发送和接收。负责端到端的通信。在这一层,它会给应用层数据报添加TCP头部,然后将TCP报文交给下一层即网络层。

    • 网络层使用IP协议,每一个主机都会对应一个唯一的IP地址,用于定位。在这一层主要实现了网络包的封装、分片、路由、转发。在TCP数据包添加上IP头部后交给下一层即网络接口层。

    • 在网络接口层对应的硬件就是网卡。每一个网卡都会有一个MAC地址,通过ARP协议获得下一站的MAC地址之后,在IP数据包中添加帧头和帧尾,放到发包队列中。

# 9. HTTP协议发展?

![](file:///./images/3.png?msec=1673664295708)

# 10. 哪些请求方法是安全的?哪些是幂等的?

安全是指不会修改服务器数据的方法:GET、HEAD、OPTIONS

幂等(idempotent):同样的请求执行一次与连续执行多次的效果是一样的。服务器的状态也是一样的。所有safe的方法都是idempotent的。GET、HEAD、OPTIONS、PUT、DELETE

# 11. 状态码301和302的区别?

301永久重定向,302临时重定向。

# 12.RESTful API

一种api设计风格。REST——Representational State Transer

  1. 每一个URI代表一种资源

  2. 客户端与服务器之间,传递这种资源的某种表现层

  3. 客户端通过HTTP method,对服务器资源进行操作,实现“表现层状态转化”

# 13. UDP和TCP区别讲一下

首先,UDP是利用IP提供的面向无连接的通信服务,而TCP是面向连接的、可靠的、基于字节流的传输层协议。

  1. 连接:TCP先建立连接,UDP直接传输。

  2. 服务对象:TCP一对一,UDP一对多,多对多,一对一

  3. 可靠性:TCP可靠,UDP不保证可靠

  4. TCP拥有流量控制和拥塞控制,UDP没有

  5. TCP流式传输,无边界,UDP一个包一个包传输。

  6. 分片:TCP数据大小大于MSS,在传输层分片,在传输层组装,分片丢失只需传输该分片。UDP数据大小大于MTU,在IP层分片,在IP层组装。

# 14. 有一个 IP 的服务器监听了一个端口,它的 TCP 的最大连接数是多少?

因为一个TCP连接由四元组确定,而服务器端IP和端口号确定,那么理论上来说是客户端IP数乘上端口数。

# 15. TCP三次握手?四次挥手?

三次握手:

  1. 一开始双方处于CLOSED状态,首先服务器端主动监听某个端口,处于LISTEN状态。

  2. 客户端初始化一个随机序列号,放在SYN报文中发送给服务器端,之后客户端处于SYN-CENT状态,这是第一次握手。

  3. 服务器端接收到TCP报文,也初始化一个随机的序列号,然后把发送过来的序列号+1得到确认应答号,接着把SYN和ACK置1

  4. 客户端接收到响应,将序列号+1得到确认应答号,把ACK位置1发送给服务器端,连接建立。

  5. 其中第一次和第二次握手不能携带数据,第三次握手时客户端是可以向服务器端发送数据的。序列号的作用是防止包乱序,确认应答号是保证对方接收到TCP报文。

为什么是三次不是两次?

  1. 主要的原因是为了避免重复的历史连接。第三次握手的作用就是告诉服务器可以发送传输数据了或者断开连接。假设只有两次握手,客户端发送一个SYN报文,由于网络拥堵客户端又发送了一个SYN报文,旧的报文先到达服务器,服务器回送SYN+ACK以后进入establish状态,开始传输数据,之后新的报文到达,因为客户端并没有告诉服务器之前那是一个历史连接,所以之前的连接还在,然后现在又建立起一个新连接,这样就导致连接重复,浪费了服务器端的资源。但是三次握手就可以解决这个问题,当客户端要重新发起请求建立连接时,它可以先发送一个RST断开和服务器的历史连接,然后再去建立新连接。

四次挥手:

双方都可以主动关闭连接,这里以客户端主动关闭连接为例。

  1. 客户端发送一个FIN报文,FIN_WAIT_1

  2. 服务端接收到FIN报文后回应一个ACK报文,CLOSE_WAIT

  3. 客户端接收到ACK报文后进入等待状态,FIN_WAIT_2

  4. 服务端处理完数据之后再向客户端发送一个FIN报文,LAST_ACK

  5. 客户端回一个ACK报文,TIME_WAIT

  6. 服务器端接收到响应后关闭连接,CLOSED

  7. 客户端经过一段时间后(2MSL)自动关闭连接,CLOSED

TCP四次挥手可以变成三次吗?

可以,当被动关闭方(上图的服务端)在 TCP 挥手过程中,没有数据要发送并且开启了 TCP 延迟确认机制,那么第二和第三次挥手就会合并传输,这样就出现了三次挥手。

TCP 延迟确认机制是指ACK应答会延迟等待一段时间再发送(看看能不能随数据一起发送,因为ACK报文比较消耗性能)

# 16. TCP重传

TCP为了确保数据准确地传送给对方,当发送端向接收端发送数据包,接收端接收到数据以后会向发送端发送确认应答。

当数据包发生丢失的情况就会触发重传。

常见的TCP重传有4种:

  • 超时重传

  • 快速重传

  • SACK

  • D-SACK

  1. 超时重传

从发送数据到接收到应答的时间超过重传时间RTO就会触发超时重传,导致超时的原因有两个,一是数据包丢失,而是确认应答丢失。RTO的大小既不能过大也不能过小,过大可能造成传输效率下降,过小又可能导致重复发送数据。所以RTO应该比RTT略大一些。但实际上RTO是动态变化的,因为网络状况是不稳定的。超时重传还有一个特点就是每一次重传的超时间隔都会增大到前一次的两倍,因为多次超时就说明网络情况不适宜频繁发送数据。

  1. 快速重传

当收到三个相同的ACK报文时会在定时器过期前重传丢失的报文,但是这样有一个问题,那就是不知道要重传丢失的那个报文还是之后的所有报文,因为收到的三个ACK确认应答号都是相同的。于是就有了下面的SACK方法

  1. SACK(选择性确认)

工作原理是通过在TCP报文头部字段种增加一个SACK的东西,它可以将缓存的地图给数据发送方,数据发送接收到缓存地图后就知道哪些数据丢失了,这样重发丢失的数据就行了。

  1. Duplicate SACK

当确认应答丢失触发重传时,接收方接收到重传的数据判断为重复数据后就会发送D-SACK告诉发送方已经接收到该数据,重复发送了该数据。

# 17. 滑动窗口

  1. Why?

TCP在发送数据时都要进行确认应答,接收到确认应答之后才发送下一个数据。

但是这样会导致通信效率低下,如果确认应答迟迟未收到,那么发送方无法发送下一个数据。

为了解决这个问题就引入了窗口这个东西。它允许发送方连续发送多个数据。

  1. HOW?

窗口的实现原理是操作系统在内存中开辟一块缓冲区,发送方将发送的数据缓存在缓冲区,当收到正确的应答才把该数据从缓冲区移除。

而且,如果连续发送的TCP数据有一个ACK应答丢失,可以通过下一个ACK应答来进行确认,这样就不用重新发送数据。

  1. 窗口大小

TCP头里有一个Window字段,表示窗口大小。一般来说窗口大小是由接收方决定的,接收方通过该字段告诉发送方自己还能处理数据的缓冲区大小,发送方根据它的能力来发送数据。

这样保证了发送的数据能够被接收方正确处理。

  1. 发送方与接收方窗口的划分

    1. 发送方:四个区域,三个指针(),一个大小

    2. 接收方:三个区域,两个指针,一个大小

  2. 发送方的窗口大小一定等于接收方窗口大小吗?

是约等于的关系,接收方处理快时窗口大,通过Window字段通知发送方,由于时延,所以并不能保证一定大小相等。

  1. 如何通过滑动窗口实现流量控制

# 18. http攻击

  1. DOS拒绝服务攻击

DOS攻击是通过发送大量请求使得目标电脑网络和系统资源耗尽,使服务中断或暂停,其他用户无法访问的攻击方式。

当攻击者使用网络上2台以上的电脑进行攻击时就成了DDOS分布式拒绝服务攻击。

DOS分为几种类型:资源消耗型、带宽消耗型、漏洞触发型。

带宽消耗型如UDP floods、ICMP floods,UDP floods通过发送大量的UDP数据包到攻击目标,堵塞其带宽。ICMP通过向未良好设置的路由器发送广播信息占用系统资源的做法。

资源消耗型如SYN floods(利用TCP三次握手,发送大量的SYN数据包却不回送ACK来占用接收端资源)、LAND攻击、CC攻击(利用代理服务器进行攻击,一位中国黑客开发的工具。)

漏洞触发型如ping of death(产生IP协议所能承受的数据包数使系统宕机)

防御方式:入侵检测、流量过滤、多重验证。

防火墙:设置允许或拒绝特定通讯协议,端口或IP地址。

使用交换机检测并过滤DOS

流量过滤:当获取到流量时,通过DDoS防御软件的处理,将正常流量和恶意流量区分开,正常的流量则回注回客户网站,反之则屏蔽。

  1. CSRF跨站请求伪造

https://segmentfault.com/a/1190000022842875

挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

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

防御:1.将cookie设置为HttpOnly。CSRF攻击很大程度是利用了浏览器的cookie,cookie设置HttpOnly属性,JS脚本就无法读取到cookie中的信息,避免攻击者伪造cookie的情况出现。2.增加token。3.检查Referer字段,这个字段用以标明请求来源于哪个地址。但是也有可能被篡改。

  1. XSS跨站脚本攻击

在通过注册的网站用户的浏览器内运行非法的HTML标签或javascript,从而达到攻击的目的,如盗取用户的cookie,改变网页的DOM结构,重定向到其他网页等。XSS攻击分类包含反射型,存储型,DOM型,FLASH。

防御:不要相信用户的任何输入,并过滤掉输入中的所有特殊字符。主要有两种方式:过滤特殊字符和使用HTTP头指定类型。

  1. DNS查询攻击

向被攻击的服务器发送海量的随机生成的域名解析请求,大部分根本就不存在,并且通过伪造端口和客户端IP,防止查询请求被ACL过滤。

防御:根据域名 IP 自学习结果主动回应,减轻服务器负载(使用 DNS Cache);对突然发起大量频度较低的域名解析请求的源 IP 地址进行带宽限制;在攻击发生时降低很少发起域名解析请求的源 IP 地址的优先级;限制每个源 IP 地址每秒的域名解析请求次数。

# 19. get post区别 ,get在不同浏览器中的最大长度

语义:get表示要获取资源,post表示要提交数据。

应用场景:get是安全的,它一般用于查询、读取。请求中的URL可以手动输入,例如我们在浏览器中去访问一个网址。请求URL可以被保存在书签历史或浏览器缓存中,还可以分享给别人。post用于改变资源的状态。

报文差别:get请求头最大长度是2048个字符,且只允许是ASCII字符;post的URL长度没有限制。

本质区别:请求行不同,对资源的操作不同。

不同浏览器get URL长度:

  • Google Chrome 允许 URL 的最大长度为 2MB

  • 在 Firefox 中,URL 的长度可以不受限制,但实际上在** 65,536 个字符之后,位置栏不再显示 URL,也就是2个字节**

  • Internet Explorer 允许 URL 的最大长度为 2083 个字符,但在 URL 的路径部分中 不超过2048 个字符

  • Opera 允许 URL 长度不受限制

  • Safari中 URL 的最大长度为 80000 个字符,超过此限制后页面会显示错误。

# 20.怎么设置cookie的有效时间 ,代码是啥

服务器收到 HTTP 请求时,在响应头里面添加一个 Set-Cookie 字段

浏览器收到响应后保存下 Cookie

前端设置cookie

/**
 * 设置cookie
 */
export function setCookie(name, value, hours = 24){
  let str = name + "=" + value;
  const time = new Date(new Date().getTime() + hours * 3600 * 1000).toGMTString();  // toGMTstring将时间转换成字符串
  str += "; expires=" + time;
  // 写入Cookie
  document.cookie = str;
}

/**
 * 获取cookie
 */
export function getCookie(name){
  const reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"),
    arr = document.cookie.match(reg);
  if (arr !== null) {
    return arr[2];
  } else {
    return null;
  }
}

/**
 * 清除cookie
 */
export function clearCookie(name){
  setCookie(name, '', -1)
}

# 21. CSRF攻击及其防御

直接看美团这篇文章

https://tech.meituan.com/2018/10/11/fe-security-csrf.html

  1. CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

  2. 一个典型的CSRF攻击有着如下的流程:

  • 受害者登录a.com,并保留了登录凭证(Cookie)。

  • 攻击者引诱受害者访问了b.com。

  • b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。

  • a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。

  • a.com以受害者的名义执行了act=xx。

  • 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。

  1. 常见的CSRF攻击类型有三种:get类型、post类型和链接类型。

get: 通常是在网页中放入一个img链接,当用户访问时就会自动向链接中的网站发送请求,并且携带用户在该域下的cookie。

post: 通常是在网页中放入一个隐藏的会自动提交的表单。

链接类型的比较少见,因为它需要用户去主动点击链接。

  1. CSRF特点
  • 攻击由第三方网站发出而不是被攻击的网站

  • 冒用了用户身份,但攻击者是不能取得用户身份凭证如cookie的。

  • 攻击方式多样难以追踪。

  1. 防护策略

根据CSRF的特点:攻击由第三方网站发起,攻击者不能获取到cookie信息,只能使用:

  • 阻止不明外域的访问

    • 同源检测

    利用HTTP Header: Origin / Referer

    • Samesite Cookie

    Samesite=Strict: 只要是外域的请求都不会携带cookie

    Samesite=Lax:页面间跳转会携带cookie,但是其他跨域请求不会

  • 提交时要求附加本域才能获取到信息

    • CSRF Token

    在每一个请求中携带token,服务器端验证token有效性。

  • 双重cookie验证

    除了浏览器自动携带的cookie,可以在参数中加入cookie,然后服务器验证cookie有效性,这种防御方式利用了黑客无法获取cookie值的特点。

# 22. HTTP协议的缓存策略有哪些?

(1)首先,缓存策略都是针对于第二次及之后的资源请求,在第一次请求资源时,服务器会返回数据以及通过报文header来告知客户端使用怎样的缓存策略。客户端拿到响应数据后,会将数据和资源标识备份到缓存数据库里。

(2)第二次或之后发起请求时

  • 强缓存
    • header:
      • Cache-Control(http1.1)
        • no-store: 不使用缓存
        • no-cache: 使用缓存但是得到服务进行比对,检查资源是否更新
        • max-age: 单位是秒,在规定时间内直接使用缓存,强缓存
      • Expires(http1.0): 单位是秒,和max-age类似,但优先级比较低
    • 在network中显示的是from memory或者from disk。
  • 协商缓存
    • 第一次请求时服务器发送的header
      • Last-modified
        • 代表资源的最后修改时间
      • Etag
        • 代表资源在服务器上的唯一标识
        • 优先级比Last-modified高
    • 第二次请求时在请求头可以包含
      • If-Last-Modified
        • 就是上次服务器返回的Last-Modified
        • 和服务器上的最后修改时间进行比较,如果服务的最后修改时间比它大,不使用缓存,返回新资源;否则比较成功,返回304状态码告知客户端使用缓存
      • If-None-Match
        • 就是上次服务器返回的Etag
        • 用于比较资源的差异
          • 强Etag: 字节上的变化就返回新资源
          • 弱Etag: 允许部分变化,比如html标签顺序的改变,多了几个空格等
            • 值前面加上'W/'
      • 如果 HTTP/1.1 缓存或服务器收到的请求既带有 If-Modified-Since,又带有实体标签条件首部,那么只有这两个条件都满足时,才能返回 304 Not Modified 响应。

(3)浏览器行为对缓存的影响

  • 浏览器地址栏回车,或者点击跳转按钮,前进,后退,新开窗口
    • Expires,max-age
  • F5刷新浏览器,或者使用浏览器导航栏的刷新按钮
    • 会忽略掉Expires,max-age的限制,浏览器会在请求头里加一个“Cache-Control: max-age=0” 强行发起请求,它可以配合 ETag 和 Last-Modified 使用,如果本地缓存还在,且服务器返回 304 ,依然可以使用本地缓存。
  • CTRL+F5
    • 强制请求,它其实是发了一个“Cache-Control: no-cache”,含义和“max-age=0”基本一样,就看后台的服务器怎么理解,通常两者的效果是相同的。
  • 很多网站的cache-control设置为no-cache,也就是使用缓存前都判断文件是否为最新,更为合理。

参考

http缓存详解,http缓存推荐方案 (opens new window)

[面试官:说说浏览器缓存知识

# 23. 跨域及解决方案

(1)CORS

  • CORS即跨域资源共享机制,实现方式简单来说就是在服务器返回的响应头里告诉浏览器允许该源请求资源。

  • CORS跨域分为两种请求

  • 简单请求

    • 简单请求满足以下所有条件
    • 一种简单的实现CORS的方式就是在请求报文的头部添加 Origin字段告知服务器当前请求来自的源;服务器则在响应报文头部中添加 Access-Control-Allow-origin字段来允许该源的资源请求,其值可以是 *表示允许任意域名的请求,也可以是具体的域名,表示仅允许来自该域名的资源请求。
    • 除了Access-Control-Allow-origin字段以外,还可以添加以下两个可选的字段
      • Access-control-Allow-Credentials:它的值是一个布尔值,表示是否允许在请求时发送cookie,该值只能设置为true,如果不允许时应当删除该字段。CORS请求默认不发送cookie.
      • Access-Contronl-Expose-Headers:CORS请求时,XHR对象的 getResponseHeader()方法只能拿到6个基本字段:Cache-ControlExpiresLast-ModifiedContent-TypeContent-LanguagePragma,如果想拿到其他字段,就必须在该字段里面进行指定。
  • 复杂请求

    • 不满足简单请求条件的请求就是复杂请求

      • 例如请求方法是PUTDELETE,或者 Content-Type字段的值是 appliction/json
    • 预检请求

      • 作用是防止服务器资源被修改等
      • 当浏览器发现一个请求是复杂请求之后,会以 OPTIONS方式主动发出一个预检请求
      • 预检请求报文头部包含两个首部字段
        • Access-Control-Request-Method告知服务器实际请求使用的方式
        • Access-Control-Request-Header告知服务器实际请求携带的自定义头部字段
      • 服务器接收到预检请求后,可以通过响应头部的 Access-Control-Allow-OriginAccess-Control-Allow-HeadersAccess-Control-Allow-Methods 来告知浏览器:服务器允许哪个源,哪种请求头,哪种方式的请求。同时还可以通过 Access-Control-Max-Age表明响应的有效时间,即在该时间内浏览器无需再为同一请求发送预检请求。
    • 预检请求之后发送实际请求

  • 如果要携带cookie

    • 对于发送者:原生Js方式必须设置XHR对象的 withCredentials属性为true,才会携带cookie

      xhr.withCredentials = true;

    • 对于服务器:必须在响应头部设置 Access-Control-Allow-Credentials: true,否则浏览器不会把响应内容返回给发送者。对于复杂请求发送的额外的预检请求的响应,也必须设置 Access-Control-Allow-Credentials: true

      • 同时要注意的是,响应不能设置Access-Control-Allow-OriginAccess-Control-Allow-HeadersAccess-Control-Allow-Methods 的值设为通配符“*

(2)JSONP

  • 原理:利用<script>标签没有跨域限制的特性
  • 使用流程
    • 通过<script>标签的src属性把回调函数名即参数传到服务端,服务端在请求的脚本里将需要的资源传入该函数并执行该函数,然后前端就可以执行该脚本从而执行该函数拿到对应的资源。

参考:

  1. 10种跨域解决方案(附终极大招) (opens new window)
  2. [3000字说说跨域!面试官听完之后露出了满意的笑容

浏览器有哪几种缓存,区别是什么?

浏览器缓存主要有http缓存cookieWeb Storage,其中Web Storage又分为sessionStoragelocaStorage

共同点:都是保存在浏览器端、且同源的。

区别

  • cookie数据始终在同源的http请求中携带(即使不需要),即cookie数据会在浏览器和服务器之间来回传递,而sessionStorage和localStorage则不会主动把数据发送给服务器,仅在本地进行存储。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下
  • 存储大小限制不同,cookie数据不能超过4k,同时由于每次发起http请求都会携带cookie、所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
  • 数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie:只在设置的cookie过期时间之前有效,即使窗口关闭或浏览器关闭
  • 作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage和cookie在所有同源窗口中都是共享的。
  • web Storage支持事件通知机制,可以将数据更新的通知发送给监听者
  • web Storage的api接口使用更方便

# 24. 谈谈你对HTTP/2的理解?

  1. HTTP2相比于HTTP1.1有许多新的特性,包括二进制分帧传输,头部压缩,多路复用和服务器推送。

  2. 二进制分帧:之前的HTTP报文都是纯文本形式传输,HTTP2则是全部采用二进制形式传输,一个报文可以被分为多个二进制帧,同一个报文的帧会有相同的StreamID标识,这样接收后就可以进行组装。不同StreamID的帧可以乱序传输。

  3. 头部压缩:在HTTP2之前如果head中包含UserAgent等字段,那么头部占用的大小可能会很大,而body的大小却比较小。HTTP2使用HPACK算法进行压缩,如果是之前传输过的头部信息,再次传送就只传送索引。

  4. 多路复用:HTTP1.x如果要并发多个请求必须建立多个TCP连接,并且浏览器对TCP连接数量有限制(6-8个),而HTTP2同域名下的所有通信都可以在一个连接上完成。一个连接可以承载任意量的双向数据流。

  5. 服务器推送:浏览器发送一个请求,服务器可以推送与这个请求相关的资源,浏览器不用发起后续的请求。推送的资源可以由不同的页面共享。

# 25. 说说DNS查询?

DNS即域名系统,是一个应用层协议,通常是运行在UDP协议之上。查询过程:

  1. 浏览器缓存

  2. 本地hosts文件

  3. 本地DNS解析器的缓存

  4. 本地DNS服务器发起请求向其他DNS服务器查询。

查询分为递归查询和迭代查询,一般本地服务器查询是递归查询即只用发起一次请求,而本地服务器向其他服务器的查询是迭代查询。

利用DNS查询还可以实现负载均衡,比如有一个域名对应多台不同IP的服务器,那么每次DNS查询到这些IP的列表后会循环列表的顺序,而客户端会优先选择最前面的IP地址,所以就实现了负载均衡。

# 26. SSL握手过程?

# 27. SSL连接断开后如何恢复?

# 28. 浏览器输入URL之后发生的事情?

以下答案来自[github](GitHub - qiu-deqing/FE-interview: 收集的前端面试题和答案 (opens new window))

  1. 在浏览器地址栏输入 URL

  2. 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤

    1. 如果资源未缓存,发起新请求
    2. 如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证。
    3. 检验新鲜通常有两个 HTTP 头进行控制ExpiresCache-Control
      • HTTP1.0 提供 Expires,值为一个绝对时间表示缓存新鲜日期
      • HTTP1.1 增加了 Cache-Control: max-age=,值为以秒为单位的最大新鲜时间
  3. 浏览器解析 URL获取协议,主机,端口,path

  4. 浏览器组装一个 HTTP(GET)请求报文

  5. 浏览器获取主机 ip 地址,过程如下:

    1. 浏览器缓存
    2. 操作系统缓存
    3. hosts 文件
    4. 路由器缓存
    5. ISP DNS 缓存
    6. DNS 递归查询(可能存在负载均衡导致每次 IP 不一样)
  6. 打开一个 socket 与目标 IP 地址,端口建立 TCP 链接,三次握手如下:

    1. 客户端发送一个 TCP 的SYN=1,Seq=X的包到服务器端口
    2. 服务器发回SYN=1, ACK=X+1, Seq=Y的响应包
    3. 客户端发送ACK=Y+1, Seq=Z
  7. TCP 链接建立后发送 HTTP 请求

  8. 服务器接受请求并解析,将请求转发到服务程序,如虚拟主机使用 HTTP Host 头部判断请求的服务程序

  9. 服务器检查HTTP 请求头是否包含缓存验证信息如果验证缓存新鲜,返回304等对应状态码

  10. 处理程序读取完整请求并准备 HTTP 响应,可能需要查询数据库等操作

  11. 服务器将响应报文通过 TCP 连接发送回浏览器

  12. 浏览器接收 HTTP 响应,然后根据情况选择关闭 TCP 连接或者保留重用,关闭 TCP 连接的四次握手如下

    1. 主动方发送Fin=1, Ack=Z, Seq= X报文
    2. 被动方发送ACK=X+1, Seq=Z报文
    3. 被动方发送Fin=1, ACK=X, Seq=Y报文
    4. 主动方发送ACK=Y, Seq=X报文
  13. 浏览器检查响应状态吗:是否为 1XX,3XX, 4XX, 5XX,这些情况处理与 2XX 不同

  14. 如果资源可缓存,进行缓存

  15. 对响应进行解码(例如 gzip 压缩)

  16. 根据资源类型决定如何处理(假设资源为 HTML 文档)

  17. 解析 HTML 文档,构件 DOM 树,下载资源,构造 CSSOM 树,执行 js 脚本,这些操作没有严格的先后顺序,以下分别解释

  18. 构建 DOM 树

    1. 词法分析(tokenize):将字符流解析为标记,起始标签,结束标签,文本,注释都会生成对应的token,加入到token队列中。还会进行一些特殊的处理,例如起始标签属性解析为键值对等。
    2. 语法分析:语法分析将token流转换为DOM节点。
    3. 生成DOM:将DOM节点组装成DOM树

    其中2,3步是同步进行的。

  19. 解析过程中遇到图片、样式表、js 文件,启动下载

  20. 构建CSSOM 树

    1. Tokenizing:字符流转换为标记流
    2. Node:根据标记创建节点
    3. CSSOM:节点创建 CSSOM 树
  21. 根据 DOM 树和 CSSOM 树构建渲染树 (opens new window):

    1. 从 DOM 树的根节点遍历所有可见节点,不可见节点包括:1)script,meta这样本身不可见的标签。2)被 css 隐藏的节点,如display: none
    2. 对每一个可见节点,找到恰当的 CSSOM 规则并应用
    3. 发布可视节点的内容和计算样式
  22. js 解析如下

    1. 浏览器创建 Document 对象并解析 HTML,将解析到的元素和文本节点添加到文档中,此时document.readystate 为 loading
    2. HTML 解析器遇到没有 async 和 defer 的 script 时,将他们添加到文档中,然后执行行内或外部脚本。这些脚本会同步执行,并且在脚本下载和执行时解析器会暂停。这样就可以用 document.write()把文本插入到输入流中。同步脚本经常简单定义函数和注册事件处理程序,他们可以遍历和操作 script 和他们之前的文档内容
    3. 当解析器遇到设置了async属性的 script 时,开始下载脚本并继续解析文档。脚本会在它下载完成后尽快执行,但是解析器不会停下来等它下载。异步脚本禁止使用 document.write(),它们可以访问自己 script 和之前的文档元素
    4. 当文档完成解析,document.readState 变成 interactive
    5. 所有defer脚本会按照在文档出现的顺序执行,延迟脚本能访问完整文档树,禁止使用 document.write()
    6. 浏览器在 Document 对象上触发 DOMContentLoaded 事件
    7. 此时文档完全解析完成,浏览器可能还在等待如图片等内容加载,等这些内容完成载入并且所有异步脚本完成载入和执行,document.readState 变为 complete,window 触发 load 事件
  23. 显示页面(HTML 解析过程中会逐步显示页面)

# 29. 什么是TCP?

TCP是一个传输层的通信协议,它具有面向连接,可靠,基于字节流的特点。

面向连接是说TCP是一个一对一的协议;可靠指TCP保证接收端接收到报文;基于字节流指报文消息可被分组传送并被正确接收。

# 30. 什么是TCP连接?

连接是指一些状态信息的组合,对于TCP连接而言包括socket、序列号、窗口大小等。

# 31. http和https的区别?

端口不同,明文和加密,https需要申请CA证书,http速度比https快

# 32. post请求的请求body长啥样?

请求体传输的数据格式应该是后端也能处理的,例如json,formData

  1. 传输json,Content-Type: application/json
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 57

{"name":"John Smith","age":30,"city":"New York"}
  1. 传输formData,以传输一张图片为例

请求体中每部分数据由boundary分隔,每个部分包含首部和主体。

POST /upload HTTP/1.1
Host: example.com
Content-Length: 356
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryyrV7KO0BoCBuDbTL

------WebKitFormBoundaryyrV7KO0BoCBuDbTL
Content-Disposition: form-data; name="title"

Title of the image
------WebKitFormBoundaryyrV7KO0BoCBuDbTL
Content-Disposition: form-data; name="image"; filename="example.jpg"
Content-Type: image/jpeg

(此处省略图片的二进制数据)
------WebKitFormBoundaryyrV7KO0BoCBuDbTL--