自定义Access-Control-Allow-Origin策略以解决字体文件跨域权限问题

jerry CSS 2015年11月23日 收藏

什么是Access-Control-Allow-Origin

Access-Control-Allow-Origin是HTML5中定义的一种服务器端返回Response header,用来解决资源(比如字体)的跨域权限问题。

它定义了该资源允许被哪个域引用,或者被所有域引用(google字体使用*表示字体资源允许被所有域引用)。

什么是资源跨域权限

当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如www.example.org),那么我们就可以认为它们是相同的域。

比如http://www.example.org/和http://www.example.org/sub/是同域,而http://www.example.org, https://www.example.org, http://www.example.org:8080, http://sub.example.org中的任何两个都将构成跨域。

例如www.a.com对www.b.com下的asset.php发送了一个跨域的HTTP请求,那么asset.php必须加入如下的响应头:

header("Access-Control-Allow-Origin: http://www.a.com");

坑爹的是,该域值不可为正则表达式,如http://*.a.com

如果HTML和CSS等资源所在的CDN不一致,就会出现跨域访问,而这在大型网站中是很常见的

HTML域: http://ctc.qzs.qq.com/ 【等】

CSS域: http://ctc.qzonestyle.gtimg.cn 【等】

字体与CSS是相对路径所以同域: http://ctc.qzonestyle.gtimg.cn 但是HTML与字体是跨域!

高级浏览器访问html页面的时候,对于CSS文件中使用的字体文件的请求,会带一个origin:头,这个头就是html页面所在的域。

高级浏览器(Firefox,IE9+)会对比自己发出的Request header中的Origin:和返回字体文件的Response header的Access-Control-Allow-Origin:域

  • 若相同,则表示该网站有权限使用该字体,浏览器显示字体
  • 若不同,则表示该网站无权使用该字体,浏览器虽然下载了该字体,但拒绝显示

解决办法1

  • 对于字体文件的Request,全部在返回头中加入:
  • Access-Control-Allow-Origin:*
  • 缺点:安全性问题

解决办法2

根据Request Headers的内容,决定一些需要的Response Headers的内容,这里定义规则如下:

根据Request的Origin: 进行决策,

在Origin来自

*.qq.com(包括www.qq.com; qq.com;)时;

Response Header中增加Access-Control-Allow-Origin:头

头的内容保持和Requset Headers中的Origin: 头URI中的protocol, domainname, port内容,并一致