You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

更新Firebase邮箱后登录功能失效问题求助

解决Firebase更新邮箱后无法登录的问题

看起来你遇到的问题核心是更新邮箱时根本没真正修改Firebase Auth里的用户邮箱,再加上登录逻辑里的错误处理不完整,导致登录失败后加载框一直停着。咱们一步步拆解问题和修复方案:

问题1:updateEmailAction 未实际更新Firebase Auth邮箱

你的代码里创建了profileChangeRequest,但既没有设置新邮箱,也没有执行邮箱更新的操作!只是调用了commitChanges——但这个方法是用来更新用户的displayName、photoURL这类信息的,邮箱更新需要单独处理。而且Firebase要求更新邮箱前必须重新验证用户身份(比如输入当前密码),否则会直接报错。

问题2:登录逻辑的错误处理缺失

当登录请求返回error时,你只打印了错误信息,但没有关闭SVProgressHUD,这就是为什么登录时会一直显示加载状态的原因。

问题3:数据库更新与Auth操作顺序错误

你现在是先更新数据库,再处理Auth的变更,但正确的顺序应该是先确保Auth的邮箱更新成功,再同步更新数据库,避免出现数据库和Auth系统数据不一致的情况。


修复后的代码示例

1. 完善updateEmailAction(真正更新邮箱+验证身份)

@IBAction func updateEmailAction(_ sender: Any) {
    self.view.endEditing(true)
    
    // 先校验输入合法性,避免强制解包崩溃
    guard let emailField = emailText.text?.lowercased(),
          let finalEmail = emailField.trimmingCharacters(in: .whitespacesAndNewlines),
          !finalEmail.isEmpty else {
        let alertController = UIAlertController(title: "OOPS", message: "You must fill all the fields", preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        present(alertController, animated: true, completion: nil)
        return
    }
    
    // 获取当前登录用户
    guard let currentUser = Auth.auth().currentUser else { return }
    
    // 弹出弹窗让用户输入当前密码,完成身份验证
    let passwordAlert = UIAlertController(title: "Verify Password", message: "Enter your current password to confirm email change", preferredStyle: .alert)
    passwordAlert.addTextField { textField in
        textField.placeholder = "Current Password"
        textField.isSecureTextEntry = true
    }
    
    passwordAlert.addAction(UIAlertAction(title: "Confirm", style: .default, handler: { [weak self] _ in
        guard let self = self,
              let password = passwordAlert.textFields?.first?.text,
              !password.isEmpty else { return }
        
        // 用当前密码重新验证用户身份
        let credential = EmailAuthProvider.credential(withEmail: currentUser.email!, password: password)
        currentUser.reauthenticate(with: credential) { [weak self] result, error in
            guard let self = self else { return }
            
            if let error = error {
                print("身份验证失败: \(error.localizedDescription)")
                let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "OK", style: .cancel))
                self.present(alert, animated: true)
                return
            }
            
            // 验证成功后,更新Firebase Auth邮箱
            currentUser.updateEmail(to: finalEmail) { [weak self] error in
                guard let self = self else { return }
                
                if let error = error {
                    print("邮箱更新失败: \(error.localizedDescription)")
                    let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "OK", style: .cancel))
                    self.present(alert, animated: true)
                    return
                }
                
                // 邮箱更新成功后,同步更新数据库
                let userInfo = [
                    "firstLastName": self.name,
                    "email": finalEmail,
                    "location": self.locationOld,
                    "interests": self.interestsOld,
                    "biography": self.biog,
                    "uid": self.uid,
                    "photoURL": self.photoUrl
                ]
                // 注意:不要存储明文密码!数据库里删掉passwordOld字段,Firebase Auth会管理密码
                let userRef = self.dataBaseRef.child("users").child(currentUser.uid)
                userRef.setValue(userInfo) { error, _ in
                    if let error = error {
                        print("数据库更新失败: \(error.localizedDescription)")
                    } else {
                        print("用户邮箱和数据库已同步更新")
                        // 提示用户更新成功并登出
                        let successAlert = UIAlertController(title: "Success", message: "Email updated successfully. Please sign in again.", preferredStyle: .alert)
                        successAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
                            do {
                                try Auth.auth().signOut()
                                self.performSegue(withIdentifier: "login", sender: self)
                            } catch {
                                print("登出失败: \(error.localizedDescription)")
                            }
                        }))
                        self.present(successAlert, animated: true)
                    }
                }
            }
        }
    }))
    
    passwordAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
    present(passwordAlert, animated: true)
}

2. 完善signInButton(修复加载框不消失+错误提示)

@IBAction func signInButton(_ sender: Any) {
    self.view.endEditing(true)
    
    guard let email = emailText.text?.lowercased(),
          let finalEmail = email.trimmingCharacters(in: .whitespacesAndNewlines),
          !finalEmail.isEmpty,
          let password = passwordText.text,
          !password.isEmpty,
          finalEmail.count >= 8 else {
        let alertController = UIAlertController(title: "OOPS", message: "You must fill in all the fields and email must be at least 8 characters", preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        present(alertController, animated: true, completion: nil)
        return
    }
    
    SVProgressHUD.show()
    Auth.auth().signIn(withEmail: finalEmail, password: password) { [weak self] user, error in
        guard let self = self else { return }
        // 无论成功失败,都要关闭加载框
        SVProgressHUD.dismiss()
        
        if let error = error {
            print("登录失败: \(error.localizedDescription)")
            let alert = UIAlertController(title: "Sign In Failed", message: error.localizedDescription, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .cancel))
            self.present(alert, animated: true)
            return
        }
        
        if let user = user {
            print("\(user.displayName ?? "User") has been signed in")
            self.enter()
            self.performSegue(withIdentifier: "signInHome", sender: nil)
        }
    }
}

3. 优化logOutAction(处理登出错误)

@IBAction func logOutAction(_ sender: Any) {
    guard Auth.auth().currentUser != nil else { return }
    do {
        try Auth.auth().signOut()
        self.performSegue(withIdentifier: "login", sender: self)
    } catch {
        print("登出失败: \(error.localizedDescription)")
        let alert = UIAlertController(title: "Error", message: "Failed to sign out", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .cancel))
        present(alert, animated: true)
    }
}

额外提醒

  • 绝对不要存储明文密码:你的代码里把passwordOld存到数据库是非常危险的行为,Firebase Auth已经负责密码的安全管理,不需要自己存储密码。
  • 避免强制解包:原代码里大量使用!强制解包,容易触发崩溃,建议用guard let/if let进行可选绑定处理。

内容的提问来源于stack exchange,提问作者hg56

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:43:52