![](/img/trans.png)
[英]Devise - Omniauth - Can't sign up (Email already exists) if previously logged in with provider
[英]Devise/Omniauth - How to deal with a Provider that doesn't include an email
我有一個使用Devise和Omniauth處理身份驗證的Rails應用程序。 按照規定,我將在omniauth_callbacks_controller中接收來自提供程序的回調,在這里檢查身份驗證是否已經存在,以及是否存在使用提供程序提供的電子郵件的用戶,並在必要時創建一個新用戶。
我需要為每個用戶提供有效的電子郵件。 我的問題來自Twitter的回調。 Twitter不為其用戶提供電子郵件,因此我無法創建有效用戶。 為了解決這個問題,我將提供者的數據存儲在一個會話中,然后向用戶發送新的注冊頁面,要求他們提交其電子郵件地址,以便創建一個有效的用戶。 提交此表格時,我遇到了問題。 表單創建了一個新用戶,但是使用該電子郵件的用戶很可能已經存在(在這種情況下,我需要向該用戶添加身份驗證)。
目前,我正在檢查是否存在與新用戶使用相同電子郵件的用戶。 如果是這樣,我將忽略新用戶,並將身份驗證應用於已經存在的用戶。 但是,這感覺確實很hack。
我應該怎么做?
class Users::RegistrationsController < Devise::RegistrationsController
def build_resource(*args)
super
if session[:omniauth]
#If a user with this email already exists then use them instead
existing_user = User.find_by_email(@user.email)
if(existing_user)
existing_user.email = @user.email
@user = existing_user
end
#If there is a session available, we know it contains data for adding an authentication
@user.apply_omniauth_data_as_authentication(session[:omniauth])
#Ensure validations are passed on to next page
@user.valid?
end
end
干得好。 我會嘗試並記住從哪里獲得修復程序,如果這樣做的話,會發布一個鏈接:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
# This controller handles callbacks from Omniauth providers. If a user already exists with this provider we sign them in.
# Otherwise we either add an authentication to the current user, or create a new user if one doesn't exist.
def facebook
authorize
end
def twitter
authorize
end
private
def authorize
omniauth_data = request.env["omniauth.auth"]
#Check to see if we have an authentication for this provider already stored for any User
authentication = Authentication.find_by_provider_and_uid(omniauth_data['provider'], omniauth_data['uid'])
#If an authentication already exists, sign the owning User in
if authentication
flash[:notice] = "Signed in successfully with " + omniauth_data['provider'].titleize
sign_in_and_redirect(:user, authentication.user)
#Otherwise if there is a current User, add a new authentication for them
elsif current_user
current_user.authentications.create(:provider => omniauth_data['provider'], :uid => omniauth_data['uid'], :token => omniauth_data['token'])
flash[:notice] = "Authentication successful"
redirect_to user_profile_url
#Otherwise we check if a user exists with the email address provided by the provider (if provided at all))
else
email = omniauth_data['info']['email']
user = User.find_by_email(email)
#If no user exists, create a new one
if(!email || !user)
user = User.new
end
user.apply_omniauth_data_as_authentication(omniauth_data)
#If they save successfully (meaning we have enough data from the authorisation) sign them in
if user.email?
#We got all we needed from the provider so we don't need them to confirm'
user.skip_confirmation!
user.save!
flash[:notice] = "Signed in successfully with " + omniauth_data['provider']
sign_in_and_redirect(:user, user)
#Otherwise we need to have the visitor manually submit missing information
else
#save the omniauth data in a session so we can add the authentication once registration is complete
flash[:alert] = "Please complete registration"
session[:omniauth] = omniauth_data.except('extra')
redirect_to new_user_registration_url
end
end
end
end
我喜歡此鏈接使用的解決方案http://www.orhancanceylan.com/rails-twitter-and-facebook-authentications-with-omniauth-and-devise/
它使用提供者憑據在正常的設計過程中注冊(以及在用戶或單獨的表上填寫提供者和uid屬性)。 因此,當新用戶嘗試使用提供者進行注冊時,將要求他們輸入電子郵件和密碼,從而減少麻煩(例如希望以常規方式登錄,但沒有密碼可輸入,然后您必須處理該問題)。
盡管此解決方案在第一時間就抵消了在社交媒體上注冊的便利性,但它卻以最小的努力創造了長期的有益效果。
如果您絕對不希望這種要求,以免丟失注冊信息或網站看起來不夠美觀,請找到另一種解決方案,並盡一切努力來處理這些下游案件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.