设计3.5.2,Rails 4.2.3
登录时,我尝试将隐藏的role_id与电子邮件/密码组合一起传递。我允许相同的电子邮件再次在另一个子域上注册,这会导致传递不同的role_id。电子邮件+ role_id是用户的唯一索引。
我可以创建一个用户,但无法登录。当我提交登录表单时,我遇到以下错误:
self.view = QTableView(self)
如果有人可以解释将电子邮件唯一性验证更改为电子邮件+ role_id的过程(不是/或,而是和),那就是我需要完成的所有事情。正确地执行该过程可以避免此错误。
POST参数如下:
undefined method 'email' for #<ActionDispatch::Request:0x007fa21628bda0>
这是我的会员模特:
{"utf8"=>"✓",
"authenticity_token"=>"[FILTERED]",
"member"=>{"role_id"=>"1",
"email"=>"some.user@email.com",
"password"=>"[FILTERED]",
"remember_me"=>"0"},
"commit"=>"Log in"}
在 config / initializers / devise.rb 中,设置如下:
class Member < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable, :omniauthable
belongs_to :role
def self.find_for_authentication(warden_conditions)
where(:email => warden_conditions[:email], :role_id => warden_conditions[:role_id]).first
end
end
config.authentication_keys = [:email, :role_id]
我的观点/ devise / sessions / new.html.erb包括:
config.request_keys = [:email, :role_id]
我通过更改此行来调整 vendor / bundle / ruby / 1.9.1 / gems / devise-3.5.2 / lib / devise / models / validatable.rb :
<%= f.hidden_field :role_id, :value => Role.find_by_name(current_subdomain).id %>
为:
validates_uniqueness_of :email, allow_blank: true, if: :email_changed?
可在此处找到该成员的相关数据库迁移:
validates_uniqueness_of :email, :scope => :role_id, allow_blank: true, if: :email_changed? #using subdomains for validation
class DeviseCreateMembers < ActiveRecord::Migration
def change
create_table(:members) do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
t.timestamps null: false
end
add_index :members, :email, unique: true
add_index :members, :reset_password_token, unique: true
add_index :members, :confirmation_token, unique: true
add_index :members, :unlock_token, unique: true
end
class AddColumnsToMember < ActiveRecord::Migration
def change
add_reference :members, :contact, index: true
add_reference :members, :role, index: true
add_reference :members, :ownership, index: true
add_column :members, :account_status, :string
end
end
跟踪的最后一项是:
vendor / bundle / ruby / 1.9.1 / gems / devise-3.5.2 / lib / devise / strategies / authenticatable.rb:152:在`block in request_values&#39;
class ReindexMembersEmailAndRole < ActiveRecord::Migration
def change
add_index :members, [:email, :role_id], :unique => true
end
end
答案 0 :(得分:3)
要解决此问题,我更改了config.request_keys = { role_id: false }
以反映以下内容:
:validatable
这解决了问题,但仍然阻止同一封电子邮件使用其他角色ID注册。为解决此问题,我从用户模型中删除了 validates_uniqueness_of :email, :case_sensitive => false, :scope => :role_id, :allow_blank => true, :if => :email_changed?
validates_format_of :email, :with => Devise.email_regexp, :allow_blank => true, :if => :email_changed?
validates_presence_of :password, :on=>:create
validates_confirmation_of :password, :on=>:create
validates_length_of :password, :within => Devise.password_length, :allow_blank => true
并添加了:
def request_values
keys = request_keys.respond_to?(:keys) ? request_keys.keys : request_keys
values = keys.map { |k| self.request[self.scope][k] }
# values = keys.map { |k| self.request.send(k) }
Hash[keys.zip(values)]
end
这允许使用不同的role_id注册相同的电子邮件地址。
我还在authenticatable.rb中更改了以下内容:
# config.request_keys = { role_id: false }
<强>更新强>
我厌倦了总是不得不重新破解设计库,特别是在我更新了宝石或转移应用程序之后。我发现这个页面提供了更好的解决方法(仍然遵循上面列出的用户模型的验证步骤):
(来自IFNULL)
注释掉我们上面编辑的以下行:
config.authentication_keys
按如下方式编辑config.authentication_keys = { email: true, role_id: false }
行:
request_keys
问题是:subdomain
仅尊重预定义的密钥,例如{{1}}。
现在应该可以创建自定义密钥组合以进行身份验证。