我正在尝试编写一个 nginx 配置来处理 http 和 https 上的两个站点,只要客户端从不访问这两个站点,它似乎就可以工作,但如果他们这样做,就会出现缓存/跨站点问题。
# 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";
}
}
所以如果我加载 example.com,一切正常,但是当我加载 admin.example.com 时,我会遇到这样的问题
(index):1 XMLHttpRequest cannot load http://origin.example.com/js/data-lib/currency.json. The 'Access-Control-Allow-Origin' header has a value 'http:// example . com' that is not equal to the supplied origin. Origin 'http:// admin . example . com' is therefore not allowed access.
据我所知,这是因为浏览器缓存了带有 header 的原始请求,现在它拒绝了我,即使来自服务器的另一个请求允许它。证据是,如果我在 Chrome 开发者工具中选中禁用缓存,那么问题就不会发生。
我该如何解决这个问题?是否可以在一个配置中执行多个域 + ssl/http,或者是否有必要根据请求的域和协议(protocol)将其拆分?
(对于我的示例中可怕的空间感到抱歉,显然 StackOverflow 认为我只是在编写示例时试图发布链接)
最佳答案
如果您添加值为 Origin
的 Vary
响应 header ,这应该会导致任何浏览器跳过其缓存并在Origin
请求 header 的值与其缓存的请求的 Origin
值不同。
参见 the relevant part of the HTTP spec .所以你可以更新你的 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";
}
您可以在 the MDN article on the Vary
response header 中阅读更多内容.
The
Vary
HTTP response header determines how to match future request headers to decide whether a cached response can be used rather than requesting a fresh one from the origin server. It is used by the server to indicate which headers it used when selecting a representation of a resource in a content negotiation algorithm.
…在 MDN Access-Control-Allow-Origin
文章中的 CORS and caching部分:
If the server sends a response with an
Access-Control-Allow-Origin
value that is an explicit origin (rather than the "*
" wildcard), then the response should also include aVary
response header with the valueOrigin
— to indicate to browsers that server responses can differ based on the value of theOrigin
request header.
……在 the Fetch spec itself 中:
If your requirements are more complicated than setting
Access-Control-Allow-Origin
to*
or a static origin, use theVary: Origin
response header.If
Vary
is not used and a server is configured to sendAccess-Control-Allow-Origin
for a certain resource only in response to a CORS request: When a user agent receives a response to a non-CORS request for that resource, the response will lackAccess-Control-Allow-Origin
and the user agent will cache that response. If the user agent then encounters a CORS request for the resource, it will use that cached response from the previous non-CORS request — withoutAccess-Control-Allow-Origin
.But if
Vary: Origin
is used in the same scenario, it will cause the user agent to fetch a response that includesAccess-Control-Allow-Origin
, rather than using the cached response from the previous non-CORS request lackingAccess-Control-Allow-Origin
关于http - 跨站点缓存 Access-Control-Allow-Origin 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46063304/