NGINX,ssl,CORS和Access-Control-Allow-Origin值跨站点缓存

Chr*_*ail 5 xss http nginx http-caching cors

我正在尝试编写一个可以同时在http和https上处理两个站点的nginx配置,只要客户端从未访问过两个站点,它似乎就可以工作,但是如果这样做的话,则存在缓存/跨站点问题。

# Allow cross origin
location ~* \.(eot|svg|ttf|woff|woff2|json)$ {
    if ($http_origin ~* (https?://(admin\.)?example\.com(:[0-9]+)?)) {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,如果我加载example.com,则一切正常,但是当我加载admin.example.com时,会遇到类似问题

(索引):1 XMLHttpRequest无法加载 http://origin.example.com/js/data-lib/currency.json。“ Access-Control-Allow-Origin”标头具有值“ http:// example”。com”不等于提供的来源。来源'http:// admin。例子 因此,不允许访问“ com”。

据我所知,这是因为浏览器将原始请求及其附带的标头缓存了起来,现在,即使来自服务器的另一个请求允许它,它也拒绝了我。证明是,如果我在Chrome开发者工具中选中了“禁用缓存”,则该问题将永远不会发生。

我该如何解决这个问题?是否可以在一个配置中同时完成多个域+ ssl / http,还是有必要根据请求的域和协议将其拆分?

(对我示例中的可怕空间感到抱歉,显然,StackOverflow认为我在编写示例时试图发布链接)

sid*_*ker 5

如果您将Vary响应标头添加为value Origin,那么当Origin请求标头的值与从其缓存的请求的值不同时,应该会导致任何浏览器跳过其缓存并发出新的网络请求Origin

至少它应该在浏览器中具有符合HTTP规范相关部分的效果

因此,您可以更新nginx配置以执行此操作:

# Allow cross origin
location ~* \.(eot|svg|ttf|woff|woff2|json)$ {
    if ($http_origin ~* (https?://(admin\.)?example\.com(:[0-9]+)?)) {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        add_header 'Vary' "Origin";
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在MDN Vary响应标题的文章中阅读更多内容

VaryHTTP响应头决定如何满足未来的请求头,以决定一个缓存的响应是否可以使用,而不是请求从源服务器一个新的一个。服务器使用它来指示在内容协商算法中选择资源表示形式时使用了哪些标头。