csrf_meta_tags 和 form_for 在 Heroku 上生成无效的 base64
csrf_meta_tags and form_for generate invalid base64 on Heroku
我正在使用 ruby 2.7.1 和 rails 6.0.3.4,每当我尝试调用 csrf_meta_tags
或 form_for
[=19= 时遇到以下错误]
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_token
和 masked_authenticity_token
但到目前为止我还无法追踪到哪些行是问题。
其他一些可能相关的版本:
Gemfile.lock
------------
webpacker (4.3.0)
yarn.lock
---------
@rails/webpacker@4.3.0
我试过简单地省略 csrf_meta_tags
但我仍然在表格上遇到如上所示的错误。我找不到对其他有相同问题的人的任何参考,因此非常感谢任何帮助。
在我们的服务器上,这个问题是由于 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
其他服务器信息:
- Ubuntu16.04
- Ruby 2.6.5
编辑:正如@cecomp64 在评论中所写,另一种解决方案是清除浏览器缓存。显然,如果您的应用有很多用户,这将不容易实现。
这是因为 Rails5 和 6 之间的 csrf token 生成不兼容(不同的算法),因此,您需要一个函数来生成新的加密处理上述兼容性错误。
你的application_controller.rb:
protect_from_forgery with: :exception
你的 application.html.erb 在 head 标签中:
<%= csrf_meta_tags %>
你的application_helper.rb或csrf_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
请参考
https://github.com/mperham/sidekiq/issues/5273
# config/initializers/sidekiq.rb
require 'sidekiq/web'
Sidekiq::Web::CsrfProtection.define_method(:decode_token) do |token|
Base64.urlsafe_decode64(token)
end
Sidekiq::Web::CsrfProtection.define_method(:encode_token) do |token|
Base64.urlsafe_encode64(token)
end
我正在使用 ruby 2.7.1 和 rails 6.0.3.4,每当我尝试调用 csrf_meta_tags
或 form_for
[=19= 时遇到以下错误]
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_token
和 masked_authenticity_token
但到目前为止我还无法追踪到哪些行是问题。
其他一些可能相关的版本:
Gemfile.lock
------------
webpacker (4.3.0)
yarn.lock
---------
@rails/webpacker@4.3.0
我试过简单地省略 csrf_meta_tags
但我仍然在表格上遇到如上所示的错误。我找不到对其他有相同问题的人的任何参考,因此非常感谢任何帮助。
在我们的服务器上,这个问题是由于 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
其他服务器信息:
- Ubuntu16.04
- Ruby 2.6.5
编辑:正如@cecomp64 在评论中所写,另一种解决方案是清除浏览器缓存。显然,如果您的应用有很多用户,这将不容易实现。
这是因为 Rails5 和 6 之间的 csrf token 生成不兼容(不同的算法),因此,您需要一个函数来生成新的加密处理上述兼容性错误。
你的application_controller.rb:
protect_from_forgery with: :exception
你的 application.html.erb 在 head 标签中:
<%= csrf_meta_tags %>
你的application_helper.rb或csrf_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
请参考
https://github.com/mperham/sidekiq/issues/5273
# config/initializers/sidekiq.rb
require 'sidekiq/web'
Sidekiq::Web::CsrfProtection.define_method(:decode_token) do |token|
Base64.urlsafe_decode64(token)
end
Sidekiq::Web::CsrfProtection.define_method(:encode_token) do |token|
Base64.urlsafe_encode64(token)
end