📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

配置项作用 #

http.cors.allow-headers 配置项用于指定在跨域资源共享(CORS)请求中允许浏览器发送的自定义 HTTP 请求头列表

当浏览器发送跨域请求时,如果请求包含自定义头部,服务器需要在响应的 Access-Control-Allow-Headers 中明确声明允许这些头部,浏览器才会允许请求通过。

配置项属性 #

  • 配置路径: http.cors.allow-headers
  • 数据类型: String(逗号分隔的字符串列表)
  • 默认值: "X-Requested-With,Content-Type,Content-Length"
  • 是否可选: 是
  • 作用域: NodeScope(节点级别)

配置项详解 #

工作机制 #

CORS 预检请求流程

浏览器发送实际请求前
    │
    ↓
发送 OPTIONS 预检请求
    │
    ↓
包含请求的头部信息
Access-Control-Request-Headers: X-Auth-Token,Custom-Header
    │
    ↓
服务器检查 allow-headers 配置
    │
    ├──────── 所有头部都在允许列表中 ✅
    │              ↓
    │         返回成功响应
    │              ↓
    │         Access-Control-Allow-Headers:
    │         X-Requested-With,Content-Type,X-Auth-Token,Custom-Header
    │              ↓
    │         浏览器发送实际请求
    │
    └──────── 有头部不在允许列表中 ❌
                       ↓
                  返回错误响应
                       ↓
                  浏览器阻止实际请求

简单请求 vs 预检请求 #

简单请求(无需预检):
- 使用默认的 CORS 安全头部
- GET、HEAD、POST 方法
- Content-Type: application/x-www-form-urlencoded
- multipart/form-data、text/plain

直接发送请求,不需要预检


非简单请求(需要预检):
- 使用自定义头部
- PUT、DELETE 方法
- Content-Type: application/json

1. 先发送 OPTIONS 预检请求
2. 服务器返回允许的头部
3. 浏览器再发送实际请求

默认头部说明 #

默认允许的头部

X-Requested-With:
- 作用: 标识 AJAX 请求
- 常见值: XMLHttpRequest
- 用途: 服务器区分普通请求和 AJAX 请求

Content-Type:
- 作用: 指定请求内容类型
- 常见值: application/json, text/plain
- 用途: 告知服务器如何解析请求体

Content-Length:
- 作用: 请求体的字节长度
- 常见值: 数字
- 用途: 服务器用于读取完整的请求体

配置建议 #

默认配置(简单场景) #

http:
  cors:
    enabled: true
    allow-origin: "*"
    allow-headers: "X-Requested-With,Content-Type,Content-Length"  # 默认值

建议: 保持默认值。适用于标准的 AJAX 请求。

需要 JSON 请求体 #

http:
  cors:
    enabled: true
    allow-origin: "*"
    allow-headers: "X-Requested-With,Content-Type,Content-Length,Accept"

建议: 添加 Accept 头。当需要发送 JSON 请求体时使用。

需要 JWT 认证 #

http:
  cors:
    enabled: true
    allow-origin: "https://example.com"
    allow-headers: "X-Requested-With,Content-Type,Content-Length,Authorization"
    allow-credentials: true

建议: 添加 Authorization 头。当使用 JWT Token 认证时使用。

完整配置(生产环境) #

http:
  cors:
    enabled: true
    allow-origin: "https://app.example.com"
    allow-headers: "X-Requested-With,Content-Type,Content-Length,Authorization,Accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers"
    allow-credentials: true
    allow-methods: "GET,POST,PUT,DELETE,OPTIONS,HEAD"
    max-age: 3600

建议: 包含所有必要的头部。生产环境的完整配置。

代码示例 #

easysearch.yml 基础配置 #

http:
  cors:
    enabled: true
    allow-origin: "*"
    allow-headers: "X-Requested-With,Content-Type,Content-Length"

开发环境配置 #

http:
  cors:
    enabled: true
    allow-origin: "http://localhost:3000"
    allow-headers: "X-Requested-With,Content-Type,Content-Length,Authorization,X-Auth-Token"

多应用支持配置 #

http:
  cors:
    enabled: true
    allow-origin: "https://app1.example.com,https://app2.example.com"
    allow-headers: "X-Requested-With,Content-Type,Content-Length,Authorization,X-API-Key,X-Client-Version"

自定义认证头配置 #

http:
  cors:
    enabled: true
    allow-origin: "https://dashboard.example.com"
    allow-headers: "X-Requested-With,Content-Type,Content-Length,X-Custom-Auth,X-Session-ID"

相关配置 #

配置项作用默认值
http.cors.enabled是否启用 CORSfalse
http.cors.allow-origin允许的来源域名-
http.cors.allow-methods允许的 HTTP 方法OPTIONS,HEAD,GET,POST,PUT,DELETE
http.cors.allow-headers允许的请求头X-Requested-With,Content-Type,Content-Length
http.cors.allow-credentials是否允许凭证false
http.cors.max-age预检请求缓存时间1728000

前端请求示例 #

带 Authorization 头的请求 #

fetch('https://easysearch.example.com/_search', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + token
  },
  body: JSON.stringify({ query: { match_all: {} } })
})

需要配置: Authorization

带自定义 API Key 的请求 #

axios.get('https://easysearch.example.com/_cluster/health', {
  headers: {
    'X-API-Key': 'your-api-key'
  }
})

需要配置: X-API-Key

带自定义客户端信息的请求 #

fetch('https://easysearch.example.com/_cat/indices', {
  headers: {
    'Content-Type': 'application/json',
    'X-Client-Version': '1.0.0',
    'X-Session-ID': 'session-123'
  }
})

需要配置: X-Client-Version, X-Session-ID

常见请求头说明 #

标准请求头 #

Content-Type:
- application/json
- application/x-www-form-urlencoded
- text/plain

Accept:
- application/json
- application/xml
- text/html

Authorization:
- Bearer <token>
- Basic <credentials>

Origin:
- https://example.com

自定义请求头 #

认证相关:
- X-Auth-Token
- X-API-Key
- X-Session-ID

客户端信息:
- X-Client-Version
- X-Device-ID
- X-Request-ID

业务相关:
- X-Tenant-ID
- X-Organization-ID
- X-Custom-Header

使用场景 #

推荐使用默认配置的场景 #

  • 简单查询: 只需要基本的 CRUD 操作
  • 公开 API: 不需要认证的数据接口
  • 标准 AJAX: 使用标准的 XMLHttpRequest 或 Fetch

推荐添加 Authorization 的场景 #

  • JWT 认证: 使用 Bearer Token 认证
  • OAuth 2.0: 使用 OAuth 认证流程
  • Basic Auth: 使用 HTTP 基本认证

推荐添加自定义头的场景 #

  • API Key: 使用自定义 API Key 认证
  • 多租户: 需要传递租户信息
  • 会话管理: 需要传递会话 ID
  • 客户端追踪: 需要传递客户端版本或设备信息

预检请求示例 #

浏览器发送 OPTIONS 请求:

OPTIONS /_search HTTP/1.1
Host: easysearch.example.com
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type,Authorization


服务器返回响应:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Headers: X-Requested-With,Content-Type,Content-Length,Authorization
Access-Control-Max-Age: 3600


浏览器检查响应后发送实际请求:

POST /_search HTTP/1.1
Host: easysearch.example.com
Origin: https://app.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

{ "query": { "match_all": {} } }

常见问题排查 #

问题 1: 请求被 CORS 阻止 #

错误信息:
Request header field X-Custom-Header is not allowed by Access-Control-Allow-Headers

原因:
allow-headers 配置中没有包含 X-Custom-Header

解决:
http.cors.allow-headers: "X-Requested-With,Content-Type,Content-Length,X-Custom-Header"

问题 2: Authorization 头未生效 #

现象:
前端设置了 Authorization 头,但服务器没有收到认证信息

原因:
1. allow-headers 中没有包含 Authorization
2. 浏览器在预检请求中被拒绝

解决:
http.cors.allow-headers: "X-Requested-With,Content-Type,Content-Length,Authorization"
http.cors.allow-credentials: true

问题 3: 大量预检请求 #

现象:
每次请求都先发送 OPTIONS 预检请求

原因:
max-age 设置过小或未设置

解决:
http.cors.max-age: 3600  # 缓存 1 小时

注意事项 #

  1. 必须启用 CORS: 只有在 http.cors.enabled: true 时,此配置才生效。

  2. 大小写不敏感: 头部名称不区分大小写,但建议使用标准的大写形式。

  3. 逗号分隔: 多个头部使用逗号分隔,不要有空格或使用其他分隔符。

  4. 预检请求: 任何不在默认列表中的自定义头部都会触发预检请求。

  5. 与 allow-credentials 配合: 如果启用了凭证,需要特别注意安全配置。

  6. 性能优化: 设置合理的 max-age 可以减少预检请求次数。

  7. 最小权限原则: 只添加业务必需的头部,不要添加所有可能的头部。

  8. 调试建议: 使用浏览器开发者工具查看 Network 面板中的预检请求。

  9. 通配符限制: 预检请求的响应中不能使用 * 作为 allow-headers 的值。

  10. 动态更新: 此配置支持动态更新,修改后立即生效。