在Rails中使用Omniauth时,如果用户存在并使用不同的身份验证,则Google

编程入门 行业动态 更新时间:2024-10-27 10:28:00
在Rails中使用Omniauth时,如果用户存在并使用不同的身份验证,则Google_omniauth2会创建新用户(When using Omniauth in Rails, Google_omniauth2 creates a new user if the user exists and use different auth)

我使用google_aouth2和facebook与设计。 谷歌似乎并没有与其他人合作。 这里有些例子 :

我以正常方式创建一个帐户(No omniauth) - : -我尝试使用Facebook登录,但它不会创建新帐户。 它只是登录现有帐户(电子邮件相同) - : -如果我使用Google登录,它会尝试创建新用户并提出此错误“验证失败:电子邮件已被删除”

我使用Facebook创建一个帐户- : -如果我使用Google登录,它会尝试创建一个新用户并提出此错误“验证失败:电子邮件已被删除”

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

如何让谷歌像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

omn​​iauth_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

Im using google_aouth2 and facebook with devise. Google aouth doesn't seems to play well with the others. Here are some examples :

I create an account in the normal way (No omniauth) --:-- I try to sign in with Facebook and it doesn't create a new account. It simply signin to the existing account (emails are same) --:-- If I use Google to sign in, it tries to create a new user and gives this error 'Validation failed: Email has already been taken'

I create an account using Facebook --:-- If I use Google to sign in, it tries to create a new user and gives this error 'Validation failed: Email has already been taken'

I create an account using Google --:-- I try to sign in with Facebook and it doesn't create a new account. It simply signin to the existing account (emails are same)

How can I make Google to work like Facebook? Detect the existing user account with the same email and sign in without creating another user with the same email?

My 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

最满意答案

找到答案了! 在user.rb文件中,它通过访问“auth.verified”属性来检查电子邮件是否通过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

Found the answer! In the user.rb file, it checks whether the email is verified by Facebook or not by accessing 'auth.verified' attribute. It will only take the email and check for an existing account if it's verified. The problem is,Google does not provide that attribute. So, if someone authenticate with Google I will bypass the verification like this :

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

更多推荐

本文发布于:2023-07-28 23:31:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1310181.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:身份验证   用户   Rails   Omniauth   Google

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!