子域名之间设置CORS头时,Access-Control-Allow-Origin该怎么写才不会报错?
我在开发主站example.com时,子域名api.example.com返回的JSON数据总被浏览器拦截,控制台提示:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.example.com/data. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
之前试过在Nginx里这样配置:
server {
listen 80;
server_name api.example.com;
add_header Access-Control-Allow-Origin "*.example.com";
# 其他配置...
}
但依然不行。后来改成具体域名https://example.com后,控制台又报错说:
Refused to execute script from 'https://api.example.com/data' because its MIME type ('application/json') is not executable, and strict MIME type checking is enabled.
难道子域名之间只能通过通配符配置?但老师说通配符不安全…现在完全不知道该怎么调整CORS头了。
首先,关于
Access-Control-Allow-Origin的值,不能用通配符加域名的形式,比如你写的"*.example.com"是无效的。浏览器只认两种情况:要么是具体的域名,比如https://example.com,要么是*表示允许所有域名。但如果你用了*,就无法同时设置凭据(credentials)相关的头,比如 cookies 或者 authorization headers。我当时也是折腾了半天才发现,正确的做法是根据请求来源动态设置这个值。在 Nginx 里,可以通过变量来实现。你可以试试下面这种配置:
这里的关键点是用正则匹配请求来源,并动态设置
$cors_origin的值。这样既安全又能满足需求。至于你提到的第二个错误,MIME 类型的问题其实跟你返回的响应内容类型有关,而不是 CORS 配置本身的问题。检查一下你的后端代码或者 Nginx 配置,确保返回 JSON 数据时,头部有明确声明
Content-Type: application/json。如果没设置或者设置错了,浏览器就会报 MIME 类型不匹配的错误。举个例子,如果你用的是 Nginx 静态文件服务,可以加上类似这样的配置:
default_type application/json;如果是后端接口,也要确保代码里正确设置了响应头。
总结一下,先用动态方式设置
Access-Control-Allow-Origin,然后检查返回数据的Content-Type是否正确。这两个地方搞定,你的问题应该就能解决了。我当时就是这么绕出来的,希望对你有帮助!