2016-12-29 99 views
2

请在下列情况下帮助我找到正确的解决方案。如何在Firebase中管理用户的不同身份验证

我正在用swift开发ios应用程序,它将使用Firebase作为后端。

用户应该能够通过电子邮件/密码或/和脸书登录到firebase。也许谷歌将在稍后添加。

对于每个真实用户拥有一个Firebase帐户非常重要,因为用户将获得奖励积分,并且如果在一个设计中(使用电子邮件登录),他将拥有X个积分并且在其他设备上与脸谱)他会有不同的观点。

这里是代码,我使用的电子邮件登录:

//EMAIL REGISTER 
    @IBAction func registerAction(_ sender: Any) { 

     if self.emailTextField.text == "" || self.passwordTextField.text == "" { 

      Print("Please enter email and password.") 

     } else { 

      FIRAuth.auth()?.createUser(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!, completion: { (user, error) in 

       if error == nil { 
        self.logoutButton.isHidden = false 
        self.usernameLabel.text = user!.email 
        self.emailTextField.text = "" 
        self.passwordTextField.text = "" 
       } else { 
        Print("\((error?.localizedDescription)!)") 
       } 

      }) 

     } 
    } 

    //EMAIL LOGIN 
    @IBAction func loginAction(_ sender: Any) { 

     if self.emailTextField.text == "" || self.passwordTextField.text == "" { 
      print("Please enter email and password.") 
     } else { 

      FIRAuth.auth()?.signIn(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!, completion: { (user, error) in 

       if error == nil { 
        self.logoutButton.isHidden = false 
        self.usernameLabel.text = user!.email 
        self.emailTextField.text = "" 
        self.passwordTextField.text = "" 

       } else { 

        Print("\((error?.localizedDescription)!)") 

       } 
      }) 
     } 
    } 

这里是我使用与Facebook登录代码:

func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) { 

     self.fbLoginButton.isHidden = true 

     if error != nil { 

      self.fbLoginButton.isHidden = false 
      print(error.localizedDescription) 
      return 

     } else if (result.isCancelled) { 

      print("canceled") 
      self.fbLoginButton.isHidden = false 

     } else { 

      let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString) 

      FIRAuth.auth()?.signIn(with: credential) { (user, error) in 
       if let error = error { 
        print(error.localizedDescription) 
        return 
       } 
      } 
     } 
    } 

这两种方法都做工精细,但他们创造两个独立的账户。

它设置为允许多个用户使用同一个电子邮件中设置: enter image description here

和我结束了以下结果:

enter image description here

很明显,我想这两个帐户自动合并。

Documentation描述了如何链接auth提供程序的方式,但用户应该使用一种方法登录并且只有在该方法之后才能链接帐户。 linkWithCredential方法用于已经拥有oauth凭证的情况。如果用户使用电子邮件在一台设备上创建,如果他决定再次在其他设备上使用Facebook登录,则无法工作。


与任一方式的FIRAuth.auth()?.addStateDidChangeListener服务是表示我使用数据库第二视图控制器洛在后。

覆盖FUNC viewDidLoad中(){ super.viewDidLoad()

let user = FIRAuth.auth()?.currentUser 
let dat = user?.providerData 

let email = user?.providerData[0].email 
let name = user?.displayName 

if email != nil { 
self.ref.child("user_profile").child("\(user!.uid)/email").setValue(email) 
} 

if name != { 
self.ref.child("user_profile").child("\(user!.uid)/name").setValue(name) 
} 

}

让我们说,我们洛与Facebook,也许就可以找到用户的UID具有相同的电子邮件和运行更新?万一有很多用户,这不是一个好主意。

其他想法是使用电子邮件作为ID这样的:

self.ref.child("user_profile").child("\(email)/name").setValue(name)

不知道这是一个很好的选择吗?

感谢您的回复。

回答

1

如何在第一台没有匿名用户的设备上使用他的电子邮件和密码登录后,使用不同设备登录用户。

创建用户后,您需要将电子邮件和密码保存为NSUbiquitousKeyValueStore,这样其他设备才能访问电子邮件和密码,因为您需要首先登录用户,然后才能将其帐户链接到Facebook下面。

在FB控制台
1.帐户电子邮件地址设置:防止创建多个账户使用相同的电子邮件地址这样该帐户没有得到,如果已经与电子邮件地址登录的用户再次创造的。

2.如果用户选择电子邮件地址作为第一登录:

var iCloudKeyStore: NSUbiquitousKeyValueStore = NSUbiquitousKeyValueStore() 

FIRAuth.auth()?.createUser(withEmail: email, password: password) { (user, error) in 

      // User created 
      if error == nil{ 

       // signed in successfully 

       //Save the password and the email. Or choose your way to save them 
       iCloudKeyStore.set(password, forKey: email) 


      }else{ 

       //Erorr 
      } 
     } 
  • 现在用户拥有帐户在火力地堡和将看起来像:
  • enter image description here 4.现在其他设备上的用户决定与Facebook(不同提供商)

    登录您在用户与Facebook和签订后有fb令牌:通常在FBSDKAccessTokenDidChange通知的函数侦听器中,您使用Facebook的令牌在Firebase中登录用户。

    let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString) 
    
        FIRAuth.auth()?.signIn(with: credential) { (user, error) in 
         // ... 
         if error != nil { 
          // SETP 5. HERE 
    
          let nsError = (error as! NSError) 
          // Error: 17007 The email address is already in use by another account. ERROR_EMAIL_ALREADY_IN_USE 
    
          if nsError.code == 17007{ 
    
    
            print(error,user?.uid,nsError.code,"facebook user error") 
    
            let email = nsError.userInfo["FIRAuthErrorUserInfoEmailKey"] as? String 
            self.signInUserWithEmail(email: email!) 
            print("email",email) 
           } 
    
    
         }else{ 
    
    
          print(user!.uid,"facebook user login") 
        } 
    
  • 由于用户已经使用此电子邮件地址,他现在试图与Facebook的帐户,这样的错误会发生:如您在步骤4中看到,现在你需要您链接之前帐户Facebook在用户登录:

    func signInUserWithEmail(email:String){ 
    
        let password = iCloudKeyStore.string(forKey: email) 
    
    
        FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user:FIRUser?, error:Error?) in 
    
    
         if user != nil{ 
    
          self.linkAccountWihtFacebook() 
          print(user?.uid) 
    
         }else{ 
    
          print(error?.localizedDescription) 
         } 
        }) 
    
    } 
    

    FUNC linkAccountWihtFacebook(){

    let credential = FIRFacebookAuthProvider.credential(withAccessToken: FBSDKAccessToken.current().tokenString) 
    
         FIRAuth.auth()?.currentUser?.link(with: credential, completion: { (user:FIRUser?, error:Error?) in 
    
          if let LinkedUser = user{ 
    
           print("NEW USER:",LinkedUser.uid) 
    
          } 
    
          if let error = error as? NSError{ 
    
           //Indicates an attempt to link a provider of a type already linked to this account. 
           if error.code == FIRAuthErrorCode.errorCodeProviderAlreadyLinked.rawValue{ 
            print("FIRAuthErrorCode.errorCodeProviderAlreadyLinked") 
           } 
    
           //This credential is already associated with a different user account. 
           if error.code == 17025{ 
    
           } 
    
           print("MyError",error) 
          } 
    
         }) 
    } 
    
  • 这样,您将在火力地堡控制台以下结果:

  • enter image description here

    火力地堡文档: https://firebase.google.com/docs/auth/ios/account-linking

    链接身份验证提供凭据的用户帐户

    将身份验证提供程序凭据链接到现有用户帐户:

    1.使用任何身份验证提供程序或方法登录用户。

    1. 完成新认证提供者的登录流程,但不包括调用FIRAuth.signInWith方法之一。 例如,获取用户的Google ID令牌,Facebook访问令牌或 电子邮件和密码。
    2. 找一个FIRAuthCredential为新的身份验证提供
    +0

    嗨,如果我选择防止多ACCS的创作......我用电子邮件和密码创建的帐户后,我不能用Facebook登录。 (因为电子邮件是相同的)。我使用的是与您通过电子邮件和密码登录相同的代码。或者我错过了什么? – Almazini

    +0

    可以说我已经有一个电子邮件和密码帐户。我想在其他设备上使用Facebook登录。我想登录到现有用户而不是创建新用户。 – Almazini

    +0

    生病编辑我的答案... – Jad

    相关问题