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

Firebase认证问题:已存在邮箱仍可注册的原因排查

问题: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:27:27