ruby-on-rails rails教學 - RoR Devise:使用用戶名或電子郵件登錄





sign_in new_with_session (11)


我使用快速入侵,以避免更改任何特定設計代碼並將其用於我的特定場景(我特別將其用於移動應用程序可以在服務器上創建用戶的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結尾的電子郵件用戶是使用用戶名創建的。

什麼是讓用戶使用他們的電子郵件地址或用戶名登錄的最佳方式? 我正在使用warden + devise進行身份驗證。 我認為這可能不會太難,但我想我需要一些建議,在哪裡放置所需的所有東西。 也許設計已經提供了這個功能? 就像在config / initializers / devise.rb中一樣,你會寫:

config.authentication_keys = [ :email, :username ]

要求用戶名和電子郵件都可以登錄。但我真的想只為用戶名和電子郵件設置一個字段,並且只需要其中一個字段。 我只是想像一下使用某些ASCII藝術,它應該在視圖中看起來像這樣:

Username or Email:
[____________________]

Password:
[____________________]

[Sign In]






我寫得像這樣,它很有效。 不知道這是不是“醜陋的修復”,但如果我想出一個更好的解決方案,我會告訴你......

 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



我找到了解決問題的方法。 我對它不太滿意(我寧願在初始化程序中指定它),但它現在有效。 在用戶模型中,我添加了以下方法:

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

正如@sguha和@Chetan指出的那樣, 官方設計維基上還有另一個很好的資源




這是一個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參數。 (我將其保留為:示例中的電子郵件以顯示快速修復。)







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

用他們的例子!




如果您使用MongoDB (使用MongoId),則需要以不同方式進行查詢:

  def self.find_for_database_authentication(conditions={})
    self.any_of({name: conditions[:email]},{email: conditions[:email]}).limit(1).first
  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 / 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 %>






我剛剛遇到同樣的問題,我找到的最簡單的解決方案是使用SSH URL而不是HTTPS:

ssh://[email protected]/username/repo.git

而不是這個:

https://github.com/username/repo.git

現在您可以使用SSH Key而不是usernamepassword





ruby-on-rails authentication devise