前端面试之计算机网络
1. HTTP 和 HTTPS
定义
超文本传输协议(HyperText Transfer Protocol,HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。
HTTPS 是一种通过计算机网络进行安全通信的传输协议,经由 HTTP 进行通信,利用 SSL/TLS 建立全信道,加密数据包。HTTPS使用的主要目的是提供对网站服务器的身份认证,同时保护交换数据的隐私与完整性。
区别
- HTTPS 协议需要到 CA 申请证书,一般免费证书很少,需要交费。
- HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协议。
- HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- HTTP 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
SSL 握手过程
- 客户端给出协议的版本号、一个客户端生成的随机数和客户端支持的加密算法;
- 服务端在客户端给出的加密算法列表中选出一种,并给出数字证书和一个服务端生成的额随机数;
- 客户端确认数字证书的有效性,然后生成一个新的随机数,并使用数字证书中的公钥加密这个随机数;
- 服务端使用私钥解密,获取客户端发来的随机数;
- 客户端和服务端根据约定的加密方法,使用之前的三个随机数,生成对话密钥,这个密钥会用来加密接下来的整个通信过程
2. TCP 三次握手
3. TCP 和 UDP
- TCP 面向连接,UDP 是无连接的,即发送数据之前不需要建立连接。
- TCP 提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付。
- TCP 面向字节流,实际上是 TCP 把数据看成一连串无结构的字节流;UDP 是面向报文的。UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如 IP 电话,实时视频会议等)。
- 每一条 TCP 连接只能是点到点的;UDP 支持一对一,一对多,多对一和多对多的交互通信。
- TCP 首部开销 20 字节;UDP 的首部开销小,只有 8 个字节。
- TCP 的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道。
4. WebSocket
- WebSocket 是 HTML5 中的协议,支持持久连续,HTTP 协议不支持持久性连接。
- WebSocket 是基于 HTTP 协议的,或者说借用了 HTTP 协议来完成一部分握手,在握手阶段 与 HTTP 是相同的。指定两个属性,
upgrade
和connection
。Upgrade: websocket Connection: Upgrade
5. HTTP1.0/HTTP1.1/HTTP2/HTTP3
HTTP1.0 和 HTTP1.1
- HTTP1.0 中主要使用 header 里的
If-Modified-Since
,Expires
来做为缓存判断的标准,HTTP1.1 则引入了更多的缓存控制策略例如Entity tag
,If-Unmodified-Since
,If-Match
,If-None-Match
等更多可供选择的缓存头来控制缓存策略。 - HTTP 1.1 支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟,在 HTTP1.1 中默认开启
Connection:keep-alive
,一定程度上弥补了 HTTP1.0 每次请求都要创建连接的缺点。
HTTP1 和 HTTP2.0
HTTP1 缺点
- TCP连接数限制 (可通过域名分片解决)
- 头部阻塞
- 明文传输不安全
HTTP2
- 二进制分帧,帧是数据传输的最小单位,以二进制传输代替原本的明文传输,原本的报文消息被划分为更小的数据帧
- 首部压缩
- 多路复用
- 服务端推送
HTTP3
QUIC协议(全称Quick UDP Internet Connections,快速UDP互联网连接)
- 实现了类似TCP的流量控制、传输可靠性的功能。
- 集成了TLS加密功能。
- 实现了HTTP/2中的多路复用功能。
6. HTTP 状态码
- 1xx:消息,请求已被服务器接收,继续处理
- 2xx:成功,请求已成功被服务器接收、理解、并接受
- 3xx:重定向,需要后续操作才能完成这一请求
- 301 永久移动
- 302 临时移动
- 304 未修改,使用缓存
- 4xx:请求错误,请求含有词法错误或者无法被执行
- 401 需要认证
- 403 无权限
- 404 未找到
- 405 方法不被允许
- 5xx:服务器错误,服务器在处理某个正确请求时发生错误
7. HTTP 常用请求头
- Accept 可接受的相应内容类型
- Accept-Charset 可接受的字符集
- If-Modified-Since、If-None-Match 未修改返回304
- 还有很多……待补充 TODO
8. 强缓存、协商缓存
缓存好处
(1)减少页面加载时间;(2)减少服务器负载;
强缓存
浏览器在加载资源时,先判断它是否命中强缓存,强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器。
HTTP1.0 - Expires
请求资源时服务器会返回 Expires
,(比如expires: Fri, 01 Jan 2021 00:00:00 GMT
)下次请求前用 Expires
跟当前的请求时间比较,如果请求时间在 Expires
指定的时间之前,就能命中缓存,否则从服务器加载资源。缺点是客户端时间和服务器时间有误差。
HTTP1.1 - Cache-Control
服务器返回 Cache-Control
,这是一个相对时间,表示缓存有效期,单位秒。(比如:cache-control: max-age=1800, s-maxage=60
其中 s-maxage
一般应用于缓存服务器)。
协商缓存
当浏览器对某个资源的请求没有命中强缓存,就会发一个请求到服务器,验证协商缓存是否命中,如果协商缓存命中,请求响应返回 304 Not Modified
。
Last-Modified,If-Modified-Since
服务器返回资源会返回 Last-Modified
,表示这个资源在服务器上的最后修改时间。(比如:last-modified: Tue, 18 Jan 2022 02:52:12 GMT
),下次请求客户端就会加上请求头 If-Modified-Since
,且对应值会服务器返回的时间(if-modified-since: Tue, 18 Jan 2022 02:52:12 GMT
)。
服务器再次收到资源请求时,根据浏览器传过来 If-Modified-Since
和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回 304 Not Modified
,但是不会返回资源内容;如果有变化,就正常返回资源内容。
缺点是有时文件改动但是时间没有修改(间隔时间过短),或者时间修改但是并没有改动文件。
HTTP1.1 - ETag、If-None-Match
服务器返回 ETag
用于标记文件,当 ETag
修改时表示文件被修改。(如:etag: 2e681a-6-5d044840
)
浏览器请求时会发送 If-None-Match
和上一次返回的 ETag
,服务器根据两次 ETag
判断是否是最新文件。
禁止缓存
请求时可以禁止缓存,cache-control: no-cache, no-store
。
no-cache
表示每次请求资源都会向浏览器发送请求(即取消强缓存),no-store
取消缓存。
public 和 private
Cache-Control
可以指定 public
或 private
,private
表示为用户个人信息,不能在缓存服务器缓存。
9. HTTP 支持方法
GET, POST, HEAD, OPTIONS, PUT, DELETE, TRACE, CONNECT
10. GET 和 POST 区别
【前端 · 面试 】HTTP 总结(五)—— GET 和 POST
- GET 多用于从服务端获取资源,POST 一般用来向服务端提交资源
- GET 一般用URL传参,由于 URL 长度限制参数长度有限制,POST 参数可以放在 body 中,无长度限制。
- 参数的数据类型,GET 只接受 ASCII 字符,而 POST 没有限制。
- GET 请求只能进行 URL 编码,POST 支持多种编码方式。
- GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置。
11. 在地址栏里输入一个 URL,到这个页面呈现出来,中间会发生什么?
- DNS 解析
域名解析为 IP 地址,浏览器缓存-->操作系统缓存-->访问 DNS 服务器 - TCP 连接
三次握手、四次挥手 - HTTP 请求
强缓存、协商缓存 - 服务端处理请求,HTTP 响应返回
返回码 - 浏览器拿到响应数据,解析响应内容,把解析的结果展示给用户
DOM树、CSSOM树、Render树、回流、重绘
12. XSS 和 CSRF
前端安全系列(一):如何防止XSS攻击?
前端安全系列之二:如何防止CSRF攻击?
XSS
Cross-Site Scripting(跨站脚本攻击) 简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。
XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。
XSS 分类
根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。
类型 | 存储区* | 插入点* |
---|---|---|
存储型 XSS | 后端数据库 | HTML |
反射型 XSS | URL | HTML |
DOM 型 XSS | 后端数据库/前端存储/URL | 前端 JavaScript |
- 存储区:恶意代码存放的位置。
- 插入点:由谁取得恶意代码,并插入到网页上。
前两种属于服务器安全漏洞,DOM 型 XSS 由前端取出恶意代码并执行,属于前端漏洞。
XSS 攻击的预防
- 输入过滤
- 改成纯前端渲染,把代码和数据分隔开
- 不要把不可信的数据作为 HTML 插到页面上、对 HTML 做充分转义
- 不要在 JavaScript 中执行不信任的字符串,比如
eval()
- Content Security Policy、输入内容长度控制、
HTTP-only Cookie
、验证码
CSRF
CSRF(Cross-site request forgery)跨站请求伪造:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。CSRF 攻击针对状态改变请求,而不是盗窃数据,因为攻击者无法查看对伪造请求的响应。
典型攻击方式:在 b.com 向 a.com 发送请求,会带上 a.com 的 cookie。
CSRF的特点
- 攻击一般发起在第三方网站,而不是被攻击的网站。
- 攻击利用受害者在被攻击网站的登录凭证,冒充受害者提交操作;而不是直接窃取数据。
- 整个过程攻击者并不能获取到受害者的登录凭证,仅仅是“冒用”。
- 跨站请求可以用各种方式:图片URL、超链接、CORS、Form提交等等。部分请求方式可以直接嵌入在第三方论坛、文章中,难以进行追踪。
防护策略
- 同源检测:通过 Origin Header 或 Referer Header 确定来源域名
- CSRF Token
- 双重Cookie验证
- Samesite Cookie属性:Samesite=Strict 表示 cookie 不可作为第三方 cookie
13. Cookie/Session/sessionStorage/localStorage/IndexDB
- Cookie 数据始终在同源的 HTTP 请求中携带(即使不需要),即 Cookie 在浏览器和服务器间来回传递。而 sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存。Cookie 数据还有路径(path)的概念,可以限制 Cookie 只属于某个路径下,存储的大小很小只有4K左右。
- sessionStorage 仅在当前浏览器窗口关闭前有效,localStorage 始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据,Cookie 只在设置的 Cookie 过期时间之前一直有效,即使窗口或浏览器关闭。
- localStorage 和 Cookie 在所有同源窗口中都是共享的。但是不同页面或标签页间无法共享 sessionStorage 的信息。
- IndexDB 是一个运行在浏览器上的非关系型数据库。理论上来说,IndexDB 是没有存储上限的(一般来说不会小于 250M)。它不仅可以存储字符串,还可以存储二进制数据。
- Session 是存储在服务器的键值对,一般把 SessionId 存在 Cookie 中,通过 SessionId 可以查找对应对象。
14. SSO 单点登录
前端鉴权的兄弟们:cookie、session、token、jwt、单点登录
cookie
在提供标记的接口,通过 HTTP 返回头的 Set-Cookie 字段,直接「种」到浏览器上;浏览器发起请求时,会自动把 cookie 通过 HTTP 请求头的 Cookie 字段,带给接口
- Domain / Path 限制 cookie 的域名/路径
- Expires / Max-Age 指定 cookie 的有效期
- Secure / HttpOnly Secure 属性指定浏览器只有在加密协议 HTTPS 下,才能将这个 Cookie 发送到服务器。HttpOnly 属性指定该 Cookie 无法通过 JavaScript 脚本拿到。
- HTTP 头对 cookie 的读写 一个 Set-Cookie 头用于向浏览器写入一条 cookie,设置多个 cookie 需要设置多条
Set-Cookie: username=jimu; domain=jimu.com; path=/blog; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
Session
- 用户登录,服务端把用户登录状态存为 Session,生成一个 sessionId,把 sessionId set 到 cookie 上
- session 存储方式,内存、数据库、Redis
Token
- 把登录信息加密存为 token,并 set 到 cookie 中,接口校验 token 有效性。
- JSON Web Token (JWT) 是一个开放标准,定义了一种传递 JSON 信息的方式。这些信息通过数字签名确保可信。
access token
用来访问业务接口,由于有效期足够短,盗用风险小,也可以使请求方式更宽松refresh token
用来获取access token
,有效期可以长一些,通过独立服务和严格的请求方式增加安全性;由于不常验证,也可以如前面的 session 一样处理
单点登录 (SSO, Single Sign On)
- 用户进入 A 系统,没有登录凭证(ticket),A 系统给他跳到 SSO
- SSO 没登录过,也就没有 sso 系统下没有凭证(注意这个和前面 A ticket 是两回事),输入账号密码登录
- SSO 账号密码验证成功,通过接口返回做两件事:一是种下 sso 系统下凭证(记录用户在 SSO 登录状态);二是通过一个带 code 的 URL 重定向到系统 A 的接口上,这个接口通常在 A 向 SSO 注册时约定
- 浏览器被重定向到 A 域下,带着 code 访问了 A 的 callback 接口,callback 接口通过 code 换取 ticket
- 这个 code 不同于 ticket,code 是一次性的,暴露在 URL 中,只为了传一下换 ticket,换完就失效
- callback 接口拿到 ticket 后,在自己的域下 set cookie 成功
- 客户端拿到 ticket,保存起来,带着请求系统 A 接口
- 系统 A 校验 ticket,成功后正常处理业务请求
- 此时用户第一次进入系统 B,没有登录凭证(ticket),B 系统给他跳到 SSO
- SSO 登录过,统一顺序访问 B 系统
15. 跨域问题
同源策略 SOP(Same origin policy)
同源指:协议相同、域名相同、端口相同。如果非同源,共有三种行为受到限制:
- Cookie、LocalStorage 和 IndexDB 无法读取。
- DOM 和 JS 对象无法获得
- AJAX 请求不能发送。
跨域解决方案
- JSONP
- WebSocket
- CORS
- 代理
跨域资源共享 CORS
浏览器将 CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
简单请求
满足下面两个条件的是简单请求:
- 请求方法是以下三种方法之一:HEAD、GET、POST
- HTTP的头信息不超出以下几种字段:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限于三个值
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
浏览器发现这次跨源AJAX请求是简单请求,就自动在头信息之中,添加一个 Origin
字段,用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
服务器返回:
Access-Control-Allow-Origin: *
表示接受的域名,*
表示任意域名Access-Control-Allow-Credentials: true
表示是否允许发送CookieAccess-Control-Expose-Headers
指定前端可以获取的返回头字段
withCredentials
如果前端要发送 cookie
需要指定
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
同时服务器需要设置 Access-Control-Allow-Credentials: true
且 Access-Control-Allow-Origin
不能为 *
。
非简单请求
不满足简单请求条件的为非简单请求。非简单请求的 CORS 请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest
请求,否则就报错。
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
服务端返回
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000 # 可选,用来指定本次预检请求的有效期,单位为秒