Man*_* F. 23 fonts ruby-on-rails heroku cors amazon-cloudfront
访问我的网站时,我一直收到来自控制台的错误消息:
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.
Run Code Online (Sandbox Code Playgroud)
我尝试了一切:
配置了application.rb文件
config.font_assets.origin = 'http://example.com'
Run Code Online (Sandbox Code Playgroud)上的Cloudfront列入白名单的头在解释此文章到
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Max-Age
Run Code Online (Sandbox Code Playgroud)但没有,零,虚无...
我在Heroku上使用Rails 4.1.
Noa*_*man 67
这是一个非常难以处理的问题,原因有两个:
CloudFront正在镜像我们的Rails应用程序的响应标头这一事实需要您扭转局面.CORS协议很难理解,但现在你必须在两个层面上遵循它:浏览器和CloudFront之间(当我们的Rails应用程序将它用作CDN时),以及浏览器和我们的Rails应用程序之间(当一些恶意网站想滥用我们).
CORS实际上是关于浏览器和网页想要访问的第三方资源之间的对话.(在我们的使用案例中,这是CloudFront CDN,为我们的应用程序提供资产.)但是,由于CloudFront 从我们的应用程序获取其Access-Control响应标头,我们的应用程序需要提供这些标头,就好像它是CloudFront通话,同时不是授予权限,使其自身暴露于导致首先开发同源策略/ CORS的滥用类型.特别是,我们不应授予对我们网站资源的*访问权限*.
我发现了那么多过时的信息 - 无穷无尽的博客文章和SO线程.自从许多帖子以来,CloudFront已经显着改进了其CORS支持,尽管它仍然不完美.(CORS应该是开箱即用的.)宝石本身也在不断发展.
我的设置:Rails 4.1.15在Heroku上运行,资产由CloudFront提供.我的应用程序在"www"上响应http和https.和区域顶点,没有进行任何重定向.
我简要地看了一下问题中提到的font_assets gem,但很快就把它放在了机架上,这似乎更有意义.我不想简单地打开所有的起源和所有路径,因为这会破坏CORS点和同源策略的安全性,所以我需要能够指定一些来历我会允许.最后,我个人赞成通过单个config/initializers/*.rb文件配置Rails,而不是编辑标准配置文件(如config.ru或config/application.rb)将所有这些放在一起,这是我的解决方案,我相信这是最好的,截至2016-04-16:
的Gemfile
gem "rack-cors"
Run Code Online (Sandbox Code Playgroud)
rack-cors gem在Rack中间件中实现CORS协议.除了在已批准的源上设置Access-Control-Allow-Origin和相关标头之外,它还添加了Vary: Origin响应标头,指示CloudFront分别缓存每个源的响应(包括响应标头).当我们的网站可以通过多个来源(例如通过http和https,以及通过"www."和裸域)访问时,这是至关重要的
配置/初始化/机架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
Run Code Online (Sandbox Code Playgroud)
这告诉浏览器它可以仅代表我们的Rails应用程序(而不是代表malicious-site.com)访问我们的Rails应用程序(以及扩展,在CloudFront上,因为它正在镜像我们)上的资源,并且仅用于/assets/URL (而不是我们的控制器).换句话说,允许CloudFront提供资产,但不要再开门了.
笔记:
起源列表也可以作为Regexps完成.小心将模式锚定在字符串末尾.
origins [
/\Ahttps?:\/\/(www\.)?example\.com\z/,
/\Ahttps?:\/\/example-staging\.herokuapp\.com\z/
]
Run Code Online (Sandbox Code Playgroud)
但我认为只读文字字符串会更容易.
配置CloudFront将浏览器的Origin请求标头传递给我们的Rails应用程序.
奇怪的是,看起来CloudFront会将Origin标头从浏览器转发到我们的Rails应用程序,无论我们是否在此处添加它,但CloudFront Vary: Origin仅在将Origin明确添加到标题白名单时才会尊重我们的应用程序的缓存指令(截至2016年4月).
请求标题白名单有点埋没.
如果分发已存在,您可以在以下位置找到它:
如果您尚未创建分发版,请在以下位置创建:
单击创建分发
(为了完整性和可重复性,我列出了我从默认设置更改的所有设置,但白名单设置是唯一与此讨论相关的设置)
交付方式:Web(不是RTMP)
原点设置
默认缓存行为设置
更改所有这些内容后,请记住,任何旧的缓存值都可能需要一些时间才能从CloudFront到期.您可以通过转到CloudFront分配的"失效"选项卡并为其创建失效来明确使缓存的资产无效*.
如果您在Passenger和Heroku上运行Rails :(如果没有,请直接跳到Noach Magedman的答案)
Noach Magedman的回答对我来说非常有用,可以正确设置CloudFront.
我也rack-cors完全按照描述安装,虽然它在开发中运行良好,生产中的CURL命令从未返回任何CORS配置:
curl -H "Origin: https://tidyme-staging.com.au" -I http://tidyme-staging.com.au/assets/31907B_4_0-588bd4e720d4008295dcfb85ef36b233ee0817d7fe23c76a3a543ebba8e7c85a.ttf
HTTP/1.1 200 OK
Connection: keep-alive
Server: nginx/1.10.0
Date: Wed, 03 Aug 2016 00:29:37 GMT
Content-Type: application/x-font-ttf
Content-Length: 316664
Last-Modified: Fri, 22 Jul 2016 03:31:57 GMT
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Cache-Control: public
Accept-Ranges: bytes
Via: 1.1 vegur
Run Code Online (Sandbox Code Playgroud)
请注意,我直接ping服务器而不通过CDN,CDN然后在使所有内容无效之后应该转发服务器响应的任何内容.这里的重要一行是Server: nginx/1.10.0,表明资产由nginx而不是Rails提供.因此,rack-cors配置不适用.
适用于我们的解决方案如下:http://monksealsoftware.com/ruby-on-rails-cors-heroku-passenger-5-0-28/
它主要涉及克隆和修改Passenger的nginx配置文件,这并不理想,因为每次乘客升级和模板更改时都需要维护此副本.
===
这是一个总结:
导航到Rails项目的根文件夹,并复制nginx配置模板
cp $(passenger-config about resourcesdir)/templates/standalone/config.erb config/passenger_config.erb
Run Code Online (Sandbox Code Playgroud)
打开config/passenger_config.erb并评论此行
<%# include_passenger_internal_template('rails_asset_pipeline.erb', 8, false) %>
Run Code Online (Sandbox Code Playgroud)
在上面提到的行下面添加这些配置
### BEGIN your own configuration options ###
# This is a good place to put your own config
# options. Note that your options must not
# conflict with the ones Passenger already sets.
# Learn more at:
# https://www.phusionpassenger.com/library/config/standalone/intro.html#nginx-configuration-template
location ~ "^/assets/.+\.(woff|eot|svg|ttf|otf).*" {
error_page 490 = @static_asset_fonts;
error_page 491 = @dynamic_request;
recursive_error_pages on;
if (-f $request_filename) {
return 490;
}
if (!-f $request_filename) {
return 491;
}
}
# Rails asset pipeline support.
location ~ "^/assets/.+-([0-9a-f]{32}|[0-9a-f]{64})\..+" {
error_page 490 = @static_asset;
error_page 491 = @dynamic_request;
recursive_error_pages on;
if (-f $request_filename) {
return 490;
}
if (!-f $request_filename) {
return 491;
}
}
location @static_asset {
gzip_static on;
expires max;
add_header Cache-Control public;
add_header ETag "";
}
location @static_asset_fonts {
gzip_static on;
expires max;
add_header Cache-Control public;
add_header ETag "";
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, HEAD, OPTIONS';
add_header 'Access-Control-Allow-Headers' '*';
add_header 'Access-Control-Max-Age' 3628800;
}
location @dynamic_request {
passenger_enabled on;
}
### END your own configuration options ###
Run Code Online (Sandbox Code Playgroud)
更改Procfile以包括此自定义配置文件
web: bundle exec passenger start -p $PORT --max-pool-size 2 --nginx-config-template ./config/passenger_config.erb
Run Code Online (Sandbox Code Playgroud)
然后部署......
===
如果您知道更好的解决方案,请填写评论.
实现后,CURL命令产生以下响应:
curl -H "Origin: https://tidyme-staging.com.au" -I http://tidyme-staging.com.au/assets/31907B_4_0-588bd4e720d4008295dcfb85ef36b233ee0817d7fe23c76a3a543ebba8e7c85a.ttf
HTTP/1.1 200 OK
Connection: keep-alive
Server: nginx/1.10.0
Date: Wed, 03 Aug 2016 01:43:48 GMT
Content-Type: application/x-font-ttf
Content-Length: 316664
Last-Modified: Fri, 22 Jul 2016 03:31:57 GMT
Expires: Thu, 31 Dec 2037 23:55:55 GMT
Cache-Control: max-age=315360000
Cache-Control: public
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 3628800
Accept-Ranges: bytes
Via: 1.1 vegur
Run Code Online (Sandbox Code Playgroud)
从 5.0 版本开始,Rails 允许为资产设置自定义 HTTP 标头,您不必使用 rack-cors 或 font-assets gem。为了为资产(包括字体)设置 Access-Control-Allow-Origin,只需在 config/environments/production.rb 中添加以下代码:
config.public_file_server.headers = {
'Access-Control-Allow-Origin' => '*'
}
Run Code Online (Sandbox Code Playgroud)
标头值也可以是特定域,如下所示:
config.public_file_server.headers = {
'Access-Control-Allow-Origin' => 'https://www.example.org'
}
Run Code Online (Sandbox Code Playgroud)
这适用于我的应用程序,我不需要更改 Cloudfront 上的任何设置。
小智 2
我刚刚遇到了同样的问题并设法解决了它。
您已正确告知 Cloudfront 允许这些标头,但您尚未将这些标头添加到 Cloudfront 获取字体的位置。是的,您的原始标头是允许的,但 Heroku 无论如何都不会使用字体发送这些标头。
要解决此问题,您需要将正确的 CORS 标头添加到 Heroku 上的字体中。幸运的是,这很容易。
首先,将rack/corsgem 添加到您的项目中。 https://github.com/cyu/rack-cors
接下来,配置您的机架服务器以为其服务的任何资产加载和配置 CORS。在应用程序预加载后添加以下内容 config.ru
require 'rack/cors'
use Rack::Cors do
allow do
origins '*'
resource '/cors',
:headers => :any,
:methods => [:post],
:credentials => true,
:max_age => 0
resource '*',
:headers => :any,
:methods => [:get, :post, :delete, :put, :patch, :options, :head],
:max_age => 0
end
end
Run Code Online (Sandbox Code Playgroud)
这将从 Heroku 返回的任何资源设置为应用正确的 CORS 标头。您可以根据您的文件和安全需求限制标头的应用。
部署后,进入 Cloudfront 并开始使之前导致 CORS 权限错误的任何内容失效。现在,当 Cloudfront 从 Heroku 加载新副本时,它将具有正确的标头,并且 Cloudfront 会将这些标头按照之前使用您的Origin权限配置的方式传递到客户端。
为了确保您从服务器提供正确的标头,您可以使用以下curl命令来验证您的标头:
curl -I -s -X GET -H "Origin: www.yoursite.com" http://www.yoursite.dev:5000/assets/fonts/myfont.svg
您应该看到返回以下标头:
Access-Control-Allow-Origin: www.yoursite.com
Access-Control-Allow-Methods: GET, POST, DELETE, PUT, PATCH, OPTIONS, HEAD
Access-Control-Max-Age: 0
Access-Control-Allow-Credentials: true
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6521 次 |
| 最近记录: |