浏览器直连需要跨源放行
浏览器里的页面与服务端接口不同源时,浏览器会先发一个预检请求,用 OPTIONS 方法询问「这个来源、这些请求头是否允许」。网关必须按来源白名单回应相应的跨源头,并对预检直接返回成功状态,真正的请求才会发出。与之相关的一个常见选择是密钥放在哪里:如果密钥随前端代码下发,任何人都能从浏览器里取到,因此更稳妥的做法是由自己的后端转发调用。
基本信息
| 协议依据 | 浏览器的跨源资源共享规则,预检使用 OPTIONS 方法 |
|---|---|
| 关键响应头 | 允许来源、允许方法、允许请求头、预检缓存时长 |
| 返回状态 | 预检通常直接返回 204 或 200,不转发给上游 |
| 来源匹配 | 按前端部署域名精确列举,不使用通配符 |
| 密钥位置 | 不宜放在前端,优先由自有后端代理转发 |
典型使用场景
- 前端直连网关:页面部署在独立域名上,需要跨源访问接口
- 多前端共存:管理后台与业务前端两个来源都需要放行
- 预检频繁:交互密集的页面每次新请求头组合都会触发预检,需要缓存时长减少往返
- 本地调试:开发环境不同端口属于不同来源,同样触发跨源规则
- 安全审查:核实是否存在来源写通配符且同时允许携带凭证的配置
网关片段
网关片段
location /v1/ {
if ($request_method = OPTIONS) { return 204; } # 预检直接放行,不转发上游
add_header Access-Control-Allow-Origin https://<前端域名> always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
add_header Access-Control-Max-Age 600 always; # 预检结果缓存十分钟,减少往返
proxy_pass http://llm;
}响应头与常见错误
| 响应头 | 作用 | 配错的后果 |
|---|---|---|
| 允许来源 | 声明可以使用该响应的来源 | 写成通配符时与携带凭证冲突,浏览器直接拒绝 |
| 允许方法 | 声明预检通过的方法 | 缺少实际使用的方法,请求被拦截 |
| 允许请求头 | 声明允许的自定义头 | 漏写鉴权头,带令牌的请求全部失败 |
| 预检缓存时长 | 浏览器缓存预检结果的秒数 | 过短导致预检频繁,延迟增加 |
| 暴露响应头 | 允许前端读取的响应头 | 未声明时前端读不到请求标识,排障困难 |
流式响应在浏览器侧还要处理读取方式与断线重连:相关内容按前端框架的文档实现,网关只负责跨源放行与不缓冲转发。
来源写成通配符同时允许携带凭证是明确的安全问题:任何站点都能在用户浏览器里调用你的接口,来源必须按实际域名列举。