【问题标题】:"Request has expired" when using S3 with Active Storage将 S3 与 Active Storage 一起使用时“请求已过期”
【发布时间】:2019-01-01 07:20:55
【问题描述】:

我是第一次使用 ActiveStorage。 在开发中一切正常,但在生产(Heroku)中,我的图像无缘无故消失了。

他们第一次显示正常,但现在没有显示图像。在控制台中我可以看到这个错误:

GET https://XXX.s3.amazonaws.com/variants/Q7MZrLyoKKmQFFwMMw9tQhPW/XXX 403 (Forbidden)

如果我尝试直接访问该 URL,我会得到一个 XML

<Error>
  <Code>AccessDenied</Code>
  <Message>Request has expired</Message>
  <X-Amz-Expires>300</X-Amz-Expires>
  <Expires>2018-07-24T13:48:25Z</Expires>
  <ServerTime>2018-07-24T15:25:37Z</ServerTime>
  <RequestId>291D41FAC6708334</RequestId>      
  <HostId>lEVGuwA6Hvlm/i40PeXaje9SEBYks9+uk6DvBs=</HostId>
</Error>

这是我在视图中看到的

<div class="cover" style="background-image: url('<%= rails_representation_path(experience.thumbnail) %>')"></div>

这就是我在模型中所拥有的

def thumbnail
  self.cover.variant(resize: "300x300").processed
end

简单来说,我不希望图像过期,而是要一直存在。

谢谢

【问题讨论】:

    标签: ruby-on-rails amazon-s3 ruby-on-rails-5 rails-activestorage


    【解决方案1】:

    ActiveStorage 不支持非过期链接。它使用过期链接(私有),并支持仅在您的服务上以私有方式上传文件。

    这对我来说也是个问题,并且只为 S3 做了 2 个补丁(注意),one simple ~30lines 覆盖 ActiveStorage 以仅适用于非过期(公共)链接,以及 @987654322 @。

    希望对你有帮助。

    【讨论】:

    • 嗨 Dinatih,看起来不错,但我正在努力解决这个问题:“ActiveStorage 不支持非过期链接”。那是什么意思?我需要的是一个超级简单的:当人们加载页面时,图像总是在那里。它们不会过期,不会发生任何花哨的事情。人们访问该网站并看到图像。为什么我不能使用 ActiveStorage 上传公共图片?
    • 看起来 ActiveStorage 在构建时没有考虑到类似的东西。性能也是如此 - 资产链接会产生大量重定向、延迟,并使使用 CDN 变得非常困难。
    【解决方案2】:

    您的问题并没有这么说,但是将 AWS CloudFront 之类的 CDN 与 Rails 应用程序一起使用是很常见的。尤其是在 Heroku 上,您可能希望节省计算能力。

    这是在这种情况下发生的情况。您像往常一样渲染一个页面,并且所有图像都是从资产主机(即 CDN)请求的,因为这就是它被配置为集成的方式。它的设置是从源端获取它在缓存中找不到的任何东西,这又是你的应用程序。

    首先传递所有图像请求。 ActiveStorage 控制器为它们创建签名的 URL,CDN 将它们传递给它们,但也会缓存它们。

    现在问题来了。默认情况下,签名的 URL 会在 5 分钟后过期,但 CDN 缓存的时间通常要长得多。这是因为您通常使用摘要资产,这意味着它们在任何更改时都不是按时间而是按名称失效。

    解决方案很简单。 将签名 URL 的有效期延长到比缓存的 TTL 更长。现在缓存会在缓存的签名 URL 失效之前丢弃它。

    使用 5.2 中的 ActiveStorage::Service.url_expires_in 或直接在初始化器 see this answer 中的 Rails.application.config.active_storage.service_urls_expire_in 设置 URL 到期时间。

    要在 CloudFront 中设置缓存 TTL:打开 AWS 控制台,选择分配,打开行为选项卡,向下滚动到这些字段:

    然后可选地发出一个失效以强制重新缓存所有内容。

    请记住,存在安全权衡。如果图像内容是私有的,那么它们很可能不属于 CDN,也不应该有持久的临时 URL。在这种情况下,请选择一个完全免除 CDN 附件的解决方案。除了渲染相关页面之外,您的应用程序还必须处理签署所有附加资产 URL 的额外负载。

    进一步记住,这不一定是一个好的解决方案,而更多的是一种解决方法。通过上述设置,您将缓存重定向,并且较重的请求将直接到达您的存储桶。 CDN 的常见场景是大型媒体,而不是轻量级重定向。不过,您确实减轻了应用程序处理大量请求的负担。应该研究多少是有效的优化。

    【讨论】:

      【解决方案3】:

      我也遇到了同样的问题,但是在我更正了计算机上的时间后,问题就解决了。这是一个服务器时差,aws 服务器无法识别。

      【讨论】:

        猜你喜欢
        • 2013-03-29
        • 1970-01-01
        • 2019-02-16
        • 1970-01-01
        • 1970-01-01
        • 2016-05-09
        • 1970-01-01
        • 2015-10-03
        • 1970-01-01
        相关资源
        最近更新 更多