Cloudfront CORS 问题在 Rails 应用程序上提供字体

2024-03-03

访问我的网站时,我不断从控制台收到此错误消息:

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。


这是一个非常难以处理的问题,原因有二:

  1. CloudFront 的事实是镜像我们的 Rails 应用程序的响应标头需要您充分思考。 CORS 协议本身就很难理解,但现在您必须在两个级别上遵循它:浏览器和 CloudFront 之间(当我们的 Rails 应用程序将其用作 CDN 时),以及浏览器和我们的 Rails 应用程序之间(当一些恶意网站想要滥用我们)。

    CORS 实际上是浏览器与网页想要访问的第三方资源之间的对话。 (在我们的用例中,这是 CloudFront CDN,为我们的应用程序提供资产。)但是由于 CloudFront 获取其访问控制响应标头from我们的应用程序,我们的应用程序需要提供这些标头as if这是 CloudFront 正在说话,并且同时地不授予可能导致自身遭受滥用的权限,而正是这种滥用导致了同源策略/CORS 的开发。特别是,我们不应该授予*进入*我们网站上的资源。

  2. 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 日为止最好的解决方案:

  1. Gemfile

    gem "rack-cors"
    

    rack-cors gem 在 Rack 中间件中实现 CORS 协议。 除了在批准的来源上设置 Access-Control-Allow-Origin 和相关标头之外,它还添加了Vary: Origin响应标头,指示 CloudFront 分别缓存每个源的响应(包括响应标头)。当我们的网站可通过多个来源访问时(例如通过 http 和 https,以及通过“www.”和裸域),这一点至关重要

  2. 配置/初始化器/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/
      ]
      

      但我认为读取文字字符串更容易。

  3. 配置 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然后单击添加>>


    如果您尚未创建发行版,请在以下位置创建:

    • https://console.aws.amazon.com/cloudfront/home#distributions https://console.aws.amazon.com/cloudfront/home#distributions
    • 单击创建分配

      (为了完整性和可重复性,我列出了我从默认值更改的所有设置,但是白名单设置是唯一与此讨论相关的设置)

    • 交付方式:Web(非 RTMP)

    • 原点设置

      • 源域名:example.com
      • Origin SSL 协议:仅限 TLSv1.2
      • 源协议策略:仅限 HTTPS
    • 默认缓存行为设置

      • 查看器协议策略:将 HTTP 重定向到 HTTPS
      • 转发标头:白名单
      • 白名单标头: Select Origin然后单击添加>>
      • 自动压缩对象:是

更改所有这些内容后,请记住,任何旧的缓存值可能需要一段时间才能从 CloudFront 过期。您可以通过转至 CloudFront 发行版的“失效”选项卡并为以下内容创建失效来显式使缓存资产失效:*.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Cloudfront CORS 问题在 Rails 应用程序上提供字体 的相关文章

随机推荐