许多用户依靠指纹或面部识别身份验证来实现对其设备的安全访问。有时我们可能希望使用相同的身份验证机制来允许用户以安全和轻松的方式访问我们的应用程序或其中的一部分。
在处理我的项目时,我需要实现此功能,我在设置中为用户提供了一个保护选项,在他能够访问应用程序数据之前,它基本上会要求指纹或面部识别身份验证。
在本文中,我们将使用local_auth
库实现此功能,它将在Android和iOS上无缝工作,我们将使用get_it
库将其实现为服务。
将local_auth添加到我们的项目中
首先,让我们首先将local_auth
和get_it
库导入pubspec.yaml。
...
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
local_auth: ^0.5.2+3
get_it: ^1.0.3+2
...
设置我们的LocalAuthenticationService
在我们的srvices文件夹中,创建local_authentication_service.dart文件并使用以下代码填充它。
import 'dart:io' show Platform;
import 'package:local_auth/local_auth.dart';
import 'package:flutter/services.dart';
class LocalAuthenticationService {
final _auth = LocalAuthentication();
bool _isProtectionEnabled = false;
bool get isProtectionEnabled => _isProtectionEnabled;
set isProtectionEnabled(bool enabled) => _isProtectionEnabled = enabled;
bool isAuthenticated = false;
Future<void> authenticate() async {
if (_isProtectionEnabled) {
try {
List<BiometricType> availableBiometrics =
await _auth.getAvailableBiometrics();
if (Platform.isIOS) {
if (availableBiometrics.contains(BiometricType.face)) {
// Face ID.
} else if (availableBiometrics.contains(BiometricType.fingerprint)) {
// Touch ID.
}
}
isAuthenticated = await _auth.authenticateWithBiometrics(
localizedReason: 'authenticate to access',
useErrorDialogs: true,
stickyAuth: true,
);
print(isAuthenicated);
} on PlatformException catch (e) {print(e);}
}
- _auth变量只是实例化LocalAuthentication库,这里没什么特别的。
- bool _isProtectionEnabled跟踪相应的设置,在真实的应用程序中,它应该存储在共享首选项中,尽管它超出了本文的范围。
- isAuthenticated变量将跟踪身份验证
最后,authenticate方法使用OS相关对话框启动身份验证流程。
stickyAuth属性设置为true,因此如果应用程序被系统置于后台,则插件不会返回失败。例如,如果用户在有机会进行身份验证之前收到了呼叫。将stickyAuth属性设置为false,插件将返回我们的dart代码失败。
设置服务定位器
在我们的services文件夹中创建service_locator.dart文件,并按如下方式注册LocalAuthentication单例。
import 'package:flutter_local_auth/services/local_authentication_service.dart';
import 'package:get_it/get_it.dart';
GetIt locator = GetIt();
void setupLocator() {
locator.registerLazySingleton(() => LocalAuthenticationService());
}
从main函数调用seupLocator()函数。
void main() {
setupLocator();
runApp(MyApp());
}
...
Android集成
为了在android上正确运行身份验证,我们必须做两件事。
首先,我们必须更新AndoridManifest.xml文件以包含USE_FINGERPRINT权限,如下所示。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.flutter_local_auth">
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
<application>
...
</application>
</manifest>
其次,在我们的Android应用程序的MainActivity.java文件中,我们必须使用相对导入将扩展类从FlutterActivity更改为FlutterFragmentActivity。
import android.os.Bundle;
import io.flutter.app.FlutterFragmentActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterFragmentActivity {
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
iOS集成
local_auth插件适用于TouchID和FaceID。但是,对于后者,我们需要将以下键值对添加到info.plist文件中
...
<key>NSFaceIDUsageDescription</key>
<string>Why is my app authenticating using face id?</string>
...
为示例构建基本UI
我们已完成逻辑部分。让我们快速构建UI以便测试它。
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final LocalAuthenticationService _localAuth = locator<LocalAuthenticationService>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset('assets/dancamdev.png'),
),
title: Text('Local Authentication'),
),
body: Center(
child: RaisedButton(
child: Text('authenticate'),
onPressed: _localAuth.authenticate,
),
),
);
}
UI由一个简单的居中按钮组成,重要的代码是使用定位器获取的LocalAuthenticationService,以及在按钮的onPressed中调用的authenticate方法。
注意事项
在LocalAuthenticationService中,在以下情况下,isAuthenticated变量将为false。
- 用户尚未通过身份验证
- 用户取消了身份验证
- 身份验证失败次数太多(指纹无法识别)
当用户成功通过身份验证时,情况将会如此。在真实世界的应用程序中,根据您的需要处理这些应用程序可能很有用。
GitHub链接为本文中显示的代码
我在本文中提供的所有代码以及如何使用它的示例都可以在GitHub上的此链接中找到。
结论
这是一个快速文章/片段,以便您开始使用flutter中的本地身份验证流程。我希望你喜欢这篇文章,它帮助你建立一个安全的扑动应用程序!