正在加载,请稍候…

HTTP 标头详解:请求、响应与安全标头

一份实用的 HTTP 标头指南,涵盖请求标头、响应标头、CORS、缓存、CSP 和 HSTS 等安全标头,以及如何正确设置它们。

HTTP 标头详解:请求、响应与安全标头

HTTP 标头:开发者完整参考

HTTP 标头是随每个请求和响应发送的键值对。它们控制缓存、身份验证、内容协商、安全策略等。理解它们对于调试 API、修复 CORS 问题和强化 Web 应用程序至关重要。

HTTP 标头详解:请求、响应与安全标头 插图

请求标头

这些标头由客户端(浏览器或 HTTP 客户端)发送到服务器。

身份与内容

标头 用途 示例
Host 目标主机名(HTTP/1.1 必需) Host: api.example.com
User-Agent 客户端软件标识 User-Agent: Mozilla/5.0...Chrome/124
Accept 客户端可处理的媒体类型 Accept: application/json, text/html
Accept-Language 首选响应语言 Accept-Language: en-US,en;q=0.9
Accept-Encoding 客户端支持的压缩方式 Accept-Encoding: gzip, deflate, br
Content-Type POST/PUT 的请求体格式 Content-Type: application/json
Content-Length 请求体大小(字节) Content-Length: 348

身份验证

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Authorization: Basic dXNlcjpwYXNzd29yZA==
Authorization: Digest username="bob", realm="api"...

Authorization 标头传输凭据。Bearer 令牌(JWT)在 API 中最常见。Basic 是 base64 编码的 user:password——仅在 HTTPS 下安全。

缓存控制(请求端)

Cache-Control: no-cache        # 即使已缓存也重新验证
Cache-Control: no-store        # 永不缓存
Cache-Control: max-age=0       # 将缓存副本视为过期
If-None-Match: "abc123"        # 通过 ETag 进行条件 GET
If-Modified-Since: Tue, 15 Nov 2022 12:45:26 GMT

CORS 预检

Origin: https://app.example.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: Content-Type, Authorization

浏览器在跨域请求使用非 GET/POST 方法或包含自定义标头之前,会发送一个预检 OPTIONS 请求,其中包含这些标头。

响应标头

HTTP 标头详解:请求、响应与安全标头 插图

内容交付

标头 用途 示例
Content-Type 响应体格式 + 字符集 Content-Type: application/json; charset=utf-8
Content-Length 响应体大小 Content-Length: 1024
Content-Encoding 应用的压缩方式 Content-Encoding: gzip
Transfer-Encoding 分块传输(用于流式传输) Transfer-Encoding: chunked
Location 重定向目标 URL Location: https://example.com/new-path

缓存

# 公共资源(CSS、图片):缓存 1 年,变更时重新验证
Cache-Control: public, max-age=31536000, immutable

# API 响应:不缓存
Cache-Control: no-store

# HTML 页面:每次请求重新验证
Cache-Control: no-cache

# 用于条件请求的 ETag
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

# 最后修改日期
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT

# 共享缓存过期时间(旧式,推荐使用 Cache-Control)
Expires: Thu, 01 Dec 2034 16:00:00 GMT

Cache-Control 指令速查表:

指令 含义
public 任何缓存(CDN、浏览器)均可存储
private 仅浏览器,不包含 CDN
no-cache 使用缓存副本前必须重新验证
no-store 任何地方都不存储
max-age=N 新鲜期 N 秒
s-maxage=N CDN 最大年龄(覆盖共享缓存的 max-age)
immutable 内容不会改变;跳过重新验证
stale-while-revalidate=N 后台获取新内容时,可提供过期内容

CORS 标头

跨域资源共享控制哪些外部源可以访问资源。

服务器响应标头

# 允许特定源
Access-Control-Allow-Origin: https://app.example.com

# 允许任何源(对于需要身份验证的端点不安全)
Access-Control-Allow-Origin: *

# 预检响应:允许的方法
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH

# 预检响应:允许的自定义标头
Access-Control-Allow-Headers: Content-Type, Authorization, X-Request-ID

# 预检结果缓存时间(秒)
Access-Control-Max-Age: 86400

# 允许凭据(cookies、身份验证标头)
Access-Control-Allow-Credentials: true

# 浏览器可暴露给 JavaScript 的标头
Access-Control-Expose-Headers: X-Total-Count, X-Page

关键规则: 不能同时使用 Access-Control-Allow-Origin: *Access-Control-Allow-Credentials: true。需要凭据的请求必须指定具体源。

CORS 错误流程图

  1. 浏览器发起跨域请求 → 浏览器添加 Origin 标头
  2. 如果请求是“简单”请求(GET/POST + 标准标头)→ 请求通过,浏览器检查响应中的 Access-Control-Allow-Origin
  3. 如果请求是“复杂”请求(DELETE、PUT 或自定义标头)→ 浏览器先发送 OPTIONS 预检请求
  4. 如果预检失败 → 原始请求被阻止,控制台显示 CORS 错误

安全标头

这些标头是防御 XSS、点击劫持和注入攻击的第一道防线。

HTTP 标头详解:请求、响应与安全标头 插图

Content-Security-Policy (CSP)

CSP 告诉浏览器允许加载脚本、样式、图片和其他资源的来源。

# 针对 SPA 的严格 CSP
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com; frame-ancestors 'none'

# 仅报告违规而不强制执行(测试阶段)
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

常见 CSP 指令:

指令 控制内容
default-src 所有资源类型的回退
script-src JavaScript 来源
style-src CSS 来源
img-src 图片来源
connect-src XHR、fetch、WebSocket 目标
frame-ancestors 允许将本页面嵌入 iframe 的源
object-src Flash/插件(设置为 'none'

Strict-Transport-Security (HSTS)

强制所有未来访问使用 HTTPS:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
  • max-age:记住 HTTPS 要求的秒数
  • includeSubDomains:应用于所有子域名
  • preload:包含在浏览器内置的 HSTS 列表中(在 hstspreload.org 提交)

其他安全标头

# 阻止 MIME 嗅探(例如,加载伪装成图片的脚本)
X-Content-Type-Options: nosniff

# 防止点击劫持(旧式,推荐使用 CSP 的 frame-ancestors)
X-Frame-Options: DENY

# 启用浏览器 XSS 过滤器(旧式,现代浏览器忽略)
X-XSS-Protection: 1; mode=block

# 控制 referrer 信息
Referrer-Policy: strict-origin-when-cross-origin

# 限制浏览器功能(摄像头、麦克风、地理位置)
Permissions-Policy: camera=(), microphone=(), geolocation=(self)

推荐的安全标头组合(2026)

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none'
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: interest-cohort=()

在 securityheaders.com 测试你的标头。

自定义标头约定

按照惯例,自定义标头使用 X- 前缀(尽管这在 RFC 6648 中已被弃用):

X-Request-ID: 550e8400-e29b-41d4-a716-446655440000
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1699012800
X-Correlation-ID: abc-123

速率限制标头逐渐标准化为 RateLimit-LimitRateLimit-RemainingRateLimit-Reset(不带 X-)。

调试标头

# 查看请求 + 响应标头
curl -v https://api.example.com/users

# 仅查看响应标头
curl -I https://example.com

# 发送自定义标头
curl -H "Authorization: Bearer TOKEN" -H "Accept: application/json" https://api.example.com

# 跟随重定向,显示最终标头
curl -L -D - https://example.com -o /dev/null

在 Chrome DevTools → Network 标签页 → 点击任意请求 → Headers 面板显示请求和响应标头,并解码值。

→ 在浏览器中使用 JWT 解析器 解码 JWT 令牌。在 HTTP 状态码 查看 HTTP 状态码。