RoR Devise: войдите под именем пользователя ИЛИ по электронной почте - PullRequest
59 голосов
/ 08 июня 2010

Как лучше всего разрешить пользователям входить в систему со своим адресом электронной почты ИЛИ своим именем пользователя? Я использую warden + devise для аутентификации. Я думаю, что это, вероятно, не будет слишком сложно сделать, но я думаю, мне нужен какой-то совет здесь, где разместить все необходимое. Возможно, разработчик уже предоставляет эту функцию? Как в config / initializers / devise.rb, вы должны написать:

config.authentication_keys = [ :email, :username ]

Требовать ввода имени пользователя и адреса электронной почты для входа. Но я действительно хочу иметь только одно поле для имени пользователя и адреса электронной почты и требовать только одно из них. Я просто представлю, что с некоторыми изображениями ASCII это должно выглядеть примерно так:

Username or Email:
[____________________]

Password:
[____________________]

[Sign In]

Ответы [ 11 ]

46 голосов
/ 09 июня 2010

Я нашел решение проблемы. Я не совсем доволен (я предпочел бы указать это в инициализаторе), но пока это работает. В пользовательской модели я добавил следующий метод:

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

Как отметили @sguha и @Chetan, еще один замечательный ресурс доступен на официальной вики разработки .

9 голосов
/ 01 июля 2010
def self.find_for_authentication(conditions)
  conditions = ["username = ? or email = ?", conditions[authentication_keys.first], conditions[authentication_keys.first]]
  # raise StandardError, conditions.inspect
  super
end

Используйте их пример!

7 голосов
/ 25 марта 2011

Убедитесь, что вы уже добавили поле имени пользователя и добавили имя пользователя в attr_accessible. Создайте виртуальный атрибут входа в Users

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 для использования: войдите в аутентификационные ключи

Измените config / initializers / devise.rb, чтобы иметь:

config.authentication_keys = [ :login ]

Перезаписать Devise метод find_for_database_authentication в Users

# 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 %>
2 голосов
/ 19 октября 2011

Platforma Tec (автор разработки) опубликовал решение для своей вики-страницы github, которое использует базовую стратегию аутентификации Warden, а не подключается к контроллеру:

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

(более ранний ответ содержал неработающую ссылку, которая, как мне кажется, была предназначена для ссылки на этот ресурс.)

2 голосов
/ 13 марта 2011

https://gist.github.com/867932: одно решение для всего. Войдите, забыл пароль, подтверждение, инструкция по разблокировке.

1 голос
/ 14 августа 2013

Я использую быстрый взлом для этого, чтобы не изменять какой-либо конкретный код и использовать его для моего конкретного сценария (особенно я использую его для 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, были созданы с использованием имени пользователя.

1 голос
/ 25 апреля 2013

Я написал так, и это работает. Не знаю, будет ли это "некрасиво", но если я найду лучшее решение, я дам тебе знать ...

 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
1 голос
/ 07 марта 2013

Вот решение Rails, которое рефакторирует ответ @ padde. Он использует ActiveRecord find_by для упрощения вызовов, обеспечивает только один вызов на основе регулярного выражения, а также поддерживает числовые идентификаторы, если вы хотите это разрешить (полезно для скриптов / 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

Как и ответы вики и @ aku, я бы также рекомендовал создать новый параметр: login, используя attr_accessible и authentication_keys вместо использования: email здесь. (Я сохранил это как: электронная почта в примере, чтобы показать быстрое исправление.)

1 голос
/ 13 июня 2012

С squeel gem вы можете сделать:

  def self.find_for_authentication(conditions={})
    self.where{(email == conditions[:email]) | (username == conditions[:email])}.first
  end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...