# INTERNAL: gRPC-Web: 来源 http://malicious-site.com 的 CORS 预检失败：响应中未包含 Access-Control-Allow-Origin

- **ID:** `grpc/cors-preflight-origin-not-allowed`
- **领域:** grpc
- **类别:** auth_error
- **错误码:** `GRPC_WEB_CORS_ORIGIN_DENIED`
- **验证级别:** ai_generated
- **修复率:** 92%

## 根因

来自未授权来源的 gRPC-Web 客户端尝试了 CORS 预检请求，但服务器的 CORS 策略未将该来源列入允许列表。

## 版本兼容性

| 版本 | 状态 | 引入 | 弃用 |
|------|------|------|------|
| gRPC-Web v1.4.0 | active | — | — |
| envoy v1.28.0 | active | — | — |
| gRPC-web-go-client v1.4.0 | active | — | — |

## 解决方案

1. ```
   Add the specific origin to the CORS allowlist on the gRPC-Web proxy (e.g., Envoy). In Envoy config: cors_policy: allow_origin_string_match: [prefix: "https://myapp.example.com"] allow_methods: "POST, OPTIONS" allow_headers: "content-type, x-grpc-web"
   ```
2. ```
   If using a custom Go gRPC-Web server, add CORS middleware: func corsMiddleware(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "https://myapp.example.com"); w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS"); w.Header().Set("Access-Control-Allow-Headers", "content-type, x-grpc-web"); if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK); return }; h.ServeHTTP(w, r) }) }
   ```
3. ```
   Use a reverse proxy like nginx to add CORS headers before the request reaches the gRPC-Web server: add_header 'Access-Control-Allow-Origin' 'https://myapp.example.com' always;
   ```

## 无效尝试

- **** — Setting Access-Control-Allow-Origin: * in production exposes the API to cross-site request forgery and data theft from any website. (90% 失败率)
- **** — Disabling CORS checks on the client by using a non-browser environment (e.g., curl) does not solve the problem for actual web users. (95% 失败率)
