设计 - 通过电话号码或电子邮件登录

时间:2017-10-03 10:33:11

标签: ruby-on-rails ruby authentication devise

我需要使用电话号码或电子邮件地址登录该应用程序。我正在使用devise 3.5.2进行身份验证。根据这篇文章(Devise sign up either by email or by mobile number),我实现了以下内容。

application_controller.rb

before_action :configure_permitted_parameters, if: :devise_controller?

protected

def configure_permitted_parameters
    added_attrs = [:phone, :email, :password, :password_confirmation, :remember_me]
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(added_attrs) }
    devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(added_attrs) }
    devise_parameter_sanitizer.for(:account_update) { |u| u.permit(added_attrs) }
end

user.rb

attr_accessor :email_confirmation, :login

devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :authentication_keys => [:login]

  def login=(login)
    @login = self.email
  end

  def login
    @login || self.phone || self.email
  end

配置/初始化/ devise.rb

config.authentication_keys = [ :login ]

现在,如果我尝试使用电子邮件或电话号码登录,我将收到未经授权的"错误。样本请求如下。

Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hCUuF5Ja9f37I4ZBSafGvCpgTnF1nKWf+q8aTEv28mW6vx3z+hIietmYjX9vi0/l/bjVqj0jDaV88mvmdXn9Vg==", "user"=>{"email"=>"jen@companyadmin.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Log in"}

 Processing by Devise::SessionsController#create as HTML
 Parameters: {"utf8"=>"✓", "authenticity_token"=>"uRnINI6Bogx3yeAP8WNpZB31jNOWnvvWVhHJg1BMZL2Hg/vQ5sl1i1Vy6zHXT+A9yi0XCN4hU+zQTLgpbsNrjg==", "user"=>{"email"=>"1234567890", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Log in"}

对于这两个请求,响应是

Completed 401 Unauthorized in 2ms

有关如何解决这个问题的想法吗?

2 个答案:

答案 0 :(得分:2)

通过您共享的参数,电话或电子邮件将被发送到email命名的参数。相反它应该是login

如果您的视图代码接受电子邮件或电话号码

<%= f.text_field :email %>
<%= f.text_field :phone %>

然后用

替换它
<%= f.text_field :login %>

这样,发送的参数将是登录,休息将由您的代码处理。让我知道这是否仍然给您错误。请参阅this link。除了使用用户名之外,它实现相同的功能另请注意modifying views。这似乎是你的问题。其他一切似乎都是正确的。

答案 1 :(得分:1)

您应该覆盖默认登录行为。

User.rb(将此代码放在user.rb模型中)

def self.find_for_database_authentication(warden_conditions)
  conditions = warden_conditions.dup
  if login = conditions.delete(:login)
    where(conditions.to_hash).where(["lower(phone) ILIKE '%#{login.downcase}%' OR lower(email) = :value", { :value => login.downcase }]).first
  elsif conditions.has_key?(:phone) || conditions.has_key?(:email)
    where(conditions.to_hash).first
  end
end