目录
HTTP 协议中的缓存
缓存是 Web 性能优化的一个重要方面。它通过存储资源副本并在后续请求中重复使用它们来帮助减少延迟、带宽消耗和服务器负载。以下是用于控制缓存行为的一些关键 HTTP 标头:
缓存控制标头
Cache-Control用于指定请求和响应中的缓存机制的指令。
常见指令:
- public:表示响应可以被任何缓存存储,即使它通常是不可缓存的。
- private:表示响应仅针对单个用户,不应由共享缓存存储。
- no-cache:强制缓存在发布缓存副本之前将请求提交给原始服务器进行验证。
- no-store:指示缓存不存储请求或响应的任何部分。
- max-age=seconds:指定资源被视为新鲜的最大时间量。在此时间之后,缓存必须重新验证资源。
- s-maxage=secondsmax-age :与共享缓存(例如,CDN)类似,但具体用于共享缓存。
用例:
- 静态内容:长时间max-age减少原始服务器的负载。
- 动态内容:使用no-cache或max-age=0确保内容始终得到验证。
HTTP 中的身份验证和授权
身份验证和授权是网络安全的重要组成部分。它们确保用户的身份与其声称的身份相符(身份验证),并且他们拥有访问资源所需的权限(授权)。下面详细介绍了各种方法及其典型的 HTTP 请求/响应,以及不同框架的常用库。
基本身份验证
username:password基本身份验证是 HTTP 协议中内置的一种简单身份验证方案。它使用标头中发送的格式的 base64 编码字符串Authorization。
HTTP 请求
GET /protected-resource HTTP/1.1
Host: example.com
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
HTTP 响应
HTTP/1.1 200 OK
Content-Type: application/json
摘要式身份验证
摘要式身份验证比基本身份验证更安全。它使用质询-响应机制来避免以明文形式发送密码
HTTP 请求
GET /protected-resource HTTP/1.1
Host: example.com
Authorization: Digest username="username", realm="example.com", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", uri="/protected-resource", response="6629fae49393a05397450978507c4ef1", opaque="5ccc069c403ebaf9f0171e9517f40e41"
HTTP 响应
HTTP/1.1 200 OK
Content-Type: application/json
开放授权
OAuth 是用于访问委托的开放标准。它允许用户授予第三方应用程序访问其资源的权限,而无需共享其凭据。
HTTP 请求(授权码授予)
GET /authorize?response_type=code&client_id=client123&redirect_uri=https://client.example.com/cb&scope=read
HTTP 响应(访问令牌)
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "2YotnFZFEjr1zCsicMWpAA",
"token_type": "bearer",
"expires_in": 3600
}
基于令牌的身份验证
基于令牌的身份验证涉及登录成功后生成令牌,然后该令牌用于后续请求。
HTTP 请求
POST /login HTTP/1.1
Host: example.com
Content-Type: application/json
{
"username": "user",
"password": "pass"
}
HTTP 响应(令牌生成)
HTTP/1.1 200 OK
Content-Type: application/json
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
JWT(JSON Web 令牌)
JWT 是一种紧凑且 URL 安全的表示双方之间传输声明的方式。它通常用于授权。
HTTP 请求(使用 JWT)
GET /protected-resource HTTP/1.1
Host: example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
HTTP 响应
HTTP/1.1 200 OK
Content-Type: application/json
Cookie 和会话
Cookie 和会话是维护 Web 应用程序状态的基础。它们允许 Web 服务器在客户端存储和检索数据,从而实现用户身份验证、首选项和购物车等功能。
设置和管理 Cookie
设置Cookies
Cookie 是存储在客户端的小块数据,每次请求时都会发送到服务器。它们是使用Set-CookieHTTP 标头设置的。
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {
'Set-Cookie': 'user=JohnDoe; Path=/; HttpOnly',
'Content-Type': 'text/plain'
});
res.end('Cookie set');
}).listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
安全和 HttpOnly 标志
安全标志
该Secure标志可确保 Cookie 仅通过 HTTPS 发送,从而通过防止传输过程中 Cookie 被盗来提供一层安全性。
HttpOnly 标志
该HttpOnly标志可阻止 JavaScript 访问 cookie,从而降低跨站点脚本 (XSS) 攻击的风险。
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {
'Set-Cookie': 'user=JohnDoe; Path=/; Secure; HttpOnly',
'Content-Type': 'text/plain'
});
res.end('Secure and HttpOnly cookie set');
}).listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
会话管理
会话提供了一种跨多个请求存储数据的方法。它们通常存储在服务器上,并通过 cookie 将会话 ID 发送给客户端。
const express = require('express');
const session = require('express-session');
const app = express();
app.use(session({
secret: 'secretKey',
resave: false,
saveUninitialized: true,
cookie: { secure: false } // Set to true if using HTTPS
}));
app.get('/', (req, res) => {
if (req.session.views) {
req.session.views++;
res.send(`Number of views: ${req.session.views}`);
} else {
req.session.views = 1;
res.send('Welcome! Refresh to start counting views.');
}
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000/');
});
通过有效利用 Cookie 和会话,您可以在多个客户端-服务器交互中保持状态,从而提供无缝且个性化的用户体验。安全标志和会话管理对于确保 Web 应用程序的安全性和完整性至关重要。
替代数据存储方法
除了 cookie 和会话之外,还有其他几种在客户端和服务器端存储数据的方法,每种方法都有自己的用例和优点。
浏览器端数据存储
- localStorage:用于跨浏览器会话的持久数据存储。
- sessionStorage:用于单个会话内的临时数据存储。
服务器端数据存储
- 数据库:SQL(例如 MySQL)或 NoSQL(例如 MongoDB)用于实现强大的数据持久性。
- 内存数据存储:类似 Redis,用于快速、临时的数据存储。
- 文件:用于存储配置、日志或其他持久数据。
代理和反向代理
正向代理
正向代理充当客户端和互联网之间的中介。它可用于屏蔽客户端的 IP 地址、过滤请求和缓存响应以提高性能。正向代理通常用于:
- 匿名性:隐藏客户端的 IP 地址。
- 内容过滤:阻止访问某些网站。
- 缓存:存储经常访问的内容以减少带宽使用。
反向代理
反向代理位于客户端和服务器之间,将客户端请求转发到适当的后端服务器。它用于:
- 负载平衡:在多台服务器之间分配客户端请求。
- 缓存:存储来自后端服务器的响应以减少负载。
- SSL 终止:处理 SSL 加密/解密以从后端服务器卸载此任务。
- 安全性:通过隐藏 IP 地址并提供额外的安全层来保护后端服务器。
代理标头
X-Forwarded-For
该X-Forwarded-For标头用于识别通过代理或负载平衡器连接到 Web 服务器的客户端的原始 IP 地址。它包含以逗号分隔的 IP 地址列表,其中第一个 IP 是客户端的 IP,后续 IP 是代理服务器的 IP。
X-Forwarded-Host
该X-Forwarded-Host标头指示客户端在HostHTTP 标头中请求的原始主机。这对于在请求通过反向代理时保留原始主机信息很有用。
Web 服务器中的压缩
内容编码
服务器使用该Content-Encoding标头来指示响应数据使用的压缩类型。常见的压缩方法包括:
- gzip:最广泛支持和使用的压缩方法之一。它在压缩率和速度之间提供了良好的平衡。
- deflate:另一种使用 zlib 数据格式的广泛支持方法。它不如 gzip 常用,但仍在使用。
- br (Brotli):Google 开发的一种较新的压缩算法。与 gzip 和 deflate 相比,它提供了更高的压缩率,但较旧的浏览器并不普遍支持它。
接受编码标头
客户端发送标Accept-Encoding头来表明其支持哪些内容编码方法。然后,服务器使用此信息为响应选择适当的编码方法。
标头示例Accept-Encoding:
Accept-Encoding: gzip, deflate, br
Web 开发高级主题
WebSockets
WebSockets 通过单个长寿命连接提供全双工通信通道。这允许客户端和服务器之间进行实时数据交换,使其成为聊天应用、实时通知和在线游戏等应用程序的理想选择。
主要特点
- 全双工通信:客户端和服务器都可以同时发送和接收消息。
- 持久连接:减少建立多个 HTTP 连接的开销。
- 低延迟:实现实时通信,最大程度降低延迟。
典型用例
- 实时聊天应用程序
- 现场体育更新
- 在线多人游戏
- 协作编辑工具
服务器发送事件 (SSE)
服务器发送事件 (SSE) 允许服务器通过单个 HTTP 连接将更新推送到客户端。与 WebSockets 不同,SSE 是一种单向协议,数据从服务器流向客户端。
主要特点
- 简单 API:SSE 使用常规 HTTP,可以使用标准 Web 服务器配置来处理。
- 自动重新连接:内置支持自动重新连接和事件 ID 跟踪。
- 基于文本的协议:SSE 以文本形式传输数据,易于调试和理解。
典型用例
- 实时新闻
- 实时通知
- 股票价格走势
- 社交媒体更新
HTTP/2 服务器推送
HTTP/2 服务器推送允许服务器在客户端明确请求资源之前将其发送给客户端。通过主动提供服务器知道客户端需要的内容,这可以显著减少页面加载时间。
主要特点
- 主动资源交付:发送客户端可能需要的资源,减少延迟。
- 单连接:对多个流使用相同的连接,提高效率。
- 提高性能:减少获取资源所需的往返次数。
典型用例
- 与主 HTML 文档一起提供样式表和脚本。
- 预加载图像和其他资产以改善用户体验。
HTTP 管道
HTTP 管道允许在收到响应之前发送多个 HTTP 请求。这可以通过减少在发送下一个请求之前等待每个响应的延迟来提高 HTTP/1.1 连接的性能。
主要特点
- 顺序请求:请求按顺序发送,而无需等待相应的响应。
- 潜在的延迟减少:可以通过重叠请求和响应传输来减少延迟。
挑战
- 队头阻塞:如果一个请求花费很长时间,它可以阻塞后续请求。
- 有限的浏览器支持:由于诸如队头阻塞之类的问题,许多浏览器对流水线的支持有限或根本不支持。