【问题标题】:Rails 4/Devise/MongoDB: "Unpermitted parameters" using custom properties and strong parametersRails 4/Devise/MongoDB:使用自定义属性和强参数的“未经许可的参数”
【发布时间】:2013-04-14 05:16:00
【问题描述】:

尝试将嵌套自定义属性 Profile(Mongoid 文档)添加到我的设计 User 类。提交 Devise 注册表单时,它应该同时创建一个 User 和一个相应的 Profile 对象。

我希望最终结果在我的 MongoDB 中看起来像这样:

用户:

{
  # Devise fields:
  "email": "my@email.com",
  ...
  # Custom field
  "profile" : "<object_id>"
}

简介:

{
  "first_name": "Dave",
  ....
}

很遗憾,每当我提交注册时,我都会在控制台中收到此信息。它成功创建了一个用户,但未能创建关联的配置文件。

Started POST "/" for 127.0.0.1 at 2013-04-20 23:37:10 -0400
Processing by Users::RegistrationsController#create as HTML
Parameters:
   {"utf8"=>"✓",
   "authenticity_token"=>"awN2GU8EYEfisU0",
   "user"=>
       {"profile_attributes"=>
           {"first_name"=>"Dave",
           "birthday(2i)"=>"4",
           "birthday(3i)"=>"21",
           "birthday(1i)"=>"1933",
           "occupation_title"=>"Software Developer"},
        "password"=>"[FILTERED]",
        "password_confirmation"=>"[FILTERED]",
        "email"=>"my@email.com"}}
Unpermitted parameters: profile_attributes

我已经设置好了:

  • Rails 4.0.0beta1,Ruby 2.0.0-p0
  • 设计('rails4' 分支),Mongoid(来自 git)
  • 自定义设计注册控制器,用于添加强参数的定义。

models/user.rb:

class User
  include Mongoid::Document

  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable,
     :token_authenticatable, :confirmable, :lockable, :timeoutable

  field :email,              type: String, default: ''

  ...

  has_one :profile
  accepts_nested_attributes_for :profile
end

models/profile.rb:

class Profile
  include Mongoid::Document
  include Mongoid::Timestamps

  # Attributes
  # ----------
  field :slug,                type: String, default: '' # Acts as user-'friendlier' slug
  field :birthday,            type: DateTime, default: DateTime.now
  field :first_name,          type: String, default: ''
  field :occupation_title,    type: String, default: ''

  belongs_to :user
  embeds_many :photos
  has_one :occupation_industry, :as => :industry
end

controllers/users/registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController

  def resource_params
    params.require(:user).permit(:email, :password, :password_confirmation, :profile_attributes)
  end
  private :resource_params
end

routes.rb

devise_for  :users,
              :path => '',
              :path_names => {
                :sign_in => 'login',
                :sign_out => 'logout',
                :sign_up => 'register'
                },
              :controllers => {
                :registrations => "users/registrations",
                :passwords => "users/passwords"
              }

我已经看过这些相关的帖子,它们似乎没有帮助:


编辑:

看起来 Devise 确实在其“rails4”分支中支持强参数(应该在几天内合并到 master 中。)查看代码,您似乎可以为 devise 上的每个操作覆盖 params 函数控制器。对于创建新用户,在我的示例中使用 sign_up_params 而不是 resource_params

尽管将此名称更改为正确的名称,但它仍然不起作用...仅使用此 bang 将所有参数列入白名单似乎有效:

def sign_up_params
  params.require(:user).permit!
end

显然,这种方式违背了强参数的目的......所以现在的问题是我如何允许我的嵌套属性profile_attributes(如我原来的问题所示)?

【问题讨论】:

    标签: ruby-on-rails mongodb devise ruby-on-rails-4 strong-parameters


    【解决方案1】:

    我遇到了完全相同的问题,覆盖 sign_up_params 确实对我有用

    def sign_up_params
       params.require(:user).permit(:email, :password, :password_confirmation, :other, :etc)
    end
    

    当然,不同之处在于我的只是标量值,而您正在尝试批量分配关系...我想这就是您应该寻找的地方。

    顺便说一句,这个主题中的文档仍然不存在(太新),并且代码注释建议覆盖devise_parameter_sanitizer,这不是必需的。

    【讨论】:

    • 在继承自 Devise::RegistrationsController 的类中,这就是您覆盖/扩展它的方式
    • 是的,这就是这样做的方法......对于哈希(如我的profile_attributes),您需要通过设计明确指定每个嵌入属性。即它看起来像:params.require(:user).permit(:email, :password, :password_confirmation, profile_attributes: [:first_name, :occupation_title])
    【解决方案2】:

    我找到了一种不同的方法,它允许所有设计覆盖逻辑和代码驻留在应用程序控制器中。这允许为每个设计操作(登录、注册、更新)传递任何和所有自定义参数。我还为 devise_invitable 添加了一个参数清理程序并在此处处理该逻辑(邀请,accept_invitation)。我有自定义参数,如 avatar、avatar_cache 等:

    #application_controller.rb
    
      before_filter :configure_permitted_parameters, if: :devise_controller?
    
    protected
      # There are just three actions in Devise that allows any set of parameters to be passed down to the model, 
      # therefore requiring sanitization. Their names and the permited parameters by default are:
    
      # sign_in (Devise::SessionsController#new) - Permits only the authentication keys (like email)
      # sign_up (Devise::RegistrationsController#create) - Permits authentication keys plus password and password_confirmation
      # account_update (Devise::RegistrationsController#update) - Permits authentication keys plus password, password_confirmation 
      # and current_password. More at https://github.com/plataformatec/devise#strong-parameters
    
      def configure_permitted_parameters
        devise_parameter_sanitizer.for(:accept_invitation) do |u|
          u.permit(:username,:validate_username, :password,:password_confirmation, :invitation_token)
        end
        devise_parameter_sanitizer.for(:invite) do |u|
          u.permit(:name,:comments)
        end
    
        devise_parameter_sanitizer.for(:sign_up) do |u|
          u.permit(:username,:password,:password_confirmation)
        end
        devise_parameter_sanitizer.for(:sign_in) do |u|
          u.permit(:username,:email,:password,:password_confirmation,:phone, :validate_username, :avatar_cache, :remove_avatar, :current_password,:remember_me)
        end
    
        devise_parameter_sanitizer.for(:account_update) do |u|
          u.permit(:username,:email,:password,:password_confirmation,:phone, :validate_username,:avatar, :avatar_cache, :remove_avatar, :current_password)
        end
      end
    

    https://github.com/plataformatec/devise#strong-parameters查找和阅读更多信息

    【讨论】:

      【解决方案3】:

      我在登录时遇到了同样的问题,它说:Unpermitted parameters: password, remember_me。 并且因为我有任何继承 Devise::SessionsController 的控制器,所以我使用自己的 parameter sanitizer

      这是我的工作:

      在 '#{Rails.root}/lib' 文件夹中创建一个文件,我是 hzsapa_parameter_sanitizer.rb 并且在 config/application.rb 中是必需的,然后在 中覆盖 devise_parameter_sanitizer 方法application_controller.rb

      lib/hzsapa_parameter_sanitizer.rb

      class HzsapaParameterSanitizer < Devise::ParameterSanitizer
        def sign_in
          default_params.permit(auth_keys + [:password, :remember_me])
        end
      end
      

      您可以根据您的问题覆盖这些方法:

      def sign_in
        default_params.permit(auth_keys)
      end
      
      def sign_up
        default_params.permit(auth_keys + [:password, :password_confirmation])
      end
      
      def account_update
        default_params.permit(auth_keys + [:password, :password_confirmation,    :current_password])
      end
      

      config/application.rb

      require "hzsapa_parameter_sanitizer"
      

      app/application_controller.rb

      class ApplicationController < ActionController::Base
        # Prevent CSRF attacks by raising an exception.
        # For APIs, you may want to use :null_session instead.
        protect_from_forgery with: :exception
      
        def devise_parameter_sanitizer
          @devise_parameter_sanitizer ||= if defined?(ActionController::StrongParameters)
                                            HzsapaParameterSanitizer.new(resource_class, resource_name, params)
                                          else
                                            Devise::BaseSanitizer.new(resource_class, resource_name, params)
                                          end
        end
      end
      

      编辑:我刚刚在设计自述文件中找到了解决方案,你可以关注它here

      【讨论】:

        【解决方案4】:

        我使用了你的代码,它对我有用!

        这就是我所做的

        class RegistrationsController < Devise::RegistrationsController
          skip_before_filter :verify_authenticity_token, :only => :create #, :if => Proc.new { |c| c.request.format == 'application/json' }
          respond_to :json, :html, :xml
        
          def create
            user = User.new(devise_registrations_permitted_parameters)
            if user.save
              render :json=> user.as_json(:auth_token=>user.authentication_token, :email=>user.email,:name => user.name), :status=>201
              return
            else
              warden.custom_failure!
              render :json=> user.errors, :status=>422
            end
          end
        
        
          protected                                                            
            def devise_registrations_permitted_parameters
              params.require(:user).permit(:name, :email, :password, :password_confirmation)
            end
        
        end
        

        【讨论】:

          猜你喜欢
          • 2013-07-18
          • 1970-01-01
          • 1970-01-01
          • 2012-12-11
          • 2016-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多