让用户使用他们的电子邮件地址或用户名登录的最佳方法是什么?我正在使用warden + devise进行身份验证。我认为这可能不会太难,但我想我需要一些建议,在哪里放置所需的所有东西。也许设计已经提供了这个功能?就像在config / initializers / devise.rb中一样,你会写:
config.authentication_keys = [ :email, :username ]
要求用户名和电子邮件都可以登录。但我真的想只为用户名和电子邮件设置一个字段,并且只需要其中一个字段。我只是想象一下使用某些ASCII艺术,它应该在视图中看起来像这样:
Username or Email:
[____________________]
Password:
[____________________]
[Sign In]
答案 0 :(得分:46)
我找到了解决问题的方法。我对它不太满意(我宁愿在初始化程序中指定它),但它现在有效。在用户模型中,我添加了以下方法:
def self.find_for_database_authentication(conditions={})
find_by(username: conditions[:email]) || find_by(email: conditions[:email])
end
正如@sguha和@Chetan指出的那样,another great resource is available on the official devise wiki。
答案 1 :(得分:25)
答案 2 :(得分: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
答案 3 :(得分: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
告诉Devise使用:登录authentication_keys
修改config / initializers / devise.rb以获得:
config.authentication_keys = [ :login ]
在用户
中覆盖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
更新您的观点 确保您在项目中拥有Devise视图,以便自定义它们
remove <%= f.label :email %> remove <%= f.email_field :email %> add <%= f.label :login %> add <%= f.text_field :login %>
答案 4 :(得分:2)
https://gist.github.com/867932:一切解决方案。登录,忘记密码,确认,解锁说明。
答案 5 :(得分:2)
Platforma Tec(设计作者)已经向他们的github wiki发布了一个解决方案,该解决方案使用基础Warden身份验证策略而不是插入Controller:
(之前的答案有一个断开的链接,我相信这个链接可以链接到这个资源。)
答案 6 :(得分:1)
如果您使用 MongoDB (使用MongoId),则需要进行不同的查询:
def self.find_for_database_authentication(conditions={})
self.any_of({name: conditions[:email]},{email: conditions[:email]}).limit(1).first
end
就这样它会在某个地方上线。
答案 7 :(得分:1)
使用 squeel gem,您可以执行以下操作:
def self.find_for_authentication(conditions={})
self.where{(email == conditions[:email]) | (username == conditions[:email])}.first
end
答案 8 :(得分:1)
这是一个Rails解决方案,它重构了@ padde的答案。它使用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而不是使用:email here来创建一个新的:login参数。 (我将其保留为:示例中的电子邮件以显示快速修复。)
答案 9 :(得分: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
答案 10 :(得分: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结尾的电子邮件用户是使用用户名创建的。