Flutter中无需认证流程,如何用OTP验证手机号?
无需绑定认证流程的Flutter手机号OTP验证实现方案
方案一:第三方短信服务+自定义后端验证
这是最直接的实现方式,完全脱离Firebase Auth绑定,仅完成纯手机号验证:
核心流程
- 前端收集用户手机号,附带当前登录用户ID,发送至你的后端接口
- 后端生成6位随机OTP,将OTP与用户ID、手机号关联后存储到Redis或数据库(设置5-10分钟过期时间)
- 后端调用第三方短信服务商(如Twilio、阿里云短信、腾讯云短信等)API,将OTP发送至用户手机号
- 用户输入OTP后,前端将OTP、手机号、用户ID发送到后端验证接口,后端对比存储的OTP,匹配则标记该用户手机号验证完成
Flutter前端核心代码示例
import 'package:dio/dio.dart'; import 'package:intl_phone_number_input/intl_phone_number_input.dart'; // 请求发送OTP Future<void> sendOtpRequest(String userId, PhoneNumber phoneNumber) async { try { await Dio().post( '/api/user/send-otp', data: { 'user_id': userId, 'phone': phoneNumber.phoneNumber, // 已格式化的手机号 }, ); // 提示用户OTP已发送 } catch (e) { // 处理网络错误或接口返回的异常(如手机号格式错误、发送次数超限) } } // 验证OTP Future<bool> verifyOtp(String userId, String phoneNumber, String otp) async { try { final response = await Dio().post( '/api/user/verify-otp', data: { 'user_id': userId, 'phone': phoneNumber, 'otp': otp, }, ); return response.data['is_valid'] == true; } catch (e) { return false; } }
- 关键注意事项
- 禁止在前端生成或存储OTP,所有验证逻辑必须在后端完成,避免安全漏洞
- 限制单手机号的OTP发送频率(如1分钟内最多发送1次),防止短信轰炸
- 用
intl_phone_number_input这类包做手机号格式校验和国际区号处理,过滤无效手机号
方案二:Firebase云函数+实时数据库(绕开Auth绑定)
如果不想额外搭建后端,可以用Firebase的云函数和实时数据库实现,不依赖Firebase Auth的手机号认证流程:
核心流程
- 前端调用Firebase云函数,传入用户ID和手机号
- 云函数生成OTP,将OTP写入实时数据库的
/otp_verifications/{user_id}节点,设置5分钟过期规则 - 云函数调用第三方短信服务商API发送OTP(不要用Firebase Auth的Phone Auth接口,避免绑定认证)
- 用户输入OTP后,前端调用云函数做验证(直接读取数据库节点对比也可,但云函数验证更安全)
云函数核心代码示例(Node.js)
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); exports.sendOtp = functions.https.onCall(async (data, context) => { const { userId, phone } = data; const otp = Math.floor(100000 + Math.random() * 900000).toString(); // 写入实时数据库并设置5分钟后自动删除 await admin.database().ref(`/otp_verifications/${userId}`).set({ otp, phone, createdAt: admin.database.ServerValue.TIMESTAMP, }); await admin.database().ref(`/otp_verifications/${userId}`).setPriority(admin.database.ServerValue.TIMESTAMP - 300000); // 调用第三方短信API发送OTP,示例用Twilio const twilio = require('twilio')('ACCOUNT_SID', 'AUTH_TOKEN'); await twilio.messages.create({ body: `你的验证码是:${otp}`, from: '+1234567890', to: phone }); return { success: true }; }); exports.verifyOtp = functions.https.onCall(async (data, context) => { const { userId, otp } = data; const snapshot = await admin.database().ref(`/otp_verifications/${userId}`).once('value'); const storedData = snapshot.val(); if (!storedData || storedData.otp !== otp) { return { isValid: false }; } // 验证成功后删除OTP节点,避免重复使用 await admin.database().ref(`/otp_verifications/${userId}`).remove(); // 将手机号写入用户信息节点 await admin.database().ref(`/users/${userId}/phone`).set(storedData.phone); return { isValid: true }; });
内容的提问来源于stack exchange,提问作者Elam
相关产品推荐
相关产品推荐

