Flutter本地身份验证插件local_auth_wall的使用

Flutter本地身份验证插件local_auth_wall的使用

Getting Started

local_auth_wall 是一个用于简化本地身份验证的 Flutter widget。它可以根据用户的认证状态重定向到不同的 widget。

iOS Integration

在 iOS 上集成时,需要添加以下权限描述:

<key>NSFaceIDUsageDescription</key>
<string>为什么我的应用需要使用面部识别进行身份验证?</string>

Android Integration

该插件可以在 SDK 16+ 上构建和运行,但在 SDK 23(Android 6.0)之前,isDeviceSupported() 将始终返回 false。因此,你需要将你的 Activity 类型从 Activity 更改为 FlutterFragmentActivity

如果你直接使用 FlutterActivity,则需要将其更改为 FlutterFragmentActivity

<!-- 在 AndroidManifest.xml 中 -->
<activity android:name=".MainActivity" />

如果你使用的是自定义的 Activity,需要更新 MainActivity.javaMainActivity.kt 文件:

// MainActivity.java
import io.flutter.embedding.android.FlutterFragmentActivity;

public class MainActivity extends FlutterFragmentActivity {
  // ...
}
// MainActivity.kt
import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity: FlutterFragmentActivity() {
  // ...
}

Permissions

AndroidManifest.xml 文件中添加以下权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.app">
    <uses-permission android:name="android.permission.USE_BIOMETRIC"/>
</manifest>

Usage Example

在这个例子中,我们使用 MaterialApp.builder 来封装所有应用程序路由,并使用 ChangeNotifierProvider 来检查认证状态。

Basic usage

MaterialApp(
  builder: (BuildContext, child) {
    return LocalAuthWall(
      appConf: {
        AuthWallConfProperty.defaultHelpText: "请授权以访问。",
        AuthWallConfProperty.autoAuthRootRoute: true,
        AuthWallConfProperty.resetRootRouteOnAnyUnAuthorized: false,
      },
      stateWallWidgets: {
        AuthWallDefaultStates.booting: OnBootState(),
        AuthWallDefaultStates.unauthorized: NotAuthorizedState(),
        AuthWallDefaultStates.unsupported: NotSupportedState(),
        /// child 提供由 Flutter MaterialApp,通常是主页路由,在这种情况下是 MyHomePage
        /// root 必须与默认路由名称匹配
        AuthWallDefaultStates.defaultRoute: child ??
            Container(
              alignment: Alignment.center,
              color: Colors.amber,
              child: Text("Something is wrong, "
                  "where is my Home Widget??"),
            )
      },
    );
  },
  title: 'Flutter Demo',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  home: MyHomePage(title: 'Flutter Demo Home Page'),
);

Complete example (see the Example app)

import 'package:flutter/material.dart';
import 'package:local_auth_wall/local_auth_wall.dart';
import 'package:local_auth_wall/src/auth_wall_notifier.dart';
import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]);

  runApp(MyApp());
}

/// 当未授权时显示的 widget
class NotAuthorizedState extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        primary: false,
        body: Container(
          color: Colors.blue,
          alignment: Alignment.center,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text("请授权以访问"),
              TextButton(
                  onPressed: () {
                    context.read<AuthWallNotifier>().authorizeRoute(
                        AuthWallDefaultStates.defaultRoute.toString(),
                        "请授权以访问");
                  },
                  child: Icon(Icons.security))
            ],
          ),
        ));
  }
}

///
class OnBootState extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        primary: false,
        body: Container(
          color: Colors.orange,
          alignment: Alignment.center,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text("请等待,正在检查硬件支持"),
            ],
          ),
        ));
  }
}

/// 硬件要求不满足时显示的 widget
class NotSupportedState extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        primary: false,
        body: Container(
          color: Colors.blue,
          alignment: Alignment.center,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text("抱歉,此设备不受支持,请使用以下替代方法进行身份验证"),
              TextButton(
                  onPressed: () {
                    /// Call here...
                  },
                  child: Icon(Icons.security))
            ],
          ),
        ));
  }
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
        builder: (BuildContext, child) {
          return LocalAuthWall(
            appConf: {
              AuthWallConfProperty.defaultHelpText: "请授权以访问。",
              AuthWallConfProperty.autoAuthRootRoute: true,
              AuthWallConfProperty.resetRootRouteOnAnyUnAuthorized: false,
            },
            stateWallWidgets: {
              AuthWallDefaultStates.booting: OnBootState(),
              AuthWallDefaultStates.unauthorized: NotAuthorizedState(),
              AuthWallDefaultStates.unsupported: NotSupportedState(),

              /// child 提供由 Flutter MaterialApp,通常是主页路由,在这种情况下是 MyHomePage
              AuthWallDefaultStates.defaultRoute: child ??
                  Container(
                    alignment: Alignment.center,
                    color: Colors.amber,
                    child: Text("Something is wrong, "
                        "where is my Home Widget??"),
                  )
            },
          );
        },
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(title: 'Flutter Demo Home Page'));
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, this.title}) : super(key: key);
  final String? title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title!),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            TextButton(
                onPressed: () {
                  context.read<AuthWallNotifier>().authorizeRoute(
                      AuthWallDefaultStates.defaultRoute.toString());
                },
                child: Text("Tap to authorize Default Route")),
            Text(
              'Default Route authorized: ${context.watch<AuthWallNotifier>().routeIsAuthorized(AuthWallDefaultStates.defaultRoute.toString())}',
            ),
            Text(
              'Hardware supported: ${context.watch<AuthWallNotifier>().isSupported}',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context
              .read<AuthWallNotifier>()
              .authorizeRoute(
                  "show_ballance", "Please, authorize to see wallet balance")
              .then((_) {
            if (context
                .read<AuthWallNotifier>()
                .routeIsAuthorized("show_ballance")) {
              ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                backgroundColor: Colors.green,
                elevation: 4,
                dismissDirection: DismissDirection.down,
                content: SizedBox(
                  height: 60,
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Icon(Icons.security),
                      ),
                      Expanded(
                        child: Text(
                          "Nice, authorized with success!",
                          style: TextStyle(fontSize: 18),
                        ),
                      )
                    ],
                  ),
                ),
              ));
            } else {
              ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                backgroundColor: Colors.red,
                elevation: 4,
                dismissDirection: DismissDirection.down,
                content: SizedBox(
                  height: 60,
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Icon(Icons.security),
                      ),
                      Expanded(
                        child: Text(
                          "Sorry, NOT authorized with success!",
                          style: TextStyle(fontSize: 18),
                        ),
                      )
                    ],
                  ),
                ),
              ));
            }
          });
        },
        tooltip: 'Balance',
        child: Icon(Icons.balance),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

更多关于Flutter本地身份验证插件local_auth_wall的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter本地身份验证插件local_auth_wall的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


local_auth_wall 是一个基于 Flutter 的插件,用于在应用中添加本地身份验证(如指纹、面容识别等)的功能。它可以用来保护应用中的某些部分或整个应用,确保只有经过身份验证的用户才能访问。

以下是如何使用 local_auth_wall 插件的基本步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 local_auth_wall 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  local_auth_wall: ^1.0.0  # 请检查最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在你的 Dart 文件中导入 local_auth_wall 插件:

import 'package:local_auth_wall/local_auth_wall.dart';

3. 使用 LocalAuthWall

LocalAuthWall 是一个小部件,你可以将它包裹在你想要保护的 UI 部分。当用户尝试访问该部分时,系统会提示他们进行身份验证。

class ProtectedPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Protected Page'),
      ),
      body: LocalAuthWall(
        onSuccess: () {
          // 身份验证成功后的回调
          print('Authentication successful!');
        },
        onFailure: () {
          // 身份验证失败后的回调
          print('Authentication failed!');
        },
        child: Center(
          child: Text('This content is protected by local authentication.'),
        ),
      ),
    );
  }
}

4. 配置本地身份验证

local_auth_wall 插件依赖于 local_auth 插件,因此你需要确保在 Android 和 iOS 上正确配置 local_auth

Android 配置

AndroidManifest.xml 文件中添加以下权限:

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

iOS 配置

Info.plist 文件中添加以下内容:

<key>NSFaceIDUsageDescription</key>
<string>We need to use Face ID to secure your data.</string>

5. 处理身份验证结果

LocalAuthWall 提供了 onSuccessonFailure 回调函数,你可以在这些回调中处理身份验证成功或失败后的逻辑。

6. 自定义外观和行为

你可以通过传递额外的参数来自定义 LocalAuthWall 的外观和行为,例如:

  • authMessage: 身份验证时显示的消息。
  • cancelButton: 取消按钮的文本。
  • biometricOnly: 是否仅使用生物识别(如指纹或面容识别)。
LocalAuthWall(
  authMessage: 'Authenticate to access this content',
  cancelButton: 'Cancel',
  biometricOnly: true,
  onSuccess: () {
    // 身份验证成功后的回调
  },
  onFailure: () {
    // 身份验证失败后的回调
  },
  child: Center(
    child: Text('This content is protected by local authentication.'),
  ),
)
回到顶部