Firebase认证问题:已存在邮箱仍可注册的原因排查
我在Firebase中创建了账号,希望阻止用户使用已存在的邮箱地址注册,但每次尝试用已存在的邮箱注册时,操作始终被允许。需要说明的是,邮箱检查在第一个视图控制器中执行,但密码、名字和姓氏等信息仅在后续视图控制器中获取,会不会是这个原因导致功能失效?
相关代码
邮箱检查调用代码
DatabaseManager.shared.userExists(with: email, completion: { [weak self] exists in guard let strongSelf = self else { return } guard !exists else { strongSelf.alertInvalidEmail() print("already exists") return } HapticsManager.shared.vibrate(for: .success) self?.presenter(vc, animated: false, pushing: true, completion: nil) print("doesnt exist") }) }
alertInvalidEmail函数(可正常运行)
@objc private func alertInvalidEmail() { myAlert.showAlert(with: "Erreur", message: "Veuillez entrer une adresse e-mail correcte.", on: self) HapticsManager.shared.vibrate(for: .warning) emailField.text = "" }
DatabaseManager及相关扩展、AppUser结构体
final class DatabaseManager { static let shared = DatabaseManager() private let database = Database.database().reference() } // MARK: - Account Management extension DatabaseManager { public func userExists(with email: String, completion: @escaping ((Bool) -> Void)) { var safeEmail = email.replacingOccurrences(of: ".", with: "-") safeEmail = safeEmail.replacingOccurrences(of: "@", with: "-") database.child(safeEmail).observeSingleEvent(of: .value, with: { snapshot in guard snapshot.value as? String != nil else { completion(false) return } completion(true) }) } public func insertUser(with user: AppUser) { database.child(user.safeEmail).setValue([ "first_name": user.firstName, "last_name": user.lastName ]) } } struct AppUser { let firstName: String let lastName: String let emailAddress: String var safeEmail: String { var safeEmail = emailAddress.replacingOccurrences(of: ".", with: "-") safeEmail = safeEmail.replacingOccurrences(of: "@", with: "-") return safeEmail } }
可能的原因分析
数据库节点判断逻辑错误:在
userExists方法中,你通过snapshot.value as? String != nil判断用户是否存在,但实际插入用户时存入的是包含first_name和last_name的字典,而非字符串。这会导致即使节点存在,snapshot.value as? String也会返回nil,错误地返回false认为用户不存在。正确的判断应该用snapshot.exists(),它会直接检测节点是否存在,不受存储数据类型影响。邮箱大小写未统一处理:Firebase Realtime Database的路径区分大小写,如果用户输入的邮箱大小写不同(比如
Test@Example.com和test@example.com),生成的safeEmail会不一样,导致检查不到已存在的用户。建议将邮箱转换为全小写后再生成safeEmail。后续注册流程未被正确阻断:虽然第一个视图控制器做了邮箱检查,但如果后续视图控制器的注册流程(比如调用Firebase Auth的
createUser方法)没有依赖这个检查结果,而是直接执行,那即使前端检查不通过,依然会创建新用户。需要确认后续流程只有在邮箱检查通过后才会触发。Firebase数据库权限问题:如果Realtime Database的规则设置不正确,当前用户可能没有权限读取对应节点的数据,导致
observeSingleEvent无法获取到已存在的用户信息,始终返回false。可以临时设置规则为{ "rules": { ".read": true, ".write": true } }测试是否是权限问题(测试后记得改回安全规则)。
内容的提问来源于stack exchange,提问作者user19534819

