更新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
相关产品推荐
相关产品推荐

