我能否将Access-Control-Allow-Origin头设置为域和其子域上的所有页面?

11

我正在尝试使用一种我有合法使用权但不可分发的网络字体。我将字体文件托管在一个用于静态内容的独立域名上。这两个域名是无关的(其中一个不是另一个的子域名)。假设使用该网络字体的网站是example.com,而托管它的网站是example.net

我在example.net的.htaccess文件中尝试了这个方法。

<FilesMatch "\.(ttf|otf|eot|woff|svg)$">
  <IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "example.com"
  </IfModule>
</FilesMatch>

然而,这使得字体仅在example.com的主页上起作用。我再次尝试:

    Header set Access-Control-Allow-Origin "example.com/*"

现在这种字体在example.com的每个页面上都可以使用,除了主页,这当然不是我想要的。

我找不到有关此标头的任何文档。我真正想要的是允许example.comwww.example.com(或者为了保险起见,*.example.com)上的所有页面使用。是否有一种简单的方法可以实现这一点?我猜测该标头需要某种正则表达式。

在寻找文档时,我找到了:

  • 关于此标题如何与ajax交互的大量内容,
  • 大量简短的注释说这对于Web字体是必需的(至少在Firefox中)。

我没有找到关于标头本身的语法或如何指定域的变体的任何文档。

根据相关问题的答案,我尝试了以下操作:

<FilesMatch "\.(ttf|otf|eot|woff|svg)$">
    <IfModule mod_headers.c>
        SetEnvIf Origin "http(s)?://(www\.)?(example.com)$" AccessControlAllowOrigin=$0$1
        Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
        Header set Access-Control-Allow-Credentials true
    </IfModule>
</FilesMatch>

我的理解是,这将为每个请求设置单独的标题,允许每个请求页面单独使用字体。然而,通过Firebug检查,看起来标题总是http://example.com,无论是在主页还是其他地方。尽管如此,它仍然可以工作,但让我感到困惑。一个相关的问题表明,对于另一个人,类似的设置没有起作用。他的问题表明,对于他来说,它实际上是为每个请求页面发送不同的标题,并且因此HTTP 304 Not Modified响应出现了问题。他的解决方案是在.htaccess中添加一个always指令,但对我来说,这导致了HTTP 500错误。

现在它正在工作,我认为当example.com切换到HTTPS时(很快就会),它仍将继续工作。但是,我无法不感到它过于复杂。它每次都设置相同的标题,但是使用复杂的模式匹配来完成。此外,虽然我还没有遇到HTTP 304 Not Modified响应的任何问题(事实上,我还没有看到任何这样的响应:浏览器根本不会请求字体文件,直到我清除缓存),但我担心将来可能会出现这种情况。


现在它是工作的 - 那么问题到底是什么呢?另请参阅https://dev59.com/kmYr5IYBdhLWcg3wB16h。 - mb21
它每次都设置相同的标题,但是使用复杂的模式匹配来实现。当我要求它每次设置相同的标题时,它却没有起作用。 - TRiG
2个回答

4
根据CORS规范Access-Control-Allow-Origin头部只能有一个域名(或*null)。
因此,是的,您需要根据请求站点的域名不同来设置不同的头部。这就是您发布的Apache配置片段尝试使用此正则表达式匹配请求的Origin头部的原因。
http(s)?://(www\.)?(example.com)$
$匹配字符串的末尾。因此,这个正则表达式将匹配来自http://www.example.comhttp://example.com及其https等价物的请求,但不匹配example.com/bla。这应该是可以接受的,因为请求的Origin头以及响应的Access-Control-Allow-Origin只应包含主机而不是子页面。
因此,当您在页面http://example.com/about-us上时,浏览器将发送类似以下请求以从http://cdn.net/myfont.otf获取字体:
GET /myfont.otf HTTP/1.1
Host: http://cdn.net
Origin: http://example.com

在这里,服务器将对Origin头进行模式匹配,并返回以下内容:

Access-Control-Allow-Origin: http://example.com

好的。这回答了为什么当我明确设置为 example.com 时它不起作用:它需要协议。并且解释了为什么需要模式匹配。没有协议时发生的怪异情况(字体只在主页上工作,或者在主页以外的地方工作)可以归因于浏览器在面对不准确的头部信息时的怪癖。谢谢。 - TRiG

0

供参考,我正在更新/etc/apache2/conf/sites-enabled/*文件以达到同样的目的。我的代码:

   <Directory /var/www/dir>
     AllowOverride FileInfo Options
     Header set Access-Control-Allow-Origin "http://example.com"
     Header set Access-Control-Allow-Origin "http://www.example.com"
   </Directory>

有一件事情我必须处理 - 我没有启用mod_headers,所以重启apache失败了。我必须使用以下命令启用它:

a2enmods headers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接