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

Xamarin使用FirebaseAuthentication.net访问受保护Firebase实时数据库报错

问题根因

你代码里有两个核心错误,直接导致抛出异常、且无法访问受保护的数据库:

  1. 认证方法调用错误:SignInWithOAuthAsync是专门对接Google、Facebook、微软这类第三方OAuth登录的方法,不支持邮箱密码认证场景,你传入FirebaseAuthType.EmailAndPassword触发的异常,和报错提示完全对应——邮箱密码登录必须用库提供的专属方法。
  2. 数据库客户端未配置鉴权令牌:就算认证流程跑通,你初始化的firebaseClient没有携带认证成功后拿到的用户ID令牌,所有请求发出去都会被你配置的auth.uid != null安全规则直接拦截,根本写不进数据。

另外还有个容错漏洞:你直接从Preferences取值反序列化,如果本地没存过对应键值会拿到空字符串,直接反序列化会抛序列化异常。

修正后的实现方案

按以下逻辑调整代码即可正常访问配置了登录校验规则的实时数据库:

  • 废弃错误的SignInWithOAuthAsync调用,邮箱密码场景使用专属登录/令牌刷新方法
  • 本地已存认证凭证时,优先校验令牌有效性,过期则自动刷新,不需要重复走账号密码登录流程
  • 初始化FirebaseClient时绑定令牌获取逻辑,所有数据库请求会自动携带合法鉴权信息
  • 增加本地凭证空值判断,避免无本地缓存时的崩溃

完整修正代码如下:

// 提前定义全局常量,替换成你自己项目的实际值
private const string WebApiKey = "你的Firebase项目Web API Key";
private FirebaseClient _firebaseClient;

private async void Button_Clicked(object sender, EventArgs e)
{
    try
    {
        var authProvider = new FirebaseAuthProvider(new FirebaseConfig(WebApiKey));
        FirebaseAuth auth;

        // 读取本地缓存的认证凭证
        var savedAuthJson = Preferences.Get("MyFirebaseRefreshToken", string.Empty);
        if (!string.IsNullOrEmpty(savedAuthJson))
        {
            var savedAuth = JsonConvert.DeserializeObject<FirebaseAuth>(savedAuthJson);
            // 自动刷新过期的令牌
            auth = await authProvider.RefreshAuthAsync(savedAuth);
        }
        else
        {
            // 本地无缓存时走邮箱密码登录,替换成你页面上用户输入的邮箱、密码对应控件
            string userEmail = emailEntry.Text.Trim();
            string userPassword = passwordEntry.Text.Trim();
            auth = await authProvider.SignInWithEmailAndPasswordAsync(userEmail, userPassword);
            // 登录成功后把完整凭证存本地,下次启动直接刷新用
            Preferences.Set("MyFirebaseRefreshToken", JsonConvert.SerializeObject(auth));
        }

        // 初始化带鉴权逻辑的数据库客户端,数据库地址替换成你自己的实时数据库地址
        _firebaseClient = new FirebaseClient(
            "https://你的项目id-default-rtdb.firebaseio.com/",
            new FirebaseOptions
            {
                AuthTokenAsyncFactory = () => Task.FromResult(auth.FirebaseToken)
            });

        // 写入数据,直接取当前登录用户的uid作为节点键,不需要硬编码
        await _firebaseClient
            .Child("users")
            .Child(auth.User.LocalId)
            .PutAsync(new userinfo
            {
                firstName = "noor",
                secondName = "mohammed"
            });

        recordData.Text = "";
    }
    catch (Exception ex)
    {
        await App.Current.MainPage.DisplayAlert("操作失败", ex.Message, "OK");
    }
}
注意事项
  • 代码里需要替换三个占位参数:Firebase Web API Key、实时数据库地址、用户输入的邮箱密码取值控件,这些参数都可以在Firebase控制台的项目设置页找到。
  • 你配置的安全规则会在服务端自动校验所有请求的令牌有效性,客户端不需要额外做权限判断,令牌无效/过期的请求会直接被拒绝。
  • 本地存储的是完整序列化后的FirebaseAuth对象,不要只存单独的token字符串,否则无法使用内置的令牌刷新逻辑。
  • 按钮点击事件是少数允许使用async void的场景,其他业务逻辑不要用async void编写,避免异常捕获失效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:27:16