61

让用户使用他们的电子邮件地址或用户名登录的最佳方式是什么?我正在使用warden + devise 进行身份验证。我认为这可能不会太难,但我想我需要一些建议,将所有需要的东西放在哪里。也许设计已经提供了这个功能?就像在 config/initializers/devise.rb 你会写:

config.authentication_keys = [ :email, :username ]

需要用户名和电子邮件才能登录。但我真的希望用户名和电子邮件只有一个字段,并且只需要其中一个。我将通过一些 ASCII 艺术形象化它,它在视图中应该看起来像这样:

Username or Email:
[____________________]

Password:
[____________________]

[Sign In]
4

11 回答 11

47

我找到了解决问题的方法。我对它不太满意(我宁愿有一种在初始化程序中指定它的方法),但它现在可以工作。在用户模型中,我添加了以下方法:

def self.find_for_database_authentication(conditions={})
  find_by(username: conditions[:email]) || find_by(email: conditions[:email])
end

正如@sguha 和@Chetan 所指出的,官方设计wiki 上提供了另一个很好的资源

于 2010-06-08T23:04:37.333 回答
26

从他们的 Wiki —如何:允许用户使用他们的用户名或电子邮件地址登录

于 2011-08-10T04:14:53.740 回答
9
def self.find_for_authentication(conditions)
  conditions = ["username = ? or email = ?", conditions[authentication_keys.first], conditions[authentication_keys.first]]
  # raise StandardError, conditions.inspect
  super
end

用他们的例子!

于 2010-07-01T10:42:37.920 回答
7

确保您已经添加了用户名字段并将用户名添加到 attr_accessible。在用户中创建登录虚拟属性

1) 添加登录作为 attr_accessor

# Virtual attribute for authenticating by either username or email
# This is in addition to a real persisted field like 'username'
attr_accessor :login

2) 添加登录到 attr_accessible

attr_accessible :login

告诉设计在 authentication_keys 中使用 :login

修改 config/initializers/devise.rb 以具有:

config.authentication_keys = [ :login ]

在 Users 中覆盖 Devise 的 find_for_database_authentication 方法

# Overrides the devise method find_for_authentication
# Allow users to Sign In using their username or email address
def self.find_for_authentication(conditions)
  login = conditions.delete(:login)
  where(conditions).where(["username = :value OR email = :value", { :value => login }]).first
end

更新您的视图确保您的项目中有设计视图,以便您可以自定义它们

remove <%= f.label :email %>
remove <%= f.email_field :email %>
add <%= f.label :login %>   
add <%= f.text_field :login %>
于 2011-03-25T04:20:24.783 回答
2

https://gist.github.com/867932:一个解决方案。登录、忘记密码、确认、解锁说明。

于 2011-03-13T06:48:17.097 回答
2

Platforma Tec(设计作者)在他们的 github wiki 上发布了一个解决方案,该解决方案使用底层 Warden 身份验证策略,而不是插入控制器:

https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

(较早的答案有一个断开的链接,我认为该链接旨在链接到该资源。)

于 2011-10-18T20:46:39.400 回答
1

如果您使用的是MongoDB(带有 MongoId),则需要进行不同的查询:

  def self.find_for_database_authentication(conditions={})
    self.any_of({name: conditions[:email]},{email: conditions[:email]}).limit(1).first
  end

就这样它会在网上的某个地方。

于 2011-10-14T05:16:30.660 回答
1

使用squeel gem,您可以:

  def self.find_for_authentication(conditions={})
    self.where{(email == conditions[:email]) | (username == conditions[:email])}.first
  end
于 2012-06-13T08:05:57.983 回答
1

这是重构@padde 答案的Rails 解决方案。它使用 ActiveRecord 的 find_by 来简化调用,确保只有一个基于正则表达式的调用,并且如果你想允许它还支持数字 ID(对脚本/API 很有用)。电子邮件的正则表达式在这种情况下非常简单;只是检查 @ 的存在,因为我假设您的用户名验证器不允许 @ 字符。

def self.find_for_database_authentication(conditions={})
  email = conditions[:email]
  if email =~ /@/ 
    self.find_by_email(email)
  elsif email.to_s =~ /\A[0-9]+\z/
    self.find(Integer(email))
  else
    self.find_by_username(email])
  end
end

就像 wiki 和 @aku 的回答一样,我还建议使用 attr_accessible 和 authentication_keys 来创建一个新的 :login 参数,而不是在这里使用 :email 。(我在示例中将其保留为 :email 以显示快速修复。)

于 2013-03-07T05:24:53.467 回答
1

我是这样写的,结果很好。不知道这是否是“丑陋的修复”,但如果我想出一个更好的解决方案,我会告诉你......

 def self.authenticate(email, password)
   user = find_by_email(email) ||
     username = find_by_username(email)
   if user && user.password_hash = BCrypt::Engine.hash_secret(password, user.password_salt)
     user
   else
     nil
   end
end
于 2013-04-25T09:23:15.383 回答
1

我为此使用了一个快速技巧,以避免更改任何设计特定的代码并将其用于我的特定场景(我特别将它用于移动应用程序可以在服务器上创建用户的 API)。

我在所有设计控制器中添加了一个 before_filter,如果正在传递用户名,我会从用户名(“#{params[:user][:username]}@mycustomdomain.com”)生成一封电子邮件并保存用户。对于所有其他呼叫,我也根据相同的逻辑生成电子邮件。我的 before_filter 看起来像这样:

def generate_email_for_username
    return if(!params[:user][:email].blank? || params[:user][:username].blank?)
    params[:user][:email] = "#{params[:user][:username]}@mycustomdomain.com"
end

我还将用户名保存在用户表中,所以我知道电子邮件以@mycustomdomain.com 结尾的用户是使用用户名创建的。

于 2013-08-14T12:37:07.933 回答