【面试梳理3】HTTP_4.28

275 阅读8分钟

注:以下内容为随手记,属于暂未成形的文章,请勿参考

网络基础

计算机网络体系结构分为3类

  • OSI体系
  • TCP/IP体系
  • 五层体系

计算机网络体系

TCP和UDP

TCP是面向连接的可靠的、基于字节流的传输协议

  • 面向连接:客户端和服务的传输数据前要经过3次握手,断开连接需要经过4次挥手
  • 可靠的;有状态的(记录发送了哪些数据、哪些被接受);可控的(网络变差和丢包时,自动调节发送速度或重发)
  • 字节流:UDP是基于数据包,TCP为了维护状态,将数据包变成字节流
协议TCPUDP
是否连接
是否可靠否,不适用流量控制是,使用流量控制
连接对象个数多个单个
传输方式报文字节流
首部开销
使用场景视频会议、直播文件传输

三次握手

确认双方都具有发送和接受的能力

SYN同步序列号

ACK确认号

seq序列号

  • 为了避免与先前连线的数据段混淆,当次连线建立时,产生各自的初始序列号
  • 连线建立时,透过 SYN,让两端的 TCP 必须进行ISN的交换同步

四次挥手

因为服务端在接收到FIN, 往往不会立即返回FIN, 必须等到服务端所有的报文都发送完毕了,才能发FIN。因此先发一个ACK表示已经收到客户端的FIN,延迟一段时间才发FIN

DNS

DNS协议提供的是一种主机名到 IP 地址的转换服务,就是我们常说的域名系统。是应用层协议,通常该协议运行在UDP协议之上,使用的是53端口号

DNS使用UDP协议主要是为了避免使用TCP协议时造成的连接延迟

递归查询

查询请求发出后,域名服务器代为向下一级域名服务器发出请求,最后向用户返回查询的最终结果。使用递归 查询,用户只需要发出一次查询请求

89356512-95168e80-d6f0-11ea-93aa-c4f59fd36942.png

迭代查询

查询请求后,域名服务器返回单次查询的结果。下一级的查询由用户自己请求。使用迭代查询,用户需要发出多次查询请求

89356522-99db4280-d6f0-11ea-9bf9-851b25bd16c3.png

HTTP协议

特点

  • 可靠,
  • 请求应答
  • 内容多样

缺点

  • 明文
  • 队头阻塞
  • 无状态

报文结构

起始行 + 头部 + 空行 + 实体

请求方法

  • GET请求数据
  • POST提交数据
  • PUT修改数据
  • DELETE删除数据
  • HEAD获取元信息
  • OPTIONS列出可用方法

GET和POST区别

  • 缓存角度,GET会被浏览器缓存,POST不会
  • 数据长度,GET2048字符
  • 安全性,GET在URL中,POST请求体中
  • 编码,GET只能是URL,POST不止
  • 可重复行,GET无害,POST不一定
  • GET包一次发出,POST分头和实体发送

状态码

  • 1XX 已接受将处理
    • 101 HTTP升级为WebSocket
  • 2XX 已成功处理
    • 204 响应头后没有 body 数据
  • 3XX 重定向
    • 301 永久重定向
    • 302 临时重定向
    • 304 协商缓存
  • 4XX 客户端错误
    • 400 请求错误
    • 401 未授权
    • 403 已阻止
    • 404 未找到
    • 405 方法不被允许
  • 5XX 服务端错误
    • 500 服务器内部错误
    • 502 网关问题

数据传输

定长

响应头设置Content-Length: 10字段

不定长

响应头设置Transfer-Encoding: chunked字段,Content-Length 字段会被忽略,基于长连接持续推送动态内容

大文件

HTTP1.1采用范围请求

Accept-Ranges: bytes
Content-Range: bytes 0-9/100

具体可以看下三元大佬的相关博客

HTTP/1.x

都无法实现状态管理和存在队头阻塞

注:队头阻塞指当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞

方法

  • 1.0 GET POST HEAD
  • 1.1 PUT DELETE OPTIONS

缓存

  • 1.0 Expires和Last-Modified
  • 1.1 Cache-Control和Etag

断点续传(大文件)

1.1中rang字段

队头阻塞

1.1 并发连接和域名分片

HTTP/2

TCP 的队头阻塞是在数据包层面,单位是数据包,前一个报文没有收到便不会将后面收到的报文上传给 HTTP

HTTP 的队头阻塞是在HTTP请求-响应层面,前一个请求没处理完,后面的请求就要阻塞住

二进制分帧

将原先的头部 + 实体部分拆成一个个二进制帧(Header帧、Data帧)

  • 通信双方都可以给对方发送二进制帧,这种二进制帧的双向传输的序列,也叫做,HTTP/2 用流来在一个 TCP 连接上来进行多个数据帧的通信,这就是多路复用的概念。
  • 不同ID的流是乱序的,相同ID的流是按顺序传输的,二进制帧到达后会将相同ID流的二进制帧进行组装。

头部压缩

头部字段占用较大空间,比如「User-Agent、Cookie、Accept、Server、Range」。2.0采用HPACK算法进行压缩,主要包括

  • 在服务器和客户端之间建立哈希表,将用到的字段存放在这张表中,那么在传输的时候对于之前出现过的值,只需要传索引给对方即可。
  • 对于整数和字符串进行哈夫曼编码,哈夫曼编码的原理就是先将所有出现的字符建立一张索引表,然后让出现次数多的字符对应的索引尽可能短,传输的时候也是传输这样的索引序列

服务器推送

以前是客户端请求,然后服务端再去应答。现在则是请求一个HTML文件,服务器就可以在返回HTML的基础上,将HTML中引用到的其他资源文件一起返回给客户端,减少客户端的等待。

HTTPS和HTTP/3

HTTPS

HTTPS = HTTP + SSL/TLS

利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。

TLS/1.2握手

89356430-58e32e00-d6f0-11ea-9320-115133c36e3e.png

HTTP/3

QUIC 基于 UDP 实现,是 HTTP/3 中的底层支撑协议,该协议基于 UDP,又取了 TCP 中的精华,实现了即快又可靠的协议

跨域

同源策略:访问相同协议、域名、端口的资源。

  • Ajax请求发送不出去
  • Cookie、LocalStorage和IndexDB无法读取
  • DOM和JS对象无法获取

JSONP

原理:利用<script>标签没有跨域限制,得到从其他来源动态产生的数据

特点:兼容性好,仅支持GET,存在XSS攻击的风险,前后端需同时支持

流程:

  • 创建一个回调函数A,他的形参用于接受目标服务器发送的数据
  • 创建一个script标签,将要跨域的API赋值给src属性,同时将回调A的函数名作为URL参数,(?callbakc=A)
  • 服务端把传递进来的函数名和它需要给你的数据拼接成一个字符串(A(data)),返回

实例:

// client
function jsonp({ url, params, callback }) {
  return new Promise((resolve, reject) => {
    let script = document.createElement('script')
    window[callback] = function (data) {
      resolve(data)
      document.body.removeChild(script)
    }
    params = { ...params, callback } // wd=b&callback=show
    let arrs = []
    for (let key in params) {
      arrs.push(`${key}=${params[key]}`)
    }
    script.src = `${url}?${arrs.join('&')}`
    document.body.appendChild(script)
  })
}
jsonp({
  url: 'http://localhost:3000/say',
  params: { name: 'admin' },
  callback: 'show'
}).then(data => {
  console.log(data)
});

// server
let express = require('express')
let app = express()
app.get('/say', function(req, res) {
  let { name, callback } = req.query
  console.log(name) // admin
  console.log(callback) // show
  res.end(`${callback}('Password')`)
})
app.listen(3000, () => {
  console.log('server is on http://localhost:3000')
})

CORS

原理:服务端通过HTTP头Access-Control-Allow-Origin来设置允许访问资源的条件

特点:主要依赖后端实现

浏览器自动在请求头当中,添加一个Origin字段,用来说明请求来自哪个源。服务器拿到请求之后,在回应时对应地添加Access-Control-Allow-Origin字段,如果Origin不在这个字段的范围中,那么浏览器就会将响应拦截

通过OPTIONS方法发送预检请求,先判断预检响应是否满足在进行请求

代理服务器/Nginx反向代理

同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略

原理:代理服务器接受客户端请求,并转发给目标服务器;目标服务器将响应发送给代理服务器,代理服务器再转发响应给客户端

websocket

原理:WebSocket和HTTP都是应用层协议,都基于TCP协议,实现浏览器与服务器的全双工通信

postMessage

原理:HTML5 API允许来自不同源的脚本采用异步方式进行有限的通信

// client
<iframe src="http://localhost:4000/b.html" frameborder="0" id="frame" onload="load()"></iframe>
<script>
  function load() {
    let frame = document.getElementById('frame')
    frame.contentWindow.postMessage('我爱你', 'http://localhost:4000') //发送数据
    window.onmessage = function(e) { //接受返回数据
      console.log(e.data) //我不爱你
    }
  }
</script>

// server
window.onmessage = function(e) {
  console.log(e.data) //我爱你
  e.source.postMessage('我不爱你', e.origin)
}

代理

正向代理

通过代理访问原本访问不到的,已知的服务器地址,同时代理可以对外隐藏用户信息。

用户 1
      \
用户 —— 代理 -> 服务器
      /
用户 3

实例:科学上网

反向代理

在客户端和服务器之间推出一个代理服务器,然后所有请求内容都经过代理服务器去管理。

用户 1               服务器 1
      \            /
用户 2 ->  总服务器 -> 服务器 2
      /            \
用户 3               服务器 3

实例:淘宝有一个总服务器,服务器里面有很多小服务器。用户访问的时候,就访问总服务器的地址(公网 IP),然后总服务器去分配具体的小服务器(私网 IP)去处理你的请求。

参考

网络安全

XSS

跨站脚本攻击。目标网站注入恶意脚本,访问时执行恶意脚本

存储型

恶意脚本存储在服务端,前后端没做好相关的过滤

反射型

诱导访问带有恶意代码的URL,打开URL后执行恶意代码

DOM型

诱导将含恶意代码的数据插入到DOM中时,被执行了恶意代码

注:内联事件监听器和链接跳转都能把字符串作为代码运行

防范措施:

  • 前后端对数据进行转义
  • Content Security Policy只允许加载同域下的资源
  • 输入内容限制,禁止特殊字符
  • HTTPOnly,禁止JavaScript访问Cookie

CSRF

跨站请求伪造。攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求

16abb8d5ab69386f.jpg

防范措施:

  • 核心操作如交易时,增加验证码校验
  • 判断请求来源,检测Referer
  • samesite属性,不允许第三方使用Cookie
  • 使用Token,服务端生成,客户端每次请求都携带

点击劫持

攻击者将需要攻击的网站通过 iframe 嵌套的方式嵌入自己的网页中,并将 iframe 设置为透明,在页面中透出一个按钮诱导用户点击

防范措施:

  • X-FRAME-OPTIONS

DDos

短时间内发起大量请求,耗尽服务器的资源,导致服务器宕机

  • 备份网站,仅提示作用
  • 带宽扩容
  • 源服务器前面有CDN。如果攻击域名,CDN可以挡住;如果直接攻击源服务器,我买了弹性IP,可以动态挂载主机实例,受到攻击就换一个地址

参考