Google Endpoints拦截OPTIONS请求:XHR跨域请求带API密钥触发403错误
这个问题我之前也碰到过,核心原因是浏览器发起的CORS预检OPTIONS请求,默认的no-referrer-when-downgrade策略在跨域场景下可能不会携带Referrer头,而你的API密钥又设置了Referer白名单,导致验证失败返回403。下面给你几个可行的解决方案,按推荐优先级排序:
方案1:让OPTIONS预检请求跳过API密钥验证(推荐)
预检请求本身只是浏览器用来确认服务器是否允许后续实际请求的“探路”请求,不包含业务数据,完全不需要携带API密钥。你可以在Endpoints的配置里,给OPTIONS方法单独设置跳过API密钥验证:
如果用OpenAPI规范定义Endpoints,只需给OPTIONS操作添加security: []字段:
paths: /your-api-endpoint: options: summary: 处理CORS预检请求 security: [] # 这里指定不需要API密钥验证 responses: '200': description: 预检通过 headers: Access-Control-Allow-Origin: schema: type: string Access-Control-Allow-Methods: schema: type: string Access-Control-Allow-Headers: schema: type: string
这样配置后,OPTIONS请求就不会触发API密钥的Referrer白名单检查,自然也就不会返回403了,这也是符合CORS最佳实践的做法。
方案2:修改请求的Referrer Policy,确保OPTIONS携带Referrer
如果你必须让OPTIONS请求也携带API密钥,可以通过修改XHR/fetch的Referrer Policy,强制请求携带符合白名单的Referrer头:
针对单个XHR请求:
const xhr = new XMLHttpRequest(); // 设置Referrer Policy为只发送源地址(既符合白名单要求,又不会泄露完整路径) xhr.referrerPolicy = 'origin'; xhr.open('POST', 'your-endpoint-url', true); // 其他请求配置(比如添加API密钥头) xhr.setRequestHeader('X-API-Key', 'your-api-key'); xhr.send();
针对fetch请求:
fetch('your-endpoint-url', { method: 'POST', headers: { 'X-API-Key': 'your-api-key' }, // 同样设置Referrer Policy referrerPolicy: 'origin' });
也可以在HTML页面的<head>里添加meta标签,全局设置Referrer Policy:
<meta name="referrer" content="origin">
这样所有请求(包括OPTIONS预检)都会携带源地址作为Referrer,只要你的白名单里包含了应用的源地址(比如https://your-app-domain.com/*),就能通过验证。
方案3:放宽API密钥的Referrer白名单(不推荐)
如果以上两种方法都无法实施,你可以尝试在Cloud Console的API密钥设置里,添加空Referrer或者通配符到白名单,但这种做法会降低安全性,因为任何来源的请求都可能通过验证,所以仅作为最后的应急方案。
内容的提问来源于stack exchange,提问作者Yugansh Marwah

