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

Firebase实时数据库安全规则配置咨询:Android应用三步验证场景

嘿,我来帮你理清这个场景下的Firebase实时数据库安全规则配置——毕竟客户端直接做验证确实容易踩安全坑,得把规则卡得恰到好处才行!

首先得明确一个核心原则:敏感操作(比如生成PIN、写入验证信息)绝对不能放在客户端做,必须依赖Firebase Cloud Functions(后端)来处理,不然恶意用户很容易绕过客户端逻辑篡改数据。先给你推荐一个适配这个验证流程的合理数据结构,规则都是基于这个结构来写的:

{
  "users": {
    "user_abc123": {
      "phone": "+1234567890",
      "pin_hash": "abcdef123456...", // 注意:PIN要加盐哈希后存储,别明文!
      "pin_expiry": 1700000000, // UNIX时间戳,设置PIN5分钟后过期
      "username": "xxx" // 其他用户信息
    }
  },
  "phone_mapping": {
    "+1234567890": "user_abc123"
  }
}

phone_mapping用来快速通过手机号找到对应的用户ID,避免客户端遍历整个users节点;users里存用户的核心信息,PIN用哈希存储避免泄露。

阶段1:校验手机号是否存在

用户输入手机号后,客户端需要查询这个号码是否在系统中。但绝对不能让客户端读取整个phone_mapping节点(防止爬虫扒走所有手机号),所以规则要限制只能查询单个指定手机号:

{
  "rules": {
    "phone_mapping": {
      "$phone": {
        // 允许未认证用户查询单个手机号的存在性,但不能遍历整个节点
        ".read": "auth == null && query.equalTo($phone).limitToFirst(1).exists()"
      }
    }
  }
}

解释:这里auth == null是因为用户还没完成验证,处于未登录状态;query.equalTo($phone).limitToFirst(1)确保客户端只能查询自己输入的那个手机号,不能批量读取。

阶段2:生成并存储一次性PIN

这一步必须用Cloud Functions来做,客户端只需要调用云函数传入手机号,云函数负责生成PIN、哈希后存入数据库、设置过期时间,再通过FCM把PIN推给用户。对应的数据库规则要限制只有云函数(管理员权限)能写入PIN相关字段:

{
  "rules": {
    "users": {
      "$userId": {
        "pin_hash": {
          // 只有管理员/云函数能写入PIN哈希
          ".write": "auth != null && auth.token.admin == true"
        },
        "pin_expiry": {
          ".write": "auth != null && auth.token.admin == true"
        },
        "phone": {
          ".write": false // 手机号一旦绑定就不允许修改
        }
      }
    }
  }
}

为什么不让客户端写PIN?如果客户端有写入权限,恶意用户可以随便修改自己或他人的PIN,整个验证流程就完全失效了,必须把这个权限牢牢握在后端手里。

阶段3:校验PIN码是否匹配

用户输入PIN后,客户端需要查询对应用户的pin_hash和pin_expiry,验证PIN哈希匹配且未过期。规则要允许未认证用户读取自己手机号对应的用户节点的PIN相关字段,但不能碰其他敏感信息:

{
  "rules": {
    "users": {
      "$userId": {
        "pin_hash": {
          // 确保只能读取当前手机号对应的用户的PIN哈希
          ".read": "auth == null && root.child('phone_mapping').child(data.parent().child('phone').val()).val() == $userId"
        },
        "pin_expiry": {
          ".read": "auth == null && root.child('phone_mapping').child(data.parent().child('phone').val()).val() == $userId"
        },
        // 其他用户信息(比如username)只能被已认证的本人读取
        "$otherFields": {
          ".read": "auth != null && auth.uid == $userId"
        }
      }
    }
  }
}

客户端验证逻辑要注意:先把用户输入的PIN做和云函数一样的加盐哈希,再和数据库里的pin_hash对比,同时检查pin_expiry是否大于当前时间戳(防止过期PIN被使用)。

额外安全小贴士

  1. PIN哈希加盐:给每个用户的PIN加独立的盐值存储,即使数据库泄露,攻击者也很难破解PIN。
  2. 限流防暴力破解:在Cloud Functions里给手机号查询、PIN验证操作加限流(比如1分钟内最多5次尝试),防止恶意用户暴力猜PIN。
  3. 验证后立即登录:PIN验证通过后,用Cloud Functions生成Firebase自定义令牌,让用户完成登录,之后所有操作都用认证后的权限,规则里可以限制只有认证用户才能访问菜单界面的相关数据。
  4. 定时清理过期PIN:用Cloud Functions定时任务删除过期的pin_hash和pin_expiry,减少数据库冗余,也降低泄露风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:11:40