我的 Rails 应用程序中有一个奇怪的错误,该错误是由某人可能做了他们不应该做的事情而触发的。但我不知道他们可能在做什么,从而如何防范。
当前设置是 Rails 7.1.3.2、Ruby 3.3.1,尽管我已经看到它好几个月了,包括回到 Rails 7.0 和 Ruby 3.2
最终,我收到以下错误:
ActionController::ParameterMissing: param is missing or the value is empty: organization
形式比较简单
<form action="/o" accept-charset="UTF-8" method="post">
<input type="hidden" name="authenticity_token" value="...">
<label for="organization_a1">A1</label>
<input required="required" type="text" name="organization[a1]" id="organization_a1">
<label for="organization_a2">A2</label>
<input type="text" name="organization[email_domain]" id="organization_a2">
<input type="submit" name="commit" value="Continue" data-disable-with="Continue">
</form>
...
控制器中也没有发生任何奇怪的事情。
def create
@organization = Organization.create(organization_params)
redirect_to start_home_index_path
end
def organization_params
params.require(:organization).permit(:a1, :a2, ...)
end
第一个请求通过并重定向得很好,第二个请求在
params.require
调用上失败
如果我查看日志,我会收到以下请求序列。
INFO -- Started POST "/o" for 47.238.233.78 at 2024-05-14 17:37:48 +0000
Processing by OrganizationsController#create as */*
INFO -- Parameters: {"authenticity_token"=>"[FILTERED]", "organization"=>{"a1"=>"v1", "a2"=>"v2"}
, "commit"=>"Continue"}
INFO -- <successful redirect>
...
INFO -- Started POST "/o" for 47.238.233.78 at 2024-05-14 17:37:51 +0000
INFO -- Processing by OrganizationsController#create as */*
INFO -- Parameters: {"authenticity_token"=>"[FILTERED]", "organization[a1]"=>"v1", "organization[a2]"=>"v2", "commit"=>"Continue", "organization"=>{}}
INFO -- Completed 400 Bad Request in 1ms
ERROR -- ActionController::ParameterMissing (param is missing or the value is empty: organization)
...
所以我可以在 Rails 日志中看到指向
{}
的空组织,但是如果我查看错误中的请求正文,它会显示为
..."organization[a1]":"v1","organization[a2]:"v2"..."
没有像 "organization":""
这样奇怪的空作业
您可以在日志中看到,这似乎是某人(同一IP地址)在3秒内提交了两次表单。第一次成功,第二次失败。
我尝试了多种不同的方法来重新创建它,包括在提交之前更改表单中的authenticity_token隐藏字段(奇怪的是,rails没有这方面的问题)。还可以使用curl多次重新提交相同的请求(没问题)。如果我更改会话 cookie 的值,这确实会导致 Rails 出现错误,但会导致不同的错误(无法验证 CSRF 令牌的真实性)。
那么什么会导致 Rails 出现这种情况呢?我当然可以通过多种不同的方式处理这个错误,但我想了解用户如何触发 Rails 以这种方式执行操作。
您可以只使用简单的表单助手,他们会发送有效的参数
<%= form_with model: Organization.new, url: organizations_path, method: :post do |form| %>
<%= form.label :a1, 'A1' %>
<%= form.text_field :a1 %>
<%= form.label :a2, 'A2' %>
<%= form.text_field :a2 %>
<%= form.submit 'Continue' %>
<% end %>