【问题标题】:How to link Phone with Email and Password Authentication in Firebase?如何在 Firebase 中将电话与电子邮件和密码身份验证相关联?
【发布时间】:2021-09-06 12:49:48
【问题描述】:

我正在尝试创建一个应用程序,用户可以使用用户名和密码进行注册,然后输入电话号码,接收 OTP 代码,并填写注册表单。但有一个问题。如果您这样做,Firebase 会创建两个不同的用户。如何合并(加入)它们以使其显示为一个帐户?

输入电话号码的活动:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_signup2)

    init()

    var phoneNumber: String

    mBackBtn.setOnClickListener {

    }

    mNextBtn.setOnClickListener {
        phoneNumber = "+" + mCountyCode!!.selectedCountryCode + mPhoneNumberEd.text.toString()
        Toast.makeText(this, phoneNumber, Toast.LENGTH_LONG).show()

        sendVerificationCode(phoneNumber)
    }
}

private fun sendVerificationCode(phone: String) {
    var phoneShadow = phone
    Log.d("MyTag", phoneShadow)

    val options = PhoneAuthOptions.newBuilder()
        .setPhoneNumber(phoneShadow)
        .setTimeout(60L, TimeUnit.SECONDS)
        .setActivity(this)
        .setCallbacks(callbacks)
        .build()
    PhoneAuthProvider.verifyPhoneNumber(options)
}

private fun init() {
    callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

        override fun onVerificationCompleted(credential: PhoneAuthCredential) {
            Log.d(TAG, "onVerificationCompleted:$credential")

            val intent = Intent(applicationContext, Signup3::class.java)
            startActivity(intent)
        }

        override fun onVerificationFailed(e: FirebaseException) {
            Log.d(TAG, "onVerificationFailed", e)
            Toast.makeText(applicationContext, "Failed", Toast.LENGTH_LONG).show()
        }

        override fun onCodeSent(verificationId: String, token: PhoneAuthProvider.ForceResendingToken) {
            Log.d("MyTag","onCodeSent:$verificationId")

            var storedVerificationId: String = verificationId
            var resendToken: PhoneAuthProvider.ForceResendingToken = token

            val intent = Intent(applicationContext, Signup3::class.java)
            intent.putExtra("storedVerificationId", storedVerificationId)
            startActivity(intent)
        }
    }

    mNextBtn = findViewById(R.id.signup2_next_btn)
    mBackBtn = findViewById(R.id.signup2_back_btn)
    mPhoneNumberEd = findViewById(R.id.signup2_phone_number_ed)
    mCountyCode = findViewById(R.id.signup2_county_code)
    mAuth = FirebaseAuth.getInstance()
}

输入手机收到的代码的活动:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_signup3)

    init()

    var storedVerificationId = intent.getStringExtra("storedVerificationId").toString()

    mConfirmBtn.setOnClickListener {
        var code = mPinView.text.toString().trim()

        if (code.isEmpty()) {
            Toast.makeText(this, "Ты ввёл?", Toast.LENGTH_LONG).show()
        } else {
            var credential : PhoneAuthCredential = PhoneAuthProvider.getCredential(storedVerificationId!!, code)
            signInWithPhoneAuthCredential(credential)
        }
    }
}

private fun init() {
    mConfirmBtn = findViewById(R.id.signup3_confirm_btn)
    mPinView = findViewById(R.id.signup3_pin_view)
    mAuth = FirebaseAuth.getInstance()
}

private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
    mAuth.signInWithCredential(credential)
        .addOnCompleteListener(this) {
            if (it.isSuccessful) {
                var intent = Intent(this, PhoneConfirmedSignup::class.java)
                startActivity(intent)
                finish()
            } else {
                if (it.exception is FirebaseAuthInvalidCredentialsException) {
                    Toast.makeText(this, "Invalid OTP", Toast.LENGTH_SHORT).show()
                }
            }
        }
}

【问题讨论】:

    标签: android firebase kotlin firebase-authentication


    【解决方案1】:

    如果您这样做,Firebase 会创建两个不同的用户。

    这是预期的行为,因为您使用了两种不同类型的身份验证。

    如何将它们组合起来,使其显示为一个帐户?

    如果您只想拥有一个,那么您应该将它们链接到一个帐户中。根据account linking的官方文档,首先,您需要获取现有凭据:

    val authCredential = EmailAuthProvider.getCredential(email, password)
    

    对于 Java 用户:

    AuthCredential authCredential = EmailAuthProvider.getCredential(email, password);
    

    然后只需使用FirebaseUser#linkWithCredential(AuthCredential credential) 方法,如以下代码行所示:

    val auth = FirebaseAuth.getInstance()
    auth.currentUser!!.linkWithCredential(credential).addOnCompleteListener(this) { task ->
        if (task.isSuccessful) {
            Log.d(TAG, "linkWithCredential:success")
            val user = task.result!!.user
            updateUI(user)
        } else {
            Log.w(TAG, "linkWithCredential:failure", task.exception)
            Toast.makeText(this, "Authentication failed.", Toast.LENGTH_SHORT).show()
            updateUI(null)
        }
    }
    

    对于 Java 用户:

    FirebaseAuth auth = FirebaseAuth.getInstance();
    auth.getCurrentUser().linkWithCredential(credential).addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
            if (task.isSuccessful()) {
                Log.d(TAG, "linkWithCredential:success");
                FirebaseUser user = task.getResult().getUser();
                updateUI(user);
            } else {
                Log.w(TAG, "linkWithCredential:failure", task.getException());
                Toast.makeText(AnonymousAuthActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show();
                updateUI(null);
            }
        }
    });
    

    【讨论】:

      猜你喜欢
      • 2018-09-09
      • 2020-05-11
      • 2018-09-03
      • 1970-01-01
      • 2021-11-21
      • 2018-09-10
      • 2019-03-15
      • 2016-11-13
      • 1970-01-01
      相关资源
      最近更新 更多