github上显示的示例法术代码在我看来是创建重复的帐户,如果它被扩展为允许多个登录方法(这是oauth的全部要点)。你可以在snipit中看到,如果login_from()没有成功,将调用create_from()。
GITHUB AT https://github.com/NoamB/sorcery-example-app/blob/master/app/controllers/oauths_controller.rb
def callback
provider = params[:provider]
begin
if @user = login_from(provider)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
else
begin
@user = create_from(provider)
在所有情况下调查create_from的源代码将创建新的用户帐户记录。如果用户帐户记录已存在,则此操作不正确。
我的问题:如果用户帐户是通过Facebook之外的某些方式创建的,那么应该在第一个facebook连接上调用哪种巫术方法。 login_from将失败,create_from将生成一个重复的usser记录?
答案 0 :(得分:3)
您可以使用def create_and_validate_from(provider)。
它将验证用户的电子邮件/用户名是否已存在。如果是真的,他会将信息存储到会话中并可以呈现为注册表。
如果您想在帐户中添加一些提供商,可以使用def add_provider_to_user(provider)。
答案 1 :(得分:2)
对于这个问题的答案已经提出了几个要求,所以我提供了我的团队的Andy Mejia最终为这个问题找到答案的答案。我们使用巫术中的来源来调整以下功能:
# Returns the hash that contains the information that was passed back from Facebook.
# It only makes sense to call this method on the callback action.
#
# Example hash:
# {:user_info=>{:id=>"562515238", :name=>"Andrés Mejía-Posada", :first_name=>"Andrés", :last_name=>"Mejía-Posada", :link=>"http://www.facebook.com/andmej", :username=>"andmej", :gender=>"male", :email=>"andmej@gmail.com", :timezone=>-5, :locale=>"en_US", :verified=>true, :updated_time=>"2011-12-31T21:39:24+0000"}, :uid=>"562515238"}
def get_facebook_hash
provider = Rails.application.config.sorcery.facebook
access_token = provider.process_callback(params, session)
hash = provider.get_user_hash
hash.merge!(:access_token => access_token.token)
hash.each { |k, v| v.symbolize_keys! if v.is_a?(Hash) }
end
# Method added to the User Account model class
def update_attributes_from_facebook!(facebook_hash)
self.first_name = facebook_hash[:user_info][:first_name] if self.first_name.blank?
self.last_name = facebook_hash[:user_info][:last_name] if self.last_name.blank?
self.facebook_access_token = facebook_hash[:access_token]
self.email ||= facebook_hash[:user_info][:email]
unless facebook_authentication?
authentications.create!(:provider => "facebook", :uid => facebook_hash[:uid])
end
self.build_facebook_profile if facebook_profile.blank?
save!
self.facebook_profile.delay.fetch_from_facebook! # Get API data
end
要在上下文中显示这些代码,我还要包含来自控制器的逻辑:
def callback
provider = params[:provider]
old_session = session.clone # The session gets reset when we login, so let's backup the data we need
begin
if @user = login_from(provider) # User had already logged in through Facebook before
restore_session(old_session) # Cleared during login
else
# If there's already an user with this email, just hook this Facebook account into it.
@user = UserAccount.with_insensitive_email(get_facebook_hash[:user_info][:email]).first
# If there's no existing user, let's create a new account from scratch.
@user ||= create_from(provider) # Be careful, validation is turned off because Sorcery is a bitch!
login_without_authentication(@user)
end
@user.update_attributes_from_facebook!(get_facebook_hash)
rescue ::OAuth2::Error => e
p e
puts e.message
puts e.backtrace
redirect_to after_login_url_for(@user), :alert => "Failed to login from #{provider.titleize}!"
return
end
redirect_to after_login_url_for(@user)
end
我希望这个解决方案对其他人有所帮助。
答案 2 :(得分:0)
我遇到了同样的问题。虽然我没有找到通过法术的直接解决方案,但我做了以下似乎有效:
@user = create_from(params[:provider]) do |user|
User.where(:twitter_id => user.twitter_id).first.blank?
end
此teqnique要求您在User模型中有twitter_id
。您也可以使用身份验证模型进行相反的操作。如:
@user = create_from(params[:provider]) do |user|
Authentication.where(:uid => user.twitter_id).first.blank?
end
如果块返回false,则它不会创建用户。避免任何重复。
注意,create_from
的阻止不适用于0.7.12
。它适用于0.7.13
。