在Rails中使用Omniauth时,如果用户存在并使用不同的身份验证,则Google_omniauth2会创建一个新用户

时间:2014-11-23 03:38:22

标签: ruby-on-rails ruby-on-rails-4 devise omniauth

我正在使用google_aouth2和facebook设计。谷歌似乎并没有与其他人合作。以下是一些例子:

  1. 我以正常方式创建一个帐户(没有omniauth) - : - 我尝试使用Facebook登录,但它没有创建新帐户。它只是登录现有帐户(电子邮件相同) - : - 如果我使用Google登录,它会尝试创建新用户并提出此错误'验证失败:电子邮件已经被采取了

  2. 我使用Facebook创建帐户 - : - 如果我使用Google登录,它会尝试创建新用户并提出此错误'验证失败:电子邮件已经被采取了

  3. 我使用Google创建了一个帐户 - : - 我尝试使用Facebook登录,但它没有创建新帐户。它只需登录现有帐户(电子邮件相同)

  4. 如何让Google像Facebook一样工作?使用相同的电子邮件检测现有用户帐户并登录,而不创建具有相同电子邮件的其他用户?

    我的user.rb:

    class User < ActiveRecord::Base
    
    
    
      # Include default devise modules. Others available are:
      # :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :omniauthable
    
     VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\-.]+\.[a-z]+\z/i
      validates :email, presence: true, length: { maximum: 255 },
                        format: { with: VALID_EMAIL_REGEX },
                        uniqueness: { case_sensitive: false }
    
      def self.find_for_oauth(auth, signed_in_resource = nil)
    
        # Get the identity and user if they exist
        identity = Identity.find_for_oauth(auth)
    
        # If a signed_in_resource is provided it always overrides the existing user
        # to prevent the identity being locked with accidentally created accounts.
        # Note that this may leave zombie accounts (with no associated identity) which
        # can be cleaned up at a later date.
        user = signed_in_resource ? signed_in_resource : identity.user
    
        # Create the user if needed
        if user.nil?
    
          # Get the existing user by email if the provider gives us a verified email.
          # If no verified email was provided we assign a temporary email and ask the
          # user to verify it on the next step via UsersController.finish_signup
          email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
          email = auth.info.email if email_is_verified
          user = User.where(:email => email).first if email
    
          # Create the user if it's a new registration
          if user.nil?
            user = User.new(
              #name: auth.extra.raw_info.name,
              username: auth.info.email,
              email: auth.info.email,
              #email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
              password: Devise.friendly_token[0,20],
              autouser: true
            )
    
            if auth.provider == 'google_oauth2'
              user.gplus = auth.info.urls.Google
            end
    
    
            user.skip_confirmation!
            user.save!
          end
        end
    
        # Associate the identity with the user if needed
        if identity.user != user
          identity.user = user
          identity.save!
        end
        user
      end
    
      def email_verified?
        self.email && self.email !~ TEMP_EMAIL_REGEX
      end
    end
    

    Identity.rb:

        class Identity < ActiveRecord::Base
          belongs_to :user
    
            validates_presence_of :uid, :provider
          validates_uniqueness_of :uid, :scope => :provider
    
          def self.find_for_oauth(auth)
            find_or_create_by(uid: auth.uid, provider: auth.provider)
          end
        end
    

    omniauth_callbacks_controller.rb:

    class OmniauthCallbacksController < Devise::OmniauthCallbacksController
      def self.provides_callback_for(provider)
        class_eval %Q{
          def #{provider}
            @user = User.find_for_oauth(env["omniauth.auth"], current_user)
    
            if @user.persisted?
              sign_in_and_redirect @user, event: :authentication
    
              set_flash_message(:notice, :success, kind: "#{provider}".gsub(/_/," ").split[0...1].join(' ').capitalize) if is_navigational_format?
            else
              session["devise.#{provider}_data"] = env["omniauth.auth"]
              redirect_to new_user_registration_url
            end
          end
        }
      end
    
      [:google_oauth2, :facebook].each do |provider|
        provides_callback_for provider
      end
    
      def after_sign_in_path_for(resource)
          super resource
      end
    end
    

1 个答案:

答案 0 :(得分:0)

找到答案!在user.rb文件中,它通过访问“auth.verified&#39;来检查电子邮件是否经过Facebook验证。属性。如果已经过验证,它只会收取电子邮件并检查现有帐户。问题是,Google没有提供该属性。因此,如果有人通过Google进行身份验证,我将绕过这样的验证:

  if auth.provider == 'google_oauth2'
    email = auth.info.email
  else
    email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
    email = auth.info.email if email_is_verified
  end