RoR Devise: войдите в систему с именем пользователя или электронной почтой
каков наилучший способ разрешить пользователям входить в систему с помощью своего адреса электронной почты или имени пользователя? Я использую warden + devise для аутентификации. Я думаю, что это, вероятно, не будет слишком трудно сделать это, но я думаю, что мне нужен совет здесь о том, где положить все, что нужно. Возможно, devise уже предоставляет эту функцию? Как в config/инициализаторы/разработать.РБ вы бы написали:
config.authentication_keys = [ :email, :username ]
для входа в систему требуется как имя пользователя, так и электронная почта. Но я действительно хочу иметь только один поле для имени пользователя и электронной почты и требуется только один из них. Я просто визуализирую, что с некоторым ASCII-искусством это должно выглядеть примерно так:
Username or Email:
[____________________]
Password:
[____________________]
[Sign In]
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 :login2) Добавить логин в 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, а не подключается к контроллеру:
(в более раннем ответе была сломана ссылка, которая, как я считаю, была предназначена для ссылки на этот ресурс.)
Если вы используете 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