主题
HTTP状态码
HTTP状态码主要分为以下五类:
1xx - 信息响应状态码
2xx - 成功状态码
3xx - 重定向状态码
4xx - 客户端错误状态码
5xx - 服务器错误状态码
200
OK 正常返回信息- 201 Created 请求成功并且服务器创建了新的资源
- 202 Accepted 服务器已接受请求,但尚未处理
- 301 Moved Permanently 请求的网页已永久移动到新位置
- 302 Found 临时性重定向
- 303 See Other 临时性重定向,且总是使用 GET 请求新的 URI
304
Not Modified 自从上次请求后,请求的网页未修改过400
Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求401
Unauthorized 请求未授权403
Forbidden 禁止访问404
Not Found 找不到如何与 URI 相匹配的资源500
Internal Server Error 最常见的服务器端错误503
Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)
什么是跨域?
跨域本质是浏览器基于同源策略
的一种安全手段。协议
(protocol), 主机
(host), 端口
(port)相同。
- JSONP
- CORS (Access-Control-Allow-Origin)
- 反向代理
- WebSocket
- Nginx 反向代理
- nodejs中间件代理(webpack 设置 devServer 中的 proxy)
- postMessage
- document.domain + iframe
- location.hash + iframe
- window.name + iframe
跨域时怎么处理 cookie?
客户端设置
withCredentials
属性:withCredentials:true服务端处理
CORS(跨域资源共享)
请求
js
response.setHeader('Access-Control-Allow-Origin', 'http://example.com');
response.setHeader('Access-Control-Allow-Credentials', 'true');
cookie 怎么设置只在 https 时携带?
设置 cookie 的 secure
属性,secure 选项用来设置 cookie 只在确保安全的请求
中才会发送。当请求是 HTTPS 或者其他安全协议时,包含 secure 选项的 cookie 才能被发送至服务器。默认情况下,cookie不会带 secure 选项(即为空)。所以默认情况下,不管是 HTTPS 协议还是 HTTP 协议的请求,cookie 都会被发送至服务端。
常见的 HTTP 请求方法
- GET: 向服务器获取数据
- POST:将实体提交到指定的资源,通常会造成服务器资源的修改。
- PUT:上传文件,修改数据
- DELETE:删除服务器上的对象
- HEAD:获取报文首部,与GET相比,不返回报文主体部分
- OPTIONS:询问支持的请求方法,用来跨域请求
- TRACE:追踪 请求—响应 的传输路径
- CONNECT:要求在与代理服务器通信时建立隧道,使用隧道进行TCP通信
session ?
HTTP Session 是 Web 应用程序中用于跟踪用户会话状态
的一种机制。在用户与 Web 应用程序进行交互的过程中,HTTP Session 允许服务器存储
和检索
关于特定用户
的信息,以便在多个请求之间保持状态
。
HTTP 本身是一种无状态
的协议,意味着每个请求
都是独立
的,服务器不会记住之前的请求或用户
。然而,在 Web 应用程序中,经常需要跟踪用户的身份、偏好、购物车内容等信息,以便提供个性化的体验。这时,就需要使用 HTTP Session 来实现会话状态的跟踪
。
HTTP Session 的工作原理如下:
- 会话创建:当用户首次访问 Web 应用程序时,
服务器会创建
一个新的 HTTP Session 对象,并为其分配一个唯一的会话标识符
(session ID)。这个会话标识符通常通过Cookie
机制发送给客户端,保存在用户的浏览器中。 - 会话维护:在后续的请求中,客户端会将会话标识符包含在
请求头
中发送给服务器。服务器通过解析请求头中的会话标识符,可以找到对应的 HTTP Session 对象,从而获取
和更新
用户的会话状态。 - 会话数据存储:HTTP Session 对象可以存储各种类型的数据,如用户身份、购物车内容、访问历史等。这些数据可以在
多个请求
之间共享
和更新
。 - 会话销毁:当用户
关闭浏览器
或会话超时
时,服务器会销毁相应的 HTTP Session 对象,释放
相关资源。
HTTP Session 依赖于 Cookie
机制来实现会话标识符的传递。因此,如果客户端禁用了 Cookie,或者使用的是不支持 Cookie 的 HTTP 客户端(如某些命令行工具),那么 HTTP Session 将无法正常工作。此外,由于 HTTP Session 数据存储在服务器端,因此在大规模并发场景下可能会对服务器性能产生一定影响。在实际开发中,为了减轻服务器压力并提高性能,可以将会话数据存储在分布式缓存
中、使用 Token
认证机制替代传统的 Session 机制等。
什么是 XSS 攻击?如何预防?
跨站脚本攻击
(XSS, Cross-Site Scripting),是攻击者通过在页面中插入恶意脚本
,利用用户浏览器对页面的信任,获取用户的敏感信息或进行其他恶意操作。
XSS攻击通常分为:
- 将用户提交的恶意脚本
存储在服务器端
,当受害者访问该页面时,恶意脚本会被执行; - 将恶意脚本
作为参数传递给服务器端
,服务器端将恶意脚本反射到页面中,当受害者访问该页面时,恶意脚本被执行; - 恶意脚本
修改
了页面中的DOM
结构
为了预防XSS攻击,可以采取以下几种方法:
输入合法性验证
转义特殊字符
设置 HTTP 头部
:设置 HTTP 头部,包括Content-Security-Policy
、X-Content-Type-Options
、X-XSS-Protection
等,来使浏览器拦截来自第三方资源的恶意脚本。使用脚本过滤器
:使用脚本过滤器,如 Google 的Closure Library和 jQuery 库等,能够对来自用户的数据进行过滤和检查。使用 HttpOnly cookie
:限制 Cookie 只能在 HTTPS 连接下使用,并使用HttpOnly
标识确保 Cookie 不能通过 JavaScript 代码访问。
什么是 CSRF 攻击?如何预防?
跨站请求伪造
(CSRF
, Cross-Site Request
Forgery)攻击,是一种常见的网络安全威胁。这种攻击利用用户在目标网站上已经认证的身份
,在用户不知情的情况下,构造恶意请求
并冒充用户身份
向目标网站发起请求。由于请求包含了用户的认证信息,如 Cookie 等,服务器会误认为这些请求是用户自己发起的,从而执行攻击者的恶意操作。这些操作可能包括更改用户的密码、发出支付请求、删除重要数据等。
为了预防 CSRF 攻击,可以采取以下几种常见的防范措施:
随机令牌
:发送请求,携带一个Token,校验 Token 有效性,无效拒绝- 检查
Referer
: 判断 Referer 字段是否和请求的地址位于同一域名下 - Cookie策略:一些浏览器(如IE6、7、8和Safari)默认会拦截第三方本地 Cookie 的发送。利用这一特性,可以减少 CSRF 攻击的风险。
添加验证码
:对于敏感操作,可以添加验证码机制。这样即使攻击者构造了恶意请求,用户也需要输入正确的验证码才能完成操作,增加了攻击的难度。- 使用安全的 HTTP 方法:尽量使用安全的 HTTP 方法,如 POST、PUT 等,来执行敏感操作,而不是使用 GET 方法。
简述一下三次握手
SYN(客户端,Synchronize, 初始序列号) -> SYN-ACK(服务器, Acknowledgment)-> ACK(客户端)
TCP 三次握手是建立 TCP 连接的一个过程,其目的是在客户端和服务器之间建立一个可靠的连接,以便进行数据传输。以下是三次握手的基本步骤:
SYN(同步)阶段:
- 客户端向服务器发送一个 SYN 包(Synchronize Sequence Numbers),包含客户端的
初始序列号
,SYN 包的作用是请求服务器建立连接
- 客户端向服务器发送一个 SYN 包(Synchronize Sequence Numbers),包含客户端的
SYN-ACK(同步应答)阶段:
- 服务器收到 SYN 包后,会回应一个 SYN-ACK 包。这个包包含服务器的初始序列号和对客户端初始序列号的确认。SYN-ACK 包的作用是确认收到客户端的连接请求,并请求客户端建立连接。
ACK(应答)阶段:
- 客户端收到 SYN-ACK 包后,会再次发送一个 ACK 包。这个包包含对服务器初始序列号的确认。当服务器收到这个 ACK 包后,连接就正式建立了。
优点:
确保通信正常
- 在进行数据传输之前,客户端发起连接请求,服务器回应确认,再由客户端发送确认,这样可以确保双方的发送和接收能力都正常。如果只进行两次握手,客户端虽然能够确认自己的发送能力和服务器的接收能力正常,但无法确认服务器的发送能力和客户端的接收能力是否正常。
避免旧连接的延迟影响
- 在网络中,请求可能会由于网络拥塞或其他原因而延迟。如果只有两次握手,客户端可能会认为连接已建立,但服务器并不知情。当客户端再次发送数据时,服务器可能会拒绝或丢弃这些数据,因为它并没有建立有效的连接。
防止建立重复连接
- 在网络延迟的情况下,如果只有两次握手,客户端可能认为连接未建立,因此发送新的连接请求。如果服务器接收到了两个连接请求,并回应确认,就会建立两个相互独立的连接。这可能导致资源浪费和数据混乱。
简述一下四次挥手
四次挥手是 TCP 协议中用于终止连接
的一个过程。当数据传输完成后,通信的双方都可以主动发起断开连接的请求。步骤:
第1次挥手:主动关闭方(客户端)发送一个 FIN 包,表示数据已经发送完毕,现在请求断开连接。此时,主动关闭方进入 FIN_WAIT_1 状态,等待被动关闭方的确认。
第2次挥手:被动关闭方(服务器)收到 FIN 包后,发送一个 ACK 包作为应答,表示同意断开连接请求。此时,被动关闭方进入 CLOSE_WAIT 状态,而主动关闭方收到这个 ACK 包后,会进入 FIN_WAIT_2状态,等待被动关闭方的 FIN 包。
第3次挥手:当被动关闭方也完成数据发送后,会发送一个 FIN 包,表示自己也准备断开连接。此时,被动关闭方进入 LAST_ACK 状态,等待主动关闭方的 ACK 包。
第4次挥手:主动关闭方收到 FIN 包后,发送一个 ACK 包进行确认。此时,主动关闭方进入 TIME_WAIT 状态,等待一段时间后(通常是2MSL,即最大报文生存时间),确保被动关闭方收到了最后的 ACK 包。如果在这段时间内没有收到被动关闭方的重传请求,那么主动关闭方就会关闭连接,进入 CLOSED 状态。而被动关闭方在收到最后的 ACK 包后,也会直接关闭连接,进入 CLOSED 状态。
四次挥手的目的是确保双方都能够正确地关闭连接
,释放相关的资源
。在这个过程中,每个方向都需要一个 FIN 包和一个 ACK 包,因此总共有四次通信,即"四次挥手"。
从存储位置看,浏览器缓存分为哪几种?
本地磁盘缓存:这是最常见的浏览器缓存形式。当您访问一个网页时,浏览器会将已访问的网页、图像和其他文件缓存到本地磁盘上。这样做的目的是为了在以后的访问中加快加载速度,减少从服务器重新获取数据的时间。
浏览器内置缓存:除了本地磁盘缓存外,浏览器还提供了内置缓存机制,如 HTTP 缓存。HTTP 缓存是基于 HTTP 协议的浏览器文件级缓存机制,它通过设置 Cache-Control、Expires 等响应头来实现。当浏览器再次请求相同的资源时,如果缓存中的资源仍然有效,浏览器会直接从本地缓存中读取资源,而不是从服务器重新获取。
应用程序缓存:对于某些应用程序,它们可能会在本地存储临时文件或缓存数据。这些缓存数据的存储位置可能因应用程序而异,但通常也是为了加快数据访问速度和提高用户体验。
Service Worker缓存:Service Worker 是一种特殊的JS脚本,它可以
拦截网络请求并返回缓存的响应
。Service Worker 并不直接存储数据,但它能够管理缓存资源的获取和更新,从而实现离线访问和更快的加载速度等功能。Web Storage缓存:这包括
localStorage
和sessionStorage
两种形式。它们提供了在浏览器端存储数据的能力,通常用于存储ajax返回的数据,以加快页面渲染速度。虽然这些数据不是传统意义上的“缓存”,但它们确实起到了缓存的作用,减少了从服务器获取数据的需要。
强缓存 Cache-Control 头有哪些常见配置值?
常见配置值主要有以下几种:
public:响应可以
被任何缓存区缓存
,包括浏览器和CDN等。即使响应中包含了HTTP认证或响应状态码(如404)表明响应不应该被缓存,使用public指令后该响应也可能会被缓存。private:响应只能被
单个用户缓存
,比如在一个特定的浏览器中。它不能被共享或被中间代理服务器缓存。no-cache:
每次请求都需要向服务器进行验证
,确认返回的响应是否已被更改。这并不意味着响应不会被缓存,而是每次都需要验证其有效性
。no-store:响应在任何情况下都
不会被缓存
,也不会写入到客户端的磁盘中
。这是基于安全考虑的,某些敏感的响应会使用这个配置。max-age:这个值指定了
缓存的最大有效时间
,单位是秒。从服务器返回的时间开始计算,如果在这个时间范围内,缓存的数据将被使用,而不会重新从服务器请求。
说说 WebSocket 和 HTTP 的区别
协议类型与通信方式:
- WebSocket 是
全双工通信
,双方都可以主动向对方发送和接收信息 - HTTP 则是一种
单向
的通信协议,通常是由客户端发起请求
- WebSocket 是
连接建立与维护:
- WebSocket在建立连接时,需要通过握手过程在浏览器和服务器之间建立持久性的连接,可以持续进行数据传输,直到
显式关闭
。 - HTTP 则是
短连接
,每次请求-响应完成后,连接就会断开
- WebSocket在建立连接时,需要通过握手过程在浏览器和服务器之间建立持久性的连接,可以持续进行数据传输,直到
协议状态与无状态性:
- WebSocket 是有
状态
的协议,服务器可以主动向客户端推送数据 - HTTP 是
无状态
的协议,每次通信完成后,连接断开
- WebSocket 是有
协议开头:
- WebSocket 的协议开头通常以
ws、wss
- HTTP 的协议开头则是
http、https
- WebSocket 的协议开头通常以
应用场景:
- WebSocket 适用于在线聊天、实时股票行情等(实时通信、频繁数据交换、服务端推送)
- HTTP 适用于简单的请求-响应模式,如网页浏览、文件下载等
https 的握手过程
客户端发起请求:客户端发送请求时,会将
支持的加密算法
、SSL/TLS版本
以及其他相关信息一并发送到服务器服务器应答:服务器收到客户端请求后,会向客户端发送一个
数字证书
,其中包含了服务器的公钥
、证书
的有效期
、证书的颁发机构
等信息客户端验证证书:客户端会对
证书进行验证
,查看证书是否过期
、是否被撤销
,验证证书颁发机构的可信度
等客户端生成密钥:客户端会生成密钥,并用服务器的
公钥
进行加密
,然后发送给服务器。服务器解密密钥:服务器使用自己的私钥对接收到的加密的密钥进行解密,得到客户端生成的对称加密密钥。
交换 Finished 信息:客户端和服务器使用之前协商好的算法和密钥,各自生成一串随机数据,并使用对方的公钥进行加密,然后交换这串数据。这样可以确保双方都正确地生成了密钥,并且密钥没有被篡改。如果任何一方在解密过程中发现
数据不一致
,那么就会断开连接。加密通信:客户端和服务器都拥有了相同的对称加密密钥,他们会使用该密钥对后续的通信进行加密和解密,保证了数据的安全性。
握手结束:客户端和服务器完成了密钥的交换和加密通信的建立,握手过程结束,之后的通信都是在该加密通道上进行。
HTTPS 为什么是安全的?
数据加密:HTTPS 使用
TLS(Transport Layer Security)
协议对传输的数据进行加密。这意味着通过 HTTPS 传输的数据在发送和接收过程中会被加密,使得攻击者很难在传输过程中截获、窃听或篡改数据。相比之下,HTTP 传输的数据是明文的,容易被拦截和解读。身份认证:HTTPS 使用
SSL证书
来验证服务器的身份
。当浏览器与服务器建立HTTPS连接时,服务器会向浏览器发送一个证书,证书包含了服务器的公钥
。浏览器会验证证书的合法性,以确保用户连接的是合法的服务器,而不是恶意伪装的网站。这种身份认证机制有助于防止中间人攻击和其他类型的欺诈行为。数据完整性:HTTPS不仅加密了数据,还提供了
数据完整性
的保证。这意味着数据在传输过程中不会被篡改
,因为篡改后的数据在解密时会无法通过完整性验证。这种机制确保了用户接收到的数据是完整且未经篡改的。信任与SEO:HTTPS 提供了更高的安全性,使用 HTTPS 的网站会得到
用户和搜索引擎的更高信任
。
HTTP2中,多路复用的原理是什么?
HTTP/2 中的多路复用(Multiplexing)原理主要基于以下几个核心概念:
二进制分帧层:协议将 HTTP 消息分解为更小的
帧(frames)
,并在一个单一的连接上交错发送这些帧。这种设计使得同一连接上的多个请求和响应可以并行处理,而不需要等待前一个请求或响应完成。流(Streams):每个请求或响应都被视为一个
独立的流
,每个流都有一个唯一的标识符
。服务器可以并发地处理多个流,不需要按照请求到达的顺序来处理。优先级(Priorities):允许客户端为每个流设置
优先级
。当服务器资源受限,可以使用这些优先级来决定首先处理哪些流流量控制(Flow Control):提供了
流量控制
机制,允许接收端控制发送端发送数据的速率
通过这些机制,HTTP/2 实现了多路复用,即在一个单一的 TCP 连接上并行处理多个请求和响应
。这极大地提高了网络资源的利用率和应用的性能。与 HTTP/1.1 相比,HTTP/2 不再需要为每个请求建立新的 TCP 连接,从而减少了连接建立和关闭的开销
,提高了整体性能。
为什么推荐将静态资源放到 CND 上?
将静态资源放到CDN(Content Delivery Network,内容分发网络
)上有多个优势,理由如下:
提高访问速度和用户体验:CDN 在多个节点上缓存静态资源,用户可以就近获取内容,减少数据传输的距离和时间,
提高网站的加载速度
。减轻源服务器负载:将静态资源缓存在 CDN 节点上,可以
减轻源服务器的负载
压力。CDN 节点能够处理大量的用户请求,分担源服务器的工作量。提供高可用性和容错性:CDN 部署了多个节点,当某个节点出现故障或网络中断时,用户仍然可以从其他可用的节点获取内容,保证网站的高可用性和
容错性
,降低了服务中断风险。节省带宽成本:网站将静态资源缓存在 CDN 边缘节点,降低主服务器的带宽使用量。
优化全球访问体验:CDN 针对不同地区和运营商进行优化,确保用户无论身处何地都能获得良好的访问体验。
什么是DNS劫持?
DNS劫持,也称为域名重定向
。攻击者通过攻击域名解析服务器
或伪造域名解析服务器
,将目标网站的域名解析为错误的IP地址,使用户无法访问目标网站,或故意或恶意要求用户访问指定的IP地址。
DNS劫持主要有四种基本类型:
- 本地DNS劫持:攻击者在用户计算机上安装木马恶意软件,并更改本地 DNS 设置,将用户重定向到恶意站点。
- 路由器DNS劫持:由于路由器密码泄露或固件错误,攻击者可以接管路由器并重置DNS地址,这将影响所有连接到路由器的用户。
- 中间人(MITM)DNS攻击:攻击者拦截用户与DNS服务器之间的通信,并向恶意站点提供不同的目标IP地址。
- 流氓DNS服务器:攻击者通过入侵DNS服务器并更改DNS记录,将DNS请求重定向到恶意站点,从而实现DNS劫持。
为了防止 DNS 劫持,建议:
- 使用
可信赖
的 DNS 服务器 - 实施
DNS SEC
更新
DNS 软件- 使用 DNS
防火墙
- 增强
网络安全
HTTP 报文结构是怎样的 ?
HTTP报文结构主要由请求
报文和响应
报文构成,这两者分别由客户端
和服务器
在HTTP通信过程
中产生。
请求报文的结构主要包括请求行
、请求头部
和请求主体
。
- 请求行包含了
请求方法
、目标URL
和协议版本
,这三部分以空格分隔并以回车换行符结束。请求方法如GET、POST等,用于指示请求的具体操作类型。目标URL则指示了请求的目标资源位置
- 请求头部包含了
关于请求的附加信息
,如请求的附加参数、客户端信息等 - 请求主体则包含了
应被发送的数据
,但并非所有请求报文都包含请求主体
响应报文的结构则主要包括状态行
、响应头部
和响应主体
。
- 状态行包含了
协议版本
、状态码
和状态码的原因短语
,用于描述请求的处理结果 - 响应头部与请求头部类似,包含了关于响应的附加信息
- 响应主体则包含了
响应的具体内容
。
POST请求的 Content-Type 常见的有哪几种?
- application/x-www-form-urlencoded:用于普通的 HTML 表单提交,在请求正文中将表单字段编码为键值对。
multipart/form-data
:用于上传文件或二进制数据的表单提交,请求正文以多部分形式进行编码。application/json
:用于发送 JSON 格式的数据,请求正文中的数据将以 JSON 形式进行传输。text/plain
:纯文本格式,适用于发送纯文本数据。- application/xml:用于发送 XML 数据。
text/html
:用于发送 HTML 数据。- application/octet-stream:用于发送二进制数据,如文件下载时使用。
- application/graphql:用于发送 GraphQL 查询或请求。
- application/x-www-form-urlencoded;charset=UTF-8:类似于 application/x-www-form-urlencoded,但指定了字符编码为 UTF-8。
- 其他自定义的 Content-Type 类型。
URI、URL、URN分别是什么?
URL代表资源的路径地址
,而 URI 代表资源的名称
。
URI(Universal Resource Identifier):
统一资源标志符
; 用来标识网络资源,指定了操作或获取方式,同时包含访问机制和网络位置。URL(Universal Resource Locator):
统一资源定位符
;URN(Universal Resource Name):
统一资源名称
; 用特定命名空间的名字标识资源。包括名字(给定的命名空间),但不包含访问方式。
URL 和 URN 都是 URI 的子集。
Blob,ArrayBuffer,Base64
Blob: Blob是一种表示二进制数据的对象
,可以存储大量的数据。它常用于处理文件、图像、音频和视频等媒体数据
。Blob对象可以通过new Blob()构造函数创建,也可以从其他数据源(例如,通过XMLHttpRequest下载的数据)生成。Blob提供了一些方法和属性,用于读取和操作二进制数据。
- 文件上传和下载:Blob对象可以用于将文
件数据存储为二进制形式
,并进行上传或下载操作。 - 图片处理:可以将图像数据存储为Blob对象,并进行处理、显示或上传。
- 多媒体处理:可用于处理音频和视频等多媒体数据。
- 生成临时URL:可以使用Blob对象创建临时URL,用于在浏览器中显示或分享文件。
ArrayBuffer:ArrayBuffer是一种用于表示通用的二进制数据缓冲区的对象
。它在内存中分配一块连续的、固定大小的原始二进制数据,并提供了一些方法和属性来读取和操作这些数据。ArrayBuffer不直接访问二进制数据,而是通过TypedArray视图或DataView对象来读写数据。
- 图像处理:可以使用ArrayBuffer来处理图像数据,例如图像解码、图像滤镜等操作。
- 网络请求:可用于处理二进制数据的网络请求,例如WebSocket通信或二进制协议的数据传输。
- 数据加密:ArrayBuffer可以用于加密算法的处理和操作。
- Web Workers:ArrayBuffer可用于在Web Worker中进行多线程数据处理。
Base64: Base64是一种将二进制数据转换为可打印字符的编码方式
。它通过将二进制数据按照一定规则进行编码,生成由A-Z、a-z、0-9和一些特殊字符组成的字符串。Base64编码后的数据可以用于在文本协议中传输二进制数据,例如在网络请求中传递图片数据或在HTML中嵌入图片。
- 图片嵌入:Base64编码可以将图片数据转换为字符串,可用于将图片嵌入到HTML、CSS或JavaScript中,减少网络请求。
- 图片传输:在文本协议中,如JSON或XML,可以使用Base64编码将图片数据传输到服务器或其他系统。
- 数据URL:可以将Base64编码的数据作为数据URL嵌入到HTML中,用于显示图像或其他媒体内容。
- 数据存储:某些浏览器API或本地存储机制支持Base64编码的数据存储。
区别:
- Blob 和 ArrayBuffer 都是用于
表示和处理二进制数据的对象
,但Blob通常用于处理大量数据和文件,而 ArrayBuffer 用于处理更小粒度的数据。 - Blob 对象提供了一些方法和属性,用于操作和读取二进制数据,而 ArrayBuffer 本身并不直接提供数据访问方法,需要通过
TypedArray
视图或DataView
对象来读写数据。 - Base64 是一种
编码方式
,用于将二进制数据转换为可打印字符
,以便在文本协议中传输。Base64 编码后的数据可以作为字符串
进行处理,而 Blob 和 ArrayBuffe r是二进制
数据的对象表示。
TCP 和 UDP 的区别是什么?
TCP(Transmission Control Protocol,传输控制协议
)和 UDP(User Datagram Protocol,用户数据报协议
)都是应用于传输层的网络协议
,它们各自有着不同的特点和适用场景。
适用场景:
- TCP 适用于对可靠性要求较高的应用场景,如
文件传输
、邮件
传输等 - UDP 适用于实时性要求较高的应用场景,如
语音
、视频
、游戏
等
- TCP 适用于对可靠性要求较高的应用场景,如
连接方式:
- TCP 是面向连接的协议,需要在
通信前建立连接
- UDP 是无连接的协议,可以
直接发送数据包
- TCP 是面向连接的协议,需要在
可靠性
- TCP 保证传输数据的可靠性,能够保证所有数据到达目的地且
顺序正确
- UDP 不保证传输数据的可靠性,可能会出现
数据丢失
或乱序
等问题
- TCP 保证传输数据的可靠性,能够保证所有数据到达目的地且
开销:
- TCP 在传输过程中要维护连接状态、进行流量控制、拥塞控制等操作,因此
开销较大
- UDP 没有这些机制,传输
开销较小
- TCP 在传输过程中要维护连接状态、进行流量控制、拥塞控制等操作,因此
速度:
- TCP 需要保证数据的可靠性,因此传输速度可能会
受到一定的影响
- UDP 没有这个限制,
传输速度快
- TCP 需要保证数据的可靠性,因此传输速度可能会
websocket 的连接原理
WebSocket 的连接主要基于 HTTP 协议的升级机制
,通过一次握手实现持久化的全双工通信
。以下是详细的连接原理:
握手阶段*:
- 客户端发起连接请求:客户端通过 HTTP 请求方式向服务器发送连接请求。这个请求中包含了 WebSocket 协议版本号、握手密匙等信息,以及一个关键字段
Upgrade
,其值为websocket
,表明客户端希望将连接协议从 HTTP 升级为 WebSocket。 - 服务器响应:服务器接收到请求后,会进行验证。如果验证成功,服务器会返回一个状态码为
101
的 HTTP 响应,表示握手成功,并同意将协议升级为 WebSocket。响应头中也会包含Upgrade
和Connection
字段,告知客户端协议已成功升级。
- 客户端发起连接请求:客户端通过 HTTP 请求方式向服务器发送连接请求。这个请求中包含了 WebSocket 协议版本号、握手密匙等信息,以及一个关键字段
连接建立:
- 握手成功,客户端和服务器之间的 WebSocket 连接建立持久化成功, 不需要每次通信都重新建立连接和断开连接。
双向通信:
- 连接建立,客户端和服务器都可以通过 WebSocket 发送和接收数据。这种双向通信的特性使得实时数据的传输成为可能。客户端和服务器都可以主动向对方发送信息,无需等待对方的请求。
保持连接:
- WebSocket 连接是持久化的,这意味着连接在建立后会保持打开状态,直到显式关闭。这种持久性连接减少了网络开销和延迟,使得实时通信更加高效。
在WebSocket连接中,服务器可以主动向客户端推送数据,这解决了传统 HTTP 协议中服务器被动性的问题。同时,WebSocket使用单一的 TCP 连接进行全双工通信,避免了传统 HTTP 协议需要建立多个连接的缺陷。WebSocket还提供了诸如心跳检测
、断线重连
等机制,以确保连接的稳定性和可靠性。这些机制使得 WebSocket 成为实现实时通信、在线游戏、聊天应用等场景的理想选择。
HTTP1.0,HTTP1.1,HTTP2.0之间有什么区别 ?
连接方式:
- HTTP1.0使用
短连接
,即每次请求/响应后都会关闭连接。这意味着每次请求都需要进行TCP握手,可能导致大量延迟。 - HTTP1.1则默认使用
持久连接
,允许在同一个连接上发送多个请求和响应,减少了连接建立和断开的开销。 - HTTP2.0进一步
支持多路复用
,可以在一个TCP连接上并发多个请求或响应,从而提高了客户端的响应速度。
- HTTP1.0使用
数据格式:
- HTTP1.0的数据是
文本格式
,虽然方便阅读,但不利于传输和解析。 - HTTP2.0则采用了
二进制格式
,有效地减少了数据传输量,提高了数据传输的可靠性,并且不易出错。
- HTTP1.0的数据是
头部压缩:
- HTTP1.0的
请求头部信息是明文
,可能导致大量的冗余数据。 - HTTP2.0则对请求头部进行了压缩,减少了数据传输量,并使用
HPACK
去除了冗余的头部字段。
- HTTP1.0的
缓存处理:
- HTTP1.0的缓存处理相对简单,主要使用 header 里的
If-Modified-Since
和Expires
来做为缓存判断的标准。 - HTTP1.1则引入了更多的缓存控制策略,如
Entity tag
、If-Unmodified-Since
、If-Match
、If-None-Match
等,提供了更多可供选择的缓存头来控制缓存策略。
- HTTP1.0的缓存处理相对简单,主要使用 header 里的
请求管道化**:
- HTTP1.1支持
请求管道化
,即在一个持久连接上可以同时发送多个请求,而HTTP1.0不支持这一特性。
- HTTP1.1支持
服务器推送:
- 在HTTP1.0中,客户端需要明确请求服务器才能获取资源。而 HTTP2.0 允许服务器主动向客户端推送资源,提高了资源获取的效率和用户体验。
你知道哪些应用层协议?
- 超文本传输 Http、Https
- 文本传输:FTP
- 电子邮件:SMTP、POP3、IMAP
- 动态主机配置:DHCP
- 域名系统:DNS
说说对 TCP/IP 协议的了解?
TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同网络间实现信息传输的协议簇
。指一个由 FTP、SMTP、TCP、UDP、IP等协议构成的协议簇。
TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。这4层分别为:
应用层
: 应用程序间沟通的层,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等。传输层
: 在此层中,它提供了节点间的数据传送,应用程序之间的通信服务,主要功能是数据格式化、数据确认和丢失重传等。如传输控制协议(TCP)、用户数据报协议(UDP)等,TCP和UDP给数据包加入传输数据并把它传输到下一层中,这一层负责传送数据,并且确定数据已被送达并接收。网络层
: 负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机(但不检查是否被正确接收),如网际协议(IP)。数据链路层
: 接收IP数据报并进行传输,从网络上接收物理帧,抽取IP数据报转交给下一层,对实际的网络媒体的管理,定义如何使用实际网络(如Ethernet、Serial Line等)来传送数据。
HTTP 中如何处理表单数据的提交?
- application/x-www-form-urlencoded
js
// 其中的数据会被编码成以&分隔的键值对
// 字符以URL编码方式编码。
{a: 1, b: 2} -> a=1&b=2 -> "a%3D1%26b%3D2"
- multipart/form-data
sh
/*
请求头中的 Content-Type 字段会包含 boundary ,且 boundary 的值有浏览器默认指定。例: Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe。
*/
/*
数据会分为多个部分,每两个部分之间通过分隔符来分隔,每部分表述均有 HTTP 头部描述子包体,如Content-Type,在最后的分隔符会加上--表示结束。
*/
Content-Disposition: form-data;name="dataA";
Content-Type: text/plain
dataA
----WebkitFormBoundaryRRJKeWfHPGrS4LKe
Content-Disposition: form-data;name="dataB";
Content-Type: text/plain
dataB
----WebkitFormBoundaryRRJKeWfHPGrS4LKe--
为什么说 HTTP 是无状态的协议?
请求完全独立的
,每个请求包含了处理这个请求所需的完整的数据
优点:
- 在于
解放了服务器
,每一次请求不会造成不必要连接占用 - 请求独立,不会互相影响;
缺点:
- 每次请求会传输大量
重复信息
- 不会记住用户状态(cookie, session)
对于定长和不定长的数据,HTTP 是怎么传输的?
定长包体:
- 发送端在传输的时候一般会带上
Content-Length
,来指明包体的长度。
不定长包体:
Transfer-Encoding: chunked
, 表示分块传输数据,设置这个字段后会自动产生两个效果: Content-Length 字段会被忽略; 基于长连接持续推送动态内容。
Cookie 属性
- 名称(Name)
- 这是 cookie 的标识符,用于在客户端和服务器之间传递数据。
- 值(Value)
- 与 cookie 关联的值,可以是任何字符串。
- 域(Domain)
- 指定可以访问 cookie 的域名。如果未设置,则默认为创建 cookie 的网页的域名。
- 路径(Path)
- 定义了 cookies 只发给指定的路径请求。如果 Path 属性没有被设置,则使用应用软件的缺省路径。
- 过期时间(Expires)
- 指定 cookie 的过期时间,即 cookie 将被自动删除的时间点。这个属性可以用来给 cookies 设置一个期限,在期限内只要打开网页就可以调用被保存的 cookies。如果一个 cookies 没有设定有效期,则其生命周期从打开浏览器开始,到关闭浏览器结束,每次运行后生命周期将结束,下次运行将重新开始。
- 安全标志(Secure)
- 表示该 cookie 只能通过加密协议(如HTTPS)传输
- 标志(HttpOnly)
- JavaScript 的 document.cookie 无法在客户端获取到cookie信息,从而有效防止XSS攻击
Cookie的优点和缺点如下:
优点:
- 会话管理:能够管理用户的会话状态,为每个用户分配一个
唯一的会话ID
并将其存储在 Cookie 中,服务器可以识别并跟踪用户的活动,从而为用户提供连续和个性化的体验。 - 跨请求数据传递:允许
在不同页面之间传递数据
,这对于维护用户状态、记住用户偏好或跟踪用户行为非常有用。 - 无需服务器端存储:由于 Cookie 存储在客户端,因此不需要在服务器上为每个用户存储大量数据。这有助于减轻服务器的负担,并减少与数据库交互的需求。
- 易于实现:Cookie的创建、读取和修改相对简单,大多数 Web 编程语言和框架都提供了内置的支持。
- 会话管理:能够管理用户的会话状态,为每个用户分配一个
缺点:
- 安全问题:如果 Cookie
未加密
或未正确设置安全属性
,它们可能会被恶意用户截获或篡改,从而导致用户数据的泄露
或会话劫持
等安全问题。 隐私问题
:Cookie可以记录用户的访问行为、偏好和其他个人信息,这引发了隐私方面的担忧。大小限制
:Cookie的大小通常受到浏览器和服务器的限制。- 用户清除:
用户可以随时清除浏览器中的Cookie
,这可能导致网站失去用户的会话状态和其他重要数据。 - 跨域问题:出于安全考虑,浏览器通常限制不同域名之间的 Cookie 共享。这可能导致在涉及多个域名的应用中实现 Cookie 共享变得复杂。
- 安全问题:如果 Cookie
get 和 post 请求有什么区别?
请求目的:
- GET 请求主要用于
请求数据
。它通常用于获取HTML页面、CSS文件、JavaScript文件和图片等静态资源,或者通过URL传递参数来搜索或获取特定信息。 - POST 请求则主要用于
提交数据
。它常用于提交表单数据,如注册表单和登录表单,上传文件,以及执行如更新或删除数据等操作。
- GET 请求主要用于
请求参数传递方式:
- GET 请求的参数一般
附加在URL的末尾
,作为查询字符串的一部分,参数可见,且长度受限于URL的长度限制。 - POST 请求的参数包含在
请求的主体中
。这样,数据量大或者敏感信息可以通过POST请求更安全地传输,因为数据不会直接暴露在URL中。
- GET 请求的参数一般
安全性:
- 由于 GET 请求的参数直接
附加在 URL 上
,因此它们可能会被缓存、保存在浏览器历史记录中,或者通过引用链接被其他人看到。这可能导致敏感信息泄露,所以GET请求通常不适合用于传输敏感数据。 - POST 请求由于将数据放在
请求体
中,相对更安全,尤其适用于需要传输敏感或大量数据的场景。
- 由于 GET 请求的参数直接
数据长度限制:
- GET 请求由于参数在 URL 中,受到 URL 长度的限制,通常不适合传输大量数据。
- POST 请求则没有数据长度的限制,可以传输大量数据。
幂等性:
- GET 请求是
幂等
的,意味着多次执行相同的GET请求,结果应该是相同的(除了可能的缓存影响)。 - POST 请求
不是幂等
的,每次执行都可能产生不同的结果,例如提交表单数据。
- GET 请求是
后退/刷新按钮的影响:
- GET 请求的结果可以
被浏览器缓存
,因此用户点击后退或刷新按钮时,可能会重新发送相同的GET请求。 - POST 请求通常
不会被缓存
,因此用户点击后退或刷新按钮时,浏览器通常会警告用户将要重新提交表单数据。
- GET 请求的结果可以
get 请求是否限制了传参长度?
HTTP 协议未规定 GET 和 POST 的长度限制, GET 的最大长度显示是因为 浏览器
和 web服务器
限制了 URL 的长度(通常限制在 2048
个字符)。
强缓存和协商缓存分别是什么 ?
强缓存
- 在发送请求前,先检查
本地缓存中是否存在可用的资源副本
。如果存在,并且该资源没有过期
,服务器将返回200
,告诉浏览器直接使用本地缓存,而不需要向服务器发送请求 - 常见的强缓存响应头有
Expires
和Cache-Control
- Expires 字段指定了缓存过期的具体时间
- Cache-Control 字段则提供了更多关于缓存行为的详细设置,如
public
表示响应可以被任何缓存存储,private
表示响应只能被浏览器缓存,以及max-age=xxx
表示缓存的有效时间
- 在发送请求前,先检查
协商缓存
- 发生在浏览器对某个资源的请求
没有命中强缓存时
。这时,浏览器会发送一个请求到服务器,验证协商缓存是否命中。如果协商缓存命中,服务器将返回一个304 Not Modified
的响应,告诉浏览器资源未修改,可以继续使用缓存中的版本 - 协商缓存通常通过
Last-Modified
和ETag
这两个响应头来实现- Last-Modified: 表示资源最后修改的时间戳
- ETag:
根据资源内容生成的唯一标识符
- 发生在浏览器对某个资源的请求
区别:
强缓存不发送请求到服务器
,直接使用本地缓存协商缓存会发送请求到服务器
,通过比较本地缓存和服务器上的资源是否一致来决定是否使用本地缓存
协商缓存中,有了 Last-Modified,为什么还会出现 ETag?
在 HTTP 协议中,协商缓存机制用于在缓存过期后,判断客户端的缓存内容是否仍然有效
,从而决定是否需要从服务器重新获取资源
。
Last-Modified表示资源最后修改的时间戳
,它通常用于判断资源是否自上次请求以来有所变动。它的局限性:
- 只能
精确到秒级
,如果资源在秒内发生变动,Last-Modified 将无法准确判断。 - 如果
资源内容发生了改变但修改时间并未更新
(例如,手动修改文件内容但未改变文件的元数据),Last-Modified也无法正确识别资源的变动
。
ETag(Entity Tag)是根据资源内容生成的字符串,用于唯一标识资源
。每当资源内容发生变化时,ETag 也会相应改变。通过比较客户端缓存的 ETag 与服务器上的 ETag
,可以准确判断资源是否变动,而无需依赖于修改时间。
由于 Last-Modified 和 ETag 在验证资源变动时各有优势,因此在实际应用中,通常会同时使用这两种机制来增强协商缓存
的可靠性。当客户端发起请求时,会同时携带 Last-Modified
和 If-None-Match
(包含客户端缓存的ETag)头部信息。服务器收到请求后,会首先检查 Last-Modified,如果资源自上次请求以来未发生变动,则直接返回304 Not Modified
状态码,告知客户端可以使用缓存内容。如果 Last-Modified 表明资源可能发生了变动,服务器会进一步比较 ETag,以确保资源确实未变动。
Nginx 支持哪些负载均衡调度算法?
Nginx是一款自由的、开源的、高性能的HTTP服务器
和反向代理服务器
;同时也是一个IMAP、POP3、SMTP
代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。
负载均衡(Load Balancing)是一种计算机技术,用于在多个计算机(或计算机集群)、网络连接、CPU、磁盘驱动器或其他资源中分配负载
,以达到最优化资源使用、最大化吞吐率、最小化响应时间,并同时避免过载的目的。简单来说,负载均衡就是将工作任务(或访问请求)进行平衡和分摊
,使其由多个操作单元
(如服务器或组件)共同执行,从而协同完成这些工作任务。在Web应用中,负载均衡技术特别重要,因为它能够将大量的访问请求分散到多个Web服务器
上,确保每个服务器都能以最佳状态处理请求,从而为用户提供更流畅、更稳定的访问体验。
轮询调度算法(Round Robin):这是最简单的负载均衡算法,它按照请求的顺序依次将请求分发给后端服务器。每个请求都会被分发给下一个服务器,直到所有服务器都被轮询到。
加权轮询调度算法(Weighted Round Robin):这是在轮询算法的基础上引入权重因素,用于实现更灵活的负载均衡。weight值越大,分配到的访问几率越高。这种方式适用于后端服务器性能不均的情况。
IP哈希调度算法(IP_HASH):每个请求按访问IP的hash结果分配,这样来自同一IP的固定访问一个后端服务器。这种算法可以确保来自同一用户的请求总是被路由到同一台服务器上,有助于解决session共享问题。
最少连接调度算法(Least Connections):将请求传递到活动连接数最少的服务器。这种方式可以确保每台服务器的负载相对均衡,避免某些服务器过载而其他服务器空闲的情况。
为什么部分请求中,参数需要使用 encodeURIComponent 进行转码?
在Web开发中,encodeURIComponent
函数被用于对URI的组件进行编码,以便它们可以安全地包含在URL中,而不会导致解析错误或安全问题
。以下是一些原因,解释了为什么在某些情况下我们需要对请求中的参数使用encodeURIComponent
进行转码:
特殊字符
:URL中有些字符具有特殊含义,例如问号(?
)用于开始查询字符串,等号(=
)用于分隔键和值,而&
用于分隔不同的参数对。如果参数值中包含这些字符,它们可能会破坏URL的结构,导致解析错误。使用encodeURIComponent
可以确保这些字符被正确编码,从而避免此类问题。非打印字符:某些字符在 URL 中可能无法直接表示,或者在某些情况下可能被视为不安全或具有潜在风险。例如,空格在URL中通常会被编码为
%20
,而其他非打印字符(如制表符、换行符等)也应该被适当编码。避免安全漏洞:在某些情况下,如果参数值未经适当编码,可能会导致安全漏洞,如跨站脚本攻击(XSS)。攻击者可能会尝试在参数值中插入恶意脚本或利用 URL 解析的漏洞。通过编码参数值,我们可以降低这种风险。
保持一致性
:对参数值进行编码可以确保在不同浏览器和服务器之间的一致性。不同的浏览器或服务器可能对 URL 中某些字符的处理方式略有不同,因此通过编码参数值,我们可以减少这种不一致性带来的潜在问题。
使用encodeURIComponent
时,请注意它只编码URI的组件,而不是整个URI。如果你需要编码整个URI,包括协议、主机名和路径等部分,你应该使用encodeURI
函数。但是,对于查询字符串中的参数值,通常使用encodeURIComponent
更为合适。
Request Header和 Response Header 里面都有哪些重要的字段 ?
Request Header和Response Header中都有一些非常重要的字段,这些字段为客户端和服务器之间的通信提供了必要的信息和指示。
Request:
- Host:指定目标服务器的
域名
或IP
地址,这对于支持多个虚拟主机的Web服务器至关重要。 - User-Agent:发送请求的用户代理的标识,通常表示
浏览器
的类型
和版本
信息,服务器可以据此为不同的客户端提供定制化的响应。 - Accept:客户端可以接受的内容类型,如text/html、application/json等,它告诉服务器客户端期望接收哪种
格式的响应
。 - Content-Type:
请求体的媒体类型
,当客户端需要发送数据给服务器时(如POST请求),这个字段会指明数据的格式。 - Authorization:提供
身份验证
凭据,用于访问受保护的资源,如API接口。 - Cookie:包含在上一次响应中设置的服务器的 Cookie,用于跟踪用户会话或实现其他功能。
- Referer:指定当前请求的来源页面 URL,有助于分析用户行为和防止跨站请求伪造(CSRF)。
- Host:指定目标服务器的
Response:
- Content-Type:指定响应体的媒体类型,告诉客户端
返回的数据格式
。 - Content-Length:指定
响应体的长度
(以字节为单位),有助于客户端正确地处理数据。 - Cache-Control:指定
缓存策略
,如缓存的有效期、是否可以缓存等,它控制浏览器和其他缓存系统如何缓存和重用响应。 - Set-Cookie:在客户端设置 Cookie,用于存储会话信息或进行用户跟踪。
- Date:响应的日期和
时间
,有助于客户端了解响应的新鲜度。 - Expires:响应过期的日期和时间,与 Cache-Control 一起使用,控制
缓存的有效期
。 - Server:
服务器软件的名称和版本
,有助于客户端了解服务器的配置和调试问题。
- Content-Type:指定响应体的媒体类型,告诉客户端
HTTP 的长连接和短连接分别是什么 ?keep-alive 是干什么的 ?
HTTP的长连接和短连接是两种不同类型的网络连接方式
,它们在HTTP协议的不同版本中得到了支持和应用。
- HTTP短连接:
- 主要存在于
HTTP/1.0
版本中。在这种连接模式下,每次客户端向服务器发送一次请求后,服务器响应完毕就会断开连接
。 - 这种方式的特点是每个请求都需要
单独建立连接
,并且在请求完成后连接会被关闭。 - 短连接的好处是
应用级接口使用方便,对开发要求不高,容错性强
,但其缺点是传输速度慢,数据包大
,且在实时交互时服务器压力大,安全性也较差。 - 对于Web网站这样的场景,由于有成千上万的客户端连接,使用短连接可以节省服务器资源。
- HTTP长连接:
- 从
HTTP/1.1
版本开始得到支持。在这种连接模式下,客户端与服务器建立连接后,连接并不会在服务端响应结果后立马关闭,而是保持连接特性。 - 这种连接方式的优点在于能够
降低服务器和客户端之间的通信频率
,减少了不必要的连接和通信开销
,实时性较高
,适用于需要实时推送数据或事件的场景,如即时聊天、实时通知等。 - 由于需要维持大量的连接,对服务器资源压力较大。
- 在使用长连接时,通常会在请求头中加上
Connection: keep-Alive
字段来标识这是一个长连接请求。通过这种方式,服务器和客户端可以在一段时间内保持连接不断开,通过周期性地发送请求来检查是否有新的数据或事件。
- 从