RoR Devise: войдите в систему с именем пользователя или электронной почтой



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



config.authentication_keys = [ :email, :username ]


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



Username or Email:
[____________________]

Password:
[____________________]

[Sign In]
675   11  

11 ответов:

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

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

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

def self.find_for_authentication(conditions)
  conditions = ["username = ? or email = ?", conditions[authentication_keys.first], conditions[authentication_keys.first]]
  # raise StandardError, conditions.inspect
  super
end

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

убедитесь, что вы уже добавили поле "Имя пользователя" и добавить имя пользователя в 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 использовать: вход в authentication_keys

изменить в config/инициализаторы/разработать.РБ иметь:

config.authentication_keys = [ :login ]

перезаписать метод Find_for_database_authentication Devise в Пользователи

# 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 %>

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

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

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

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

Если вы используете MongoDB (С MongoId), вам нужно запросить по-разному:

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

просто так будет где-то в интернете.

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

  def self.find_for_authentication(conditions={})
    self.where{(email == conditions[:email]) | (username == conditions[:email])}.first
  end

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

 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

Я использую быстрый хак для этого, чтобы избежать изменения любого конкретного кода devise и использовать его для моего конкретного сценария (я особенно использую его для API, где мобильные приложения могут создавать пользователей на сервере).

Я добавил before_filter ко всем контроллерам devise, где, если имя пользователя передается, я генерирую электронное письмо от имени пользователя ("#{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

Я также сохраняю имя пользователя в таблице users, поэтому я знаю, что пользователи с электронной почтой заканчиваются на @mycustomdomain.com были созданы с использованием имени пользователя.

вот решение, рельсы, которая обрабатывает ответ @гребными по. Он использует Find_by ActiveRecord для упрощения вызовов, гарантирует, что есть только один вызов на основе регулярного выражения, а также поддерживает числовые идентификаторы, если вы хотите разрешить это (полезно для скриптов/API). Регулярное выражение для электронной почты так же просто, как и должно быть в этом контексте; просто проверка наличия@, поскольку я предполагаю, что ваше имя пользователя validtor не позволяет @ символов.

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

Comments

    Ничего не найдено.