简体   繁体   English

将 S3 与 Active Storage 一起使用时出现“请求已过期”

[英]"Request has expired" when using S3 with Active Storage

I'm using ActiveStorage for the first time.我是第一次使用 ActiveStorage。 Everything works fine in development but in production (Heroku) my images disappear without a reason.在开发中一切正常,但在生产(Heroku)中我的图像无故消失。

They were showing ok the first time, but now no image is displayed.他们第一次显示正常,但现在没有显示图像。 In the console I can see this error:在控制台中我可以看到这个错误:

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

If I try to visit that URL directly I get an XML如果我尝试直接访问那个 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>

This is what I have in the view这就是我的看法

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

This is what I have in the model这就是我在 model 中所拥有的

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

In simple words, I don't want images to expire but to be always there.简而言之,我不希望图像过期,而是一直存在。

Thanks谢谢

ActiveStorage does not support non-expiring link. ActiveStorage 不支持非过期链接。 It uses expiring links (private), and support uploading files only as private on your service.它使用过期链接(私人),并支持仅在您的服务中将文件上传为私人文件。

It was a problem for me too, and did 2 patches (caution) for S3 only, one simple ~30lines that override ActiveStorage to work only with non-expiring (public) links, and another that add an acl option to has_one_attached and has_many_attached methods .这对我来说也是一个问题,并且仅针对 S3 做了 2 个补丁(警告), 一个简单的 ~30 行覆盖 ActiveStorage 以仅使用非过期(公共)链接, 另一个向 has_one_attached 和 has_many_attached 方法添加 acl 选项.

Hope it helps.希望能帮助到你。

I had this same issue, but after I corrected the time on my computer, the problem was resolved.我有同样的问题,但在我更正计算机上的时间后,问题就解决了。 It was a server time difference, that the aws servers did not recognize.这是一个服务器时间差异,aws 服务器无法识别。

Your question doesn't say so, but it's common to use a CDN like AWS CloudFront with a Rails app.您的问题并没有这么说,但是将 AWS CloudFront 之类的 CDN 与 Rails 应用程序一起使用是很常见的。 Especially on Heroku you probably want to conserve compute power.特别是在 Heroku 上,您可能希望节省计算能力。

Here is what happens in that scenario.这是在这种情况下发生的情况。 You render a page as usual, and all the images are requested from the asset host, which is the CDN, because that's how it is configured to integrate.你像往常一样渲染一个页面,所有的图像都是从资产主机请求的,它是 CDN,因为它是如何配置集成的。 Its setup to fetch anything it doesn't find in cache from origin, which is your application again.它的设置是从原点获取它在缓存中找不到的任何内容,这又是您的应用程序。

First all image requests are passed through.首先传递所有图像请求。 The ActiveStorage controller creates signed URLs for them, and the CDN passes them on, but also caches them. ActiveStorage 控制器为它们创建签名 URL,CDN 传递它们,但也会缓存它们。

Now comes the problem.现在问题来了。 The signed URL expires in 5 minutes by default, but the CDN caches usually much longer.默认情况下,签名 URL 会在 5 分钟后过期,但 CDN 缓存通常会更长。 This is because usually you use digest assets, meaning they are invalidated not by time but by name, on any change.这是因为通常您使用摘要资产,这意味着它们不是按时间而是按名称在任何更改时失效。

The solution is simple.解决方法很简单。 Increase the expiry of the signed URL to be longer than the cache's TTL .将签名 URL 的到期时间增加到比缓存的 TTL 更长的时间 Now the cache drops the cached signed URL before it becomes invalid.现在缓存会在缓存的签名 URL 变得无效之前删除它。

Set the URL expiry using ActiveStorage::Service.url_expires_in in 5.2 or directly in Rails.application.config.active_storage.service_urls_expire_in in an initializer see this answer for details.使用 5.2 中的ActiveStorage::Service.url_expires_in或直接在Rails.application.config.active_storage.service_urls_expire_in中的初始值设定项中设置 URL 到期, 请参阅此答案以了解详细信息。

To set cache TTL in CloudFront: open the AWS console, pick the distribution, open the Behavior tab, scroll down to these fields:要在 CloudFront 中设置缓存 TTL:打开 AWS 控制台,选择分配,打开行为选项卡,向下滚动到以下字段:

Cloudfront ttl 字段

Then optionally issue an invalidation to force re-caching of all contents.然后可选地发出失效以强制重新缓存所有内容。

Keep in mind there is a security trade-off.请记住,存在安全权衡。 If the image contents are private, then they don't belong into a CDN most likely, and shouldn't have long lasting temp URLs either.如果图像内容是私有的,那么它们很可能不属于 CDN,也不应该具有持久的临时 URL。 In that case choose a solution that exempts attachments from CDN altogether.在这种情况下,请选择一个完全免除 CDN 附件的解决方案。 Your application will have to handle the additional load of signing all attached assets' URLs on top of rendering the relevant page.您的应用程序必须在呈现相关页面的基础上处理对所有附加资产的 URL 进行签名的额外负载。

Further keep in mind, that this isn't necessarily a good solution, but more of a workaround.进一步记住,这不一定是一个好的解决方案,而是更多的解决方法。 With the above setup you will cache redirects, and the heavier requests will hit your storage bucket directly.通过上述设置,您将缓存重定向,而较重的请求将直接命中您的存储桶。 The usual scenario for CDNs is large media, not lightweight redirects. CDN 的常见场景是大型媒体,而不是轻量级重定向。 You do relieve the app of handling a lot of requests though.不过,您确实减轻了应用程序处理大量请求的负担。 How much that is a valid optimization should be looked into.应该研究多少是有效的优化。

#production.rb #production.rb

Change改变

config.active_storage.service =:local config.active_storage.service =:本地

To

config.active_storage.service =:amazon config.active_storage.service =:亚马逊

Should match aws/amazon whatever you defined it as in storage.yml无论您在 storage.yml 中定义什么,都应该匹配 aws/amazon

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 活动存储未保存到 S3 - Active Storage not saving to S3 使用Amazon S3和Rails Active Storage时丢失附件文件 - Missing attached files when using Amazon S3 and Rails Active Storage 如何使用Ruby on Rails / Coffeescript来测试S3 Presigned GET URL以查看其是否已过期,以及如何对其进行重新生成。 - How to test an S3 Presigned GET url to see if it has expired, and regenerate it if it has, using Ruby on Rails/Coffeescript 用于活动存储文件的 S3 直接链接 - S3 Direct Link for Active Storage Files Rails 6:访问具有活动存储的亚马逊 S3 时,应用程序名称中带有特殊字符的文件会崩溃 - Rails 6: Files with special characters in the name crash app when accessing amazon S3 with active storage 带有 Amazon S3 的 Active Storage 不使用指定的文件名保存,而是使用文件密钥保存 - Active Storage with Amazon S3 not saving with filename specified but using file key instead 单击链接以删除 Active Storage 和 Amazon S3 上的附件 - Click a link to remove an attachment on Active Storage & Amazon S3 如何在 Ruby on Rails Active Storage 上为 S3 设置传输加速 - How to Setup Transfer Acceleration for S3 on Ruby on Rails Active Storage Heroku 主动存储 S3 Seahorse::Client::NetworkingError (Net::OpenTimeout) - Heroku active storage S3 Seahorse::Client::NetworkingError (Net::OpenTimeout) Rails 6 Active storage sidekiq 文件在 S3 上上传背景图片 - Rails 6 Active storage sidekiq file upload background image on S3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM