Rails 5中Devise注册参数为何有时格式异常?
Rails 5自定义Devise注册控制器遭遇异常参数格式问题
我在Rails 5应用中对Devise做了轻度定制:继承Devise::RegistrationsController并为User资源实现了自定义create方法,没有调用super。
正常与异常的参数格式
开发环境下始终、生产环境下绝大多数情况,表单提交后的params格式如下:
{ "utf8"=>"✓", "authenticity_token"=>"***", "user"=> { "email"=>"foo@example.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]" }, "commit"=>"Create account" }
但仅在生产环境中,会出现少数异常情况,此时params格式变为:
{ "utf8"=>"✓", "authenticity_token"=>"***", "user[email]"=>"foo@example.com", "user[password]"=>"[FILTERED]", "user[password_confirmation]"=>"[FILTERED]", "commit"=>"Create account", "registration"=> { "user[email]"=>"foo@example.com", "user[password]"=>"[FILTERED]", "user[password_confirmation]"=>"[FILTERED]", "commit"=>"Create account" } }
自定义的create方法是基于params[:user]为用户属性哈希的假设编写的,这种异常格式会直接导致代码抛出异常。我曾猜测是Devise在特定场景下的处理逻辑不同,但测试验证失败后重提交的场景,并未复现该问题。
提交表单代码(省略样式类)
<%= form_for(@user, as: :user, url: registration_path(:user)) do |f| %> <div class="row"> <%= f.label :email %> <%= f.email_field :email, autofocus: true %> </div> <div class="row"> <%= f.label :password %> <%= f.password_field :password, autocomplete: "off" %> </div> <div class="row"> <%= f.label :password_confirmation, 'Password confirmation' %> <%= f.password_field :password_confirmation, autocomplete: "off" %> </div> <div class="row"> <div> <%= f.submit "Create account" %> </div> </div> <% end %>
排查结论
后续通过日志排查发现:异常请求的request.media_type为application/json(正常请求应为application/x-www-form-urlencoded)。这种错误的媒体类型导致参数未被正确解析,同时结合JSON参数包裹的配置,出现了registration嵌套对象。最终确认,这类异常请求是由机器人发起的——机器人错误地将表单转为不符合Rails规范的JSON格式提交,才引发了参数格式异常。
内容的提问来源于stack exchange,提问作者Pathogen
相关产品推荐
相关产品推荐

