Kratos跨域必须在Gateway层config.yaml配置,因网关作为独立进程默认拦截OPTIONS请求并返回204,不透传下游,且allowCredentials为true时allowOrigins禁用“*”,否则浏览器静默丢弃响应。

Kratos 的跨域必须在 Gateway 层的 config.yaml 里配,下游 service 加 CORS 中间件完全无效——预检请求(OPTIONS)压根到不了你写的 service。
为什么网关层配置是唯一有效方式
Kratos Gateway 是独立进程,所有 HTTP 流量先经过它再转发。它的 cors 中间件默认启用且 OptionsPassthrough: false,意味着:OPTIONS 请求被网关直接拦截并返回 204 No Content,根本不会透传给下游服务。
- 你在 user service 或 order service 里用
gorilla/handlers.CORS()或自定义中间件加 CORS 头,浏览器永远看不到——因为响应来自网关,不是你的 service - 网关不透传下游的
Access-Control-Allow-*响应头,即使下游写了也白写 - 错误现象典型如:
Response to preflight request doesn't pass access control check,根源就是网关没配或配错
allowCredentials: true 时 allowOrigins 不能写 ["*"]
这是最常踩的坑:浏览器明确禁止 credentials + * 组合,会静默丢弃响应,连控制台都不报错。
- 开发环境可写死:
allowOrigins: ["http://localhost:3000", "https://dev.example.com"] - 生产环境禁用通配符;若需动态支持多域名,得手写中间件提取请求头
Origin,校验后只回写该值(避免反射型漏洞) -
allowMethods必须显式包含"OPTIONS",否则预检失败 - 自定义 header(如
X-Auth-Token)必须列在allowHeaders里,否则浏览器拒绝读取
如何验证网关是否正确处理 OPTIONS 预检
别只靠浏览器调试——它可能缓存失败响应或隐藏细节。用 curl 直接模拟最可靠:
curl -v -X OPTIONS \ -H "Origin: https://app.example.com" \ -H "Access-Control-Request-Method: POST" \ -H "Access-Control-Request-Headers: X-Auth-Token" \ http://localhost:8000/api/user
- 检查响应状态码是否为
204 - 确认响应头含:
Access-Control-Allow-Origin: https://app.example.com、Access-Control-Allow-Credentials: true、Access-Control-Allow-Methods: POST, OPTIONS等 - 注意:
Vary: Origin必须存在,否则 CDN 或反向代理可能缓存错误响应(Kratos 默认加,但手写中间件容易漏)
真正麻烦的从来不是配几个字段,而是理解 Kratos Gateway 的请求生命周期——它不转发 OPTIONS,也不透传下游头,更不会合并多个 CORS 配置。配错位置,等于没配。











