【问题标题】:csrf_meta_tags and form_for generate invalid base64 on Herokucsrf_meta_tags 和 form_for 在 Heroku 上生成无效的 base64
【发布时间】:2021-02-01 07:39:08
【问题描述】:

我正在使用 ruby​​ 2.7.1 和 rails 6.0.3.4 并在尝试调用 csrf_meta_tagsform_for 时遇到以下错误

2021-02-01T07:25:10.058892+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab] ActionView::Template::Error (invalid base64):
2021-02-01T07:25:10.058893+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     1: <h2>Log in</h2>
2021-02-01T07:25:10.058894+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     2:
2021-02-01T07:25:10.058895+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     3: <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
2021-02-01T07:25:10.058895+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     4:   <div class="field">
2021-02-01T07:25:10.058896+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     5:     <%= f.label :email %><br />
2021-02-01T07:25:10.058898+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]     6:     <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
2021-02-01T07:25:10.058899+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab]
2021-02-01T07:25:10.058899+00:00 app[web.1]: [9c50e00c-9868-45dc-89d8-1ec8f42d56ab] app/views/devise/sessions/new.html.erb:3

我只有在部署到 Heroku 时才会在生产环境中出现此错误。在开发中,真实性令牌生成时没有错误,但由于某种原因在 Heroku 上产生了上述错误。知道这里会发生什么吗?

我已尝试缩小导致问题的行的范围,并且我得到了 form_authenticity_tokenmasked_authenticity_token 但到目前为止我无法追踪哪些行是问题所在。

其他一些可能相关的版本:

Gemfile.lock
------------
webpacker (4.3.0)

yarn.lock
---------
@rails/webpacker@4.3.0

我试过简单地省略csrf_meta_tags,但我仍然在表单上遇到错误,如上所示。我找不到其他有相同问题的参考资料,因此非常感谢您的帮助。

【问题讨论】:

  • ruby 2.6.5 rails 6.0.3 在生产中遇到同样的错误(不是 heroku)。格林威治标准时间 7:00 左右开始。
  • 你的 'webpacker' 版本是什么?
  • @MichałCzapko 我更新了描述。根据 Gemfile.lock 和 yarn.lock 文件,开发和生产似乎都在使用 webpacker 4.3.0。
  • 我不使用 webpacker。
  • 我遇到了类似的问题,当我重新部署没有 CSRF 标记的应用程序并再次使用之前不起作用的相同代码时,它会自动修复。

标签: heroku ruby-on-rails-6


【解决方案1】:

在我们的服务器上,这个问题是由将 Rails 从 6.1 降级到 6.0.3 引起的。

首先,我们尝试将 Rails 从 6.0.3 升级到 6.1,但错过了一些必要的更改以使迁移成功,因此不得不恢复到 6.0.3。然而,在我们的应用程序在 Rails 6.1 上运行期间,我们处理了许多用户请求并生成了新的 csrf 令牌。问题是,Rails 6.1 有不同的 csrf 令牌生成算法,当我们恢复到 Rails 6.0.3 时,Rails 6.1 生成的令牌无法验证。

为了缓解问题并避免向用户显示错误,我们修饰了 csrf 生成函数以捕获上述错误并重置会话,以便生成与 Rails 6.0.3 兼容的令牌。

def rescued_csrf_meta_tags
  csrf_meta_tags
rescue ArgumentError
  request.reset_session
  csrf_meta_tags
end

其他服务器信息:

  • Ubuntu 16.04
  • Ruby 2.6.5

编辑:正如@cecomp64 在评论中所写,另一个解决方案是清除浏览器缓存。显然,如果您的应用有很多用户,这将不容易实现。

【讨论】:

  • 这正是问题所在!我还联系了 Heroku 支持,他们建议简单地清除我浏览器中的缓存和 cookie,这也有效。我知道如果你有一个成熟的应用程序,你不想建议你的所有用户都这样做,但对我来说,清除缓存就足够了。您能否添加“清除缓存”解决方法,我会接受答案?
  • 缓存清除效果很好。你把装饰器放在哪里?
  • 顺便说一句,仅清除缓存对我来说还不够。我也必须清除 cookie。这是我实际上只在 Chrome 上看到的问题。
【解决方案2】:

这是因为 Rails 5 和 6 之间的 csrf token 生成不兼容(不同的算法),因此,您需要一个函数来生成新的加密来处理上述兼容性错误。 p>

您的application_controller.rb

protect_from_forgery with: :exception

head 标签中的 application.html.erb

<%= csrf_meta_tags %>

您的 application_helper.rbcsrf_helper.rb

def csrf_meta_tags
  if defined?(protect_against_forgery?) && protect_against_forgery?
    [
      tag("meta", name: "csrf-param", content: request_forgery_protection_token),
      tag("meta", name: "csrf-token", content: form_authenticity_token)
    ].join("\n").html_safe
  end
end

【讨论】:

    猜你喜欢
    • 2013-08-17
    • 1970-01-01
    • 2017-03-14
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多