Nice programing

RoR Devise : 사용자 이름 또는 이메일로 로그인

nicepro 2020. 12. 8. 19:59
반응형

RoR Devise : 사용자 이름 또는 이메일로 로그인


사용자가 이메일 주소 또는 사용자 이름으로 로그인 할 수 있도록하는 가장 좋은 방법은 무엇입니까? 나는 인증을 위해 warden + devise를 사용하고 있습니다. 나는 그것을하는 것이 너무 어렵지 않을 것이라고 생각하지만 필요한 모든 것을 어디에 둘 것인지에 대한 조언이 필요하다고 생각합니다. 아마도 devise는 이미이 기능을 제공하고 있습니까? config / initializers / devise.rb 에서처럼 다음과 같이 작성합니다.

config.authentication_keys = [ :email, :username ]

로그인을 위해 사용자 이름과 이메일을 모두 요구합니다.하지만 사용자 이름과 이메일 모두에 대해 하나의 필드 만 있고 그중 하나만 요구하고 싶습니다. ASCII 아트를 사용하여 시각화하면 뷰에서 다음과 같이 보일 것입니다.

Username or Email:
[____________________]

Password:
[____________________]

[Sign In]

문제에 대한 해결책을 찾았습니다. 나는 그것에 만족하지 않지만 (차라리 이니셜 라이저에서 이것을 지정하는 방법을 갖고 싶습니다) 지금은 작동합니다. 사용자 모델에서 다음 방법을 추가했습니다.

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

@sguha와 @Chetan이 지적했듯이 공식 devise wiki에서 또 다른 훌륭한 리소스를 사용할 수 있습니다 .


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에 사용자 이름을 추가하십시오. 사용자에서 로그인 가상 속성 만들기

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에 : login을 사용하도록 지시하십시오.

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

https://gist.github.com/867932 : 모든 것을위한 하나의 솔루션. 로그인, 비밀번호 분실, 확인, 잠금 해제 지침.


Platforma Tec (개발자)는 컨트롤러에 연결하는 대신 기본 Warden 인증 전략을 사용하는 솔루션을 github wiki에 게시했습니다.

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 gem을 사용하면 다음을 수행 할 수 있습니다.

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

I wrote like this and it works out. Don't know if it's "ugly fix", but if I'll come up with a a better solution I'll let you know...

 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

I use a quick hack for this, to avoid changing any devise specific code and use it for my specific scenario (I particularly use it for an API where mobile apps can create users on the server).

I have added a before_filter to all the devise controllers where if username is being passed, I generate an email from the username ("#{params[:user][:username]}@mycustomdomain.com") and save the user. For all other calls as well, I generate the email based on same logic. My before_filter looks like this:

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

I am also saving username in the users table, so I know that users with email ending in @mycustomdomain.com were created using username.


Here's a Rails solution which refactors @padde's answer. It uses ActiveRecord's find_by to simplify the calls, ensures there's only one call based on the regex, and also supports numeric IDs if you want to allow that (useful for scripts/APIs). The regex for email is as simple as it needs to be in this context; just checking for the presence of an @ as I assume your username validtor doesn't allow @ characters.

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

Like the wiki and @aku's answer, I'd also recommend making a new :login parameter using attr_accessible and authentication_keys instead of using :email here. (I kept it as :email in the example to show the quick fix.)

참고URL : https://stackoverflow.com/questions/2997179/ror-devise-sign-in-with-username-or-email

반응형