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

如何在Flutter应用中通过Firebase实现APP内邮箱OTP改密码?是否免费?

Firebase 邮箱验证+APP内改密方案(Flutter)

1. 是否支持该功能?

Firebase本身没有直接提供“邮箱OTP验证码验证后改密”的原生流程,但可以通过结合邮箱链接登录验证和密码修改API实现完全在APP内完成改密的需求——本质是用邮箱链接完成用户身份验证(替代OTP验证码的作用),验证通过后直接在APP内调用接口修改密码。

2. 具体实现步骤(Flutter)

步骤1:发送邮箱验证链接

用户输入注册邮箱后,调用Firebase的sendSignInLinkToEmail方法,配置handleCodeInApp: true让链接跳转回APP,同时设置对应的deep link和平台参数:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:shared_preferences/shared_preferences.dart';

Future<void> sendResetLink(String userEmail) async {
  final actionCodeSettings = ActionCodeSettings(
    url: 'https://yourapp.page.link/reset', // 你的APP专属deep link
    handleCodeInApp: true,
    iOSBundleId: 'com.yourapp.ios', // iOS包名
    androidPackageName: 'com.yourapp.android', // Android包名
    androidInstallApp: true,
    androidMinimumVersion: '12',
  );

  await FirebaseAuth.instance.sendSignInLinkToEmail(
    email: userEmail,
    actionCodeSettings: actionCodeSettings,
  );
  
  // 临时保存邮箱到本地,后续验证需要
  final prefs = await SharedPreferences.getInstance();
  prefs.setString('reset_temp_email', userEmail);
}

步骤2:处理APP内的验证链接

配置Firebase Dynamic Links接收跳转回APP的链接,验证链接有效性并完成身份验证:

import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';

void initDynamicLinks(BuildContext context) async {
  // 处理APP启动时的链接
  final initialLink = await FirebaseDynamicLinks.instance.getInitialLink();
  if (initialLink != null) {
    _handleResetLink(initialLink.link, context);
  }

  // 监听后台唤醒的链接
  FirebaseDynamicLinks.instance.onLink.listen((dynamicLinkData) {
    _handleResetLink(dynamicLinkData.link, context);
  });
}

Future<void> _handleResetLink(Uri deepLink, BuildContext context) async {
  if (FirebaseAuth.instance.isSignInWithEmailLink(deepLink.toString())) {
    final prefs = await SharedPreferences.getInstance();
    final email = prefs.getString('reset_temp_email');
    
    if (email != null) {
      try {
        // 完成身份验证(无需密码,通过链接确认用户身份)
        await FirebaseAuth.instance.signInWithEmailLink(
          email: email,
          emailLink: deepLink.toString(),
        );
        
        // 验证成功,跳转到APP内的改密页面
        Navigator.push(
          context,
          MaterialPageRoute(builder: (_) => const ResetPasswordPage()),
        );
      } catch (e) {
        // 处理验证失败(如链接过期、邮箱不匹配等)
        print('验证失败: $e');
      }
    }
  }
}

步骤3:APP内修改密码

在改密页面,调用Firebase的updatePassword方法完成密码修改:

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';

class ResetPasswordPage extends StatefulWidget {
  const ResetPasswordPage({super.key});

  @override
  State<ResetPasswordPage> createState() => _ResetPasswordPageState();
}

class _ResetPasswordPageState extends State<ResetPasswordPage> {
  final _newPasswordController = TextEditingController();
  final _auth = FirebaseAuth.instance;

  Future<void> _resetPassword() async {
    final user = _auth.currentUser;
    final newPassword = _newPasswordController.text.trim();
    
    if (user != null && newPassword.isNotEmpty) {
      try {
        await user.updatePassword(newPassword);
        // 改密成功,提示用户并退出登录
        await _auth.signOut();
        Navigator.popUntil(context, (route) => route.isFirst);
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('密码修改成功,请重新登录')),
        );
      } catch (e) {
        // 处理错误(如密码强度不足、用户会话过期等)
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('修改失败: ${e.toString()}')),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('修改密码')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _newPasswordController,
              obscureText: true,
              decoration: const InputDecoration(labelText: '新密码'),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _resetPassword,
              child: const Text('确认修改'),
            ),
          ],
        ),
      ),
    );
  }
}

3. 免费计划是否包含该功能?

是的,Firebase免费计划(Spark计划)完全支持上述功能:

  • 邮箱验证链接的发送和验证属于**身份验证(Authentication)**服务的免费内容,每月免费额度包含10,000条验证邮件发送;
  • 用户密码修改API调用也属于Authentication的基础功能,无额外收费,只要不超过免费计划的其他限制(如每月活跃用户数等)即可正常使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:50:31