访问我的网站时,我不断从控制台收到此错误消息:
font from origin 'https://xxx.cloudfront.net' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://www.example.com' is therefore not allowed access.
我已经尝试了一切:
- 我已经安装了字体资产宝石 https://github.com/ericallam/font_assets
-
配置application.rb文件
config.font_assets.origin = 'http://example.com'
-
Cloudfront 上的白名单标头,如中所述本文 http://kennethjiang.blogspot.co.uk/2014/07/set-up-cors-in-cloudfront-for-custom.html to
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Max-Age
但什么也没有,零,什么也没有。
我在 Heroku 上使用 Rails 4.1。
这是一个非常难以处理的问题,原因有二:
-
CloudFront 的事实是镜像我们的 Rails 应用程序的响应标头需要您充分思考。 CORS 协议本身就很难理解,但现在您必须在两个级别上遵循它:浏览器和 CloudFront 之间(当我们的 Rails 应用程序将其用作 CDN 时),以及浏览器和我们的 Rails 应用程序之间(当一些恶意网站想要滥用我们)。
CORS 实际上是浏览器与网页想要访问的第三方资源之间的对话。 (在我们的用例中,这是 CloudFront CDN,为我们的应用程序提供资产。)但是由于 CloudFront 获取其访问控制响应标头from我们的应用程序,我们的应用程序需要提供这些标头as if这是 CloudFront 正在说话,并且同时地不授予可能导致自身遭受滥用的权限,而正是这种滥用导致了同源策略/CORS 的开发。特别是,我们不应该授予*
进入*
我们网站上的资源。
I found so much那里有过时的信息——无穷无尽的博客文章和SO线程。自发布许多帖子以来,CloudFront 已显着改进了其 CORS 支持,尽管它仍然不完美。 (CORS 确实应该开箱即用地处理。)宝石本身已经进化了。
我的设置:Rails 4.1.15 在 Heroku 上运行,资产由 CloudFront 提供。我的应用程序在“www”上响应 http 和 https。和区域顶点,不做任何重定向。
我简单地浏览了问题中提到的 font_assets gem,但很快就放弃了它,转而使用rack-cors,这似乎更切题。我不想简单地开放所有来源和所有路径,因为这会破坏 CORS 的要点和同源策略的安全性,因此我需要能够指定我允许的少数来源。最后,我个人更喜欢通过个人配置 Railsconfig/initializers/*.rb
文件而不是编辑标准配置文件(例如config.ru
or config/application.rb
)将所有这些放在一起,这是我的解决方案,我认为这是截至 2016 年 4 月 16 日为止最好的解决方案:
-
Gemfile
gem "rack-cors"
rack-cors gem 在 Rack 中间件中实现 CORS 协议。
除了在批准的来源上设置 Access-Control-Allow-Origin 和相关标头之外,它还添加了Vary: Origin
响应标头,指示 CloudFront 分别缓存每个源的响应(包括响应标头)。当我们的网站可通过多个来源访问时(例如通过 http 和 https,以及通过“www.”和裸域),这一点至关重要
-
配置/初始化器/rack-cors.rb
## Configure Rack CORS Middleware, so that CloudFront can serve our assets.
## See https://github.com/cyu/rack-cors
if defined? Rack::Cors
Rails.configuration.middleware.insert_before 0, Rack::Cors do
allow do
origins %w[
https://example.com
http://example.com
https://www.example.com
http://www.example.com
https://example-staging.herokuapp.com
http://example-staging.herokuapp.com
]
resource '/assets/*'
end
end
end
这告诉浏览器它只能代表我们的 Rails 应用程序(并且通过扩展,在 CloudFront 上,因为它是我们的镜像)访问我们的 Rails 应用程序上的资源(并且not代表恶意站点.com)且仅用于/assets/
网址(和not对于我们的控制器)。换句话说,允许 CloudFront 为资产提供服务,但不要打开任何不必要的门。
Notes:
- 我尝试插入这个after机架超时而不是在中间件链的头部。
它在开发中有效,但在 Heroku 上不起作用,尽管
具有相同的中间件(Honeybadger 除外)。
-
来源列表也可以作为正则表达式完成。
小心地将图案锚定在绳子末端。
origins [
/\Ahttps?:\/\/(www\.)?example\.com\z/,
/\Ahttps?:\/\/example-staging\.herokuapp\.com\z/
]
但我认为读取文字字符串更容易。
-
配置 CloudFront 以将浏览器的 Origin 请求标头传递到我们的 Rails 应用程序。
奇怪的是,CloudFront 似乎将 Origin 标头从浏览器转发到我们的 Rails 应用程序不管我们是否将其添加到此处,但 CloudFront 尊重我们应用程序的Vary: Origin
仅当 Origin 明确添加到标头白名单(截至 2016 年 4 月)时才使用缓存指令。
请求标头白名单有点被隐藏了。
如果该发行版已经存在,您可以在以下位置找到它:
- https://console.aws.amazon.com/cloudfront/home#distributions https://console.aws.amazon.com/cloudfront/home#distributions
- 选择分布
- 单击分发设置
- 转到行为选项卡
- 选择行为(可能只有一个)
- 单击编辑
- 转发标头:白名单
-
白名单标头: Select Origin然后单击添加>>
如果您尚未创建发行版,请在以下位置创建:
更改所有这些内容后,请记住,任何旧的缓存值可能需要一段时间才能从 CloudFront 过期。您可以通过转至 CloudFront 发行版的“失效”选项卡并为以下内容创建失效来显式使缓存资产失效:*
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)