site logo

Marico's space

Flutter 应用生物识别认证的正确实现方式

Others 2026-07-01 17:34:06 3

最近给几个项目加了生物识别认证,踩了几个坑,顺手把正确的实现方式整理一下。这玩意儿看着简单,真正跑起来会发现一堆细节没处理到位,尤其是跨平台(安卓/iOS)的时候。

这篇文章不整那些花里胡哨的理论,直接上生产级代码和避坑指南。

为什么要用生物识别认证

先把价值说清楚,不然没法说服产品和老板:

  • 登录体验快,不需要输入密码
  • 比传统密码认证更安全,指纹和面部信息难以伪造
  • 安卓和iOS原生支持,不需要额外硬件
  • 用户信任度更高,留存率明显提升

Flutter 生态用什么

我们用的是官方维护的插件:

  • local_auth:Flutter官方出品,封装了底层原生API
  • 底层调用:Face ID/Touch ID(iOS)、指纹识别(Android)

就这么简单,不需要再找第三方库。

Step 1:添加依赖

dependencies: local_auth: ^3.0.1

然后拉取依赖:

flutter pub get

Step 2:平台配置

Android 配置

android/app/src/main/AndroidManifest.xml 里加上权限声明:

<uses-permission android:name="android.permission.USE_BIOMETRIC"/>

同时加上这个声明,让没有指纹功能的设备也能正常安装:

<uses-feature android:name="android.hardware.fingerprint" android:required="false"/>

iOS 配置

ios/Runner/Info.plist 里加上 Face ID 的使用描述:

<key>NSFaceIDUsageDescription</key>
<string>我们使用 Face ID 来安全验证您的身份</string>

⚠️ 这个必须加,不然 Face ID 直接跪,严重的会导致应用闪退。

Step 3:核心逻辑实现

生产级别的代码我们通常封装成一个 Service 类,把所有生物识别相关的操作都集中在这里:

import 'package:flutter/foundation.dart';
import 'package:local_auth/local_auth.dart'; class BiometricService { final LocalAuthentication _auth = LocalAuthentication(); /// 检查设备是否支持生物识别 Future<bool> isBiometricAvailable() async { try { final bool canCheckBiometrics = await _auth.canCheckBiometrics; final bool isDeviceSupported = await _auth.isDeviceSupported(); return canCheckBiometrics && isDeviceSupported; } catch (e) { debugPrint('生物识别可用性检查失败: $e'); return false; } } /// 获取可用的生物识别类型(指纹、面容等) Future<List<BiometricType>> getAvailableBiometrics() async { try { return await _auth.getAvailableBiometrics(); } catch (e) { debugPrint('获取生物识别类型失败: $e'); return []; } } /// 用户认证(可选是否只使用生物识别,不启用设备密码 fallback) Future<bool> authenticate({ bool biometricOnly = false, }) async { try { final bool isAvailable = await isBiometricAvailable(); if (!isAvailable) { debugPrint('该设备不支持生物识别'); return false; } final bool isAuthenticated = await _auth.authenticate( localizedReason: '请进行身份验证以继续', options: AuthenticationOptions( biometricOnly: biometricOnly, stickyAuth: true, useErrorDialogs: true, ), ); return isAuthenticated; } catch (e) { debugPrint('认证失败: $e'); return false; } }
}

Step 4:UI 层调用

业务代码里直接用这个 Service:

final BiometricService biometricService = BiometricService(); Future<void> loginWithBiometrics(BuildContext context) async { final bool isAuthenticated = await biometricService.authenticate(); if (isAuthenticated) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('身份验证成功'), ), ); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('验证失败,请重试'), ), ); }
}

一次实现,Face ID 和指纹都能用

这套方案最爽的地方在于:不需要写任何平台判断的逻辑。

同一套代码自动适配:

  • Android 指纹识别
  • iOS Face ID(面容 ID)
  • iOS Touch ID(老设备)

local_auth 会自动检测设备支持哪种生物识别方式,对业务层来说调用方式完全一样。

生产环境我们还会加上这些

实际项目里光能认证是不够的:

  • ✅ 用安全存储(flutter_secure_storage)保存用户是否开启生物识别的状态
  • ✅ 预留 PIN 或密码作为 fallback 方案
  • ✅ 在设置页面提供开关,让用户自己选择是否启用
  • ✅ 应用启动时自动触发生物识别(如果用户之前开启过)

我们见过的典型错误

这部分是重点,大部分实现翻车都在这里:

1. 不处理不支持的设备

很多开发者默认生物识别肯定能用。

👉 正确做法:每次认证前先检查:

✅ canCheckBiometrics
✅ isDeviceSupported

2. 漏掉 iOS 的权限配置

NSFaceIDUsageDescription 没配是踩坑重灾区。

👉 后果:要么闪退,要么直接提示认证失败,用户一脸懵。

3. 没有 fallback 方案

生物识别失败的原因太多了:

  • 手指沾水
  • 面部被遮挡
  • 传感器故障

👉 必须提供:

  • PIN 码或密码作为备选

4. 默认强制开启,没给用户选择权

绝对不能默认开启生物识别。

👉 正确做法:

  • 首次使用时弹出引导,让用户自己决定
  • 在设置页面可以随时开关

5. 异常处理太粗糙

大多数开发者 catch 到异常直接返回 false,然后就没然后了。

👉 更好的做法:

  • 分类处理不同类型的异常
  • 给用户有意义的提示信息

6. 不测边界情况

生物识别流程在某些场景下表现不一样:

  • 应用切到后台再切回来
  • 锁屏后解锁
  • 连续多次认证失败

👉 测试清单:

  • 后台/前台切换
  • 锁屏场景
  • 多次失败后的锁定逻辑

7. 把生物识别当作唯一的安全层

生物识别只是本地认证手段,不能替代后端验证。

👉 必须配合:

  • 安全的 Token 机制
  • 后端接口二次校验

真正把这事儿做对的几个关键

踩了这么多坑,总结下来就几点:

  • 生物识别逻辑单独封装成 Service,便于维护和测试
  • 永远提供 fallback 认证方式
  • 尊重用户隐私,让用户自己决定是否启用
  • 真机测试,别光在模拟器上跑
  • 体验要顺滑,不要为了安全牺牲太多便捷性

总结

生物识别认证是个好东西,但真正用好并不简单。

不是加个指纹按钮或 Face ID 按钮就完事了,关键是打造一个安全、流畅、可靠的认证体验。

做对了,安全性和用户体验能同时上一个台阶。

如果你正在做 Flutter 应用,想提升登录体验,这功能值得认真对待。