防止机器人访问 rails active_storage 图像

Prevent bots from accessing rails active_storage images

我的网站有大量图表,每天都会在有新数据可用时重新计算这些图表。这些图表使用 active_storage 存储在 Amazon S3 上。一个典型的例子是

# app/models/graph.rb
class Graph < ApplicationRecord
  has_one_attached :plot
end

并在视图中

<%= image_tag graphs.latest.plot %>

其中 graphs.latest 检索最新图表。每天都会创建一个新图表和附加图,并删除旧的 graph/plot。

包括来自 Google 和 Yandex 在内的许多机器人正在为图表编制索引,但是当机器人 returns 并再次通过

之类的网址访问图像时会生成异常
www.myapp.com/rails/active_storage/representations/somelonghash

有没有办法为删除 graph/plot 然后重新计算时不会过期的情节生成持久的 link。如果做不到这一点,是否有办法阻止机器人访问这些地块。

请注意,我目前在 routes.rb 文件的末尾有一个总称:

get '*all', to: 'application#route_not_found', constraints: lambda { |req|
      req.path.exclude? 'rails/active_storage'
    } if Rails.env.production?

在 catchall 中排除活动存储是对此 issue 的回应。删除 active_storage 豁免很诱人,但这可能会停止正确的 active_storage 路由。

也许我可以在 rack_rewrite.rb 中添加一些东西来解决这个问题?

你试过了吗?

file /robots.txt put中:

User-agent: *
Disallow: /rails/active_storage*

有趣的问题。

一个简单的解决方案是使用 send_data 功能直接发送图像。但是,这可能有其自身的问题,主要是在可能增加服务器带宽使用(并降低服务器性能)方面。但是,如果您不想经历以下关于创建重定向模型和相关逻辑的麻烦,那么您需要这样的解决方案。


原答案

重定向需要设置某种 Redirects::Graph 模型。这基本上可以验证图形是否已被删除并重定向到新图形而不是请求的图形。它有两个字段,一个 old_signed_id (biglonghash) 和一个 new_signed_id.

每次删除

我们需要填充重定向模型,并在每次创建新图时添加一个新条目(我们应该能够以某种方式从 blob 生成 signed_id)。

为了性能,并避免连续进行大量重定向,这可能会导致不同的 error/issue。您必须管理请求更改。 IE:假设您现在有一个重定向 A => B,您删除 B 将其替换为 C 现在您需要一个 A => CB => C(以避免 A => B => C redirect),这条链确实会变得相当长。这可以通过添加新的 signed_id => new_id 索引并执行 Redirects::Graph.where(new_signed_id: old_signed_id).update_all(new_signed_id: new_signed_id) 更新所有相关的旧重定向来有效地处理,每当您重新生成图形时。

控制器本身比较棘手,我能想到的最干净的方法是猴子修补 ActiveStorage::RepresentationsController 添加一个 before_action 来做这样的事情(可能无法按原样工作,参数[:signed_id] 表示路径可能不对):

before_action :redirect_if_needed

def redirect_if_needed
  redirect_model = Redirects::Graph.find_by(old_signed_id: params[:signed_id])
  redirect_to rails_activestorage_representations_path(
    signed_id: redirect_model.new_signed_id
  ) if redirect_model.present?
end

如果您为数据库设置了版本控制(IE:Papertrail gem 或其他),您可以通过一些工作来计算 old_signed_idnew_signed_id并为当前导致错误的网址构建重定向。否则,可悲的是,这种方法只会防止将来的错误,并且可能无法使当前损坏的 url 正常工作。

理想情况下,虽然您会更新 blob 本身以使用新图而不是旧图而不是删除,但不确定 possible/practical。