Firebase手机身份认证能否发送服务端生成的自定义OTP验证码?
核心结论
Firebase 原生手机认证流程不支持直接替换服务端自定义生成的OTP作为它认证链路里的验证代码——它默认的OTP由Firebase后台生成、走官方短信通道下发,没有开放修改验证码内容的接口。但你提到的两个核心诉求:防止创建用户接口被恶意调用、自定义OTP落库用于后续数据重置场景,完全可以通过调整业务链路实现,不需要硬改Firebase原生逻辑。
具体实现方案
一、先堵上创建用户接口的未授权访问漏洞
你现在的问题本质是把创建用户的信任根放在了客户端回调上,相当于把鉴权逻辑交给了前端,自然挡不住Postman直接调用,按下面改就行:
- 客户端完成Firebase手机认证拿到合法的
ID Token之后,再把这个Token作为参数传给你ASP.NET服务端的创建用户接口,不要传任何自定义的「认证成功」标记 - 服务端收到请求第一步,必须用Firebase Admin SDK校验这个ID Token的合法性:验证签名是否有效、是否在有效期内、提取Token里绑定的手机号字段,确认这个Token确实是Firebase为对应用户完成手机验证后签发的,校验不通过直接返回403错误
- 校验通过后先查自有用户库,如果该手机号已经绑定过系统用户,直接返回重复注册提示;同时加基础限流规则:单个IP1小时内最多允许3次注册请求,挡住脚本批量刷接口
- 改完之后,哪怕有人用Postman直接调接口,拿不到对应手机号合法签发的Firebase ID Token,根本过不了服务端校验,没法恶意创建用户。
二、自定义OTP的存储与使用逻辑
你完全不需要把自定义OTP塞进Firebase注册认证的流程里,把注册验证和后续敏感操作验证的链路分开就行,维护成本最低:
- 注册阶段的验证码直接用Firebase默认下发的即可,你不需要存储这部分OTP,验证结果完全以服务端校验Firebase ID Token的结果为准,省得自己维护验证码有效期、防暴力破解的逻辑
- 当用户触发数据重置、修改敏感信息这类需要二次验证手机号的场景时,不走Firebase认证流程,完全走你自有OTP逻辑:
- 用户提交手机号发起验证请求时,ASP.NET服务端生成6位数字OTP,设置5-10分钟有效期,把「手机号+OTP加盐哈希值+过期时间+剩余尝试次数」写入服务端数据库,禁止存储明文OTP,哈希逻辑和你存储用户密码的逻辑保持一致即可
- 调用你自己对接的短信服务商接口,把这个自定义OTP下发给用户
- 用户提交验证码时,服务端对用户传入的验证码做相同的加盐哈希,和数据库存储的值比对,同时校验是否过期、尝试次数是否超限(最多允许5次错误,超限直接作废该条记录,15分钟内禁止该手机号再次发起验证请求)
- 验证通过后才允许执行后续数据重置操作,操作完成立刻把库中对应的OTP记录标记为已使用,避免验证码被重复复用。
三、如果一定要在注册阶段使用自有OTP(非必要不推荐)
如果你因为合规、短信通道要求等原因,注册阶段也必须用自己生成的OTP,可以走Firebase提供的自定义认证链路:
- 放弃Firebase默认的短信下发能力,注册时由你的ASP.NET服务端生成OTP,自己对接短信通道下发给用户
- 用户提交验证码后,服务端先校验自有OTP的合法性,校验通过后调用Firebase Admin SDK生成对应用户的Firebase自定义令牌,返回给客户端
- 客户端拿到自定义令牌后调用Firebase SDK完成登录,后续的鉴权逻辑和前面的方案保持一致
- 注意这个方案需要你自己实现所有OTP场景的防刷、防暴力破解、过期控制逻辑,还要自行承担短信费用,维护成本比用Firebase默认注册流程高很多。
注意:所有鉴权、校验逻辑必须在服务端实现,绝对不要信任客户端传来的任何状态标记,包括但不限于「已完成手机验证」「验证通过」这类字段。
内容的提问来源于stack exchange,提问作者Sulfy
相关产品推荐
相关产品推荐

