Flutter身份验证管理插件auth_management的使用

Flutter身份验证管理插件auth_management的使用

auth_management 是一个用于Flutter应用程序的身份验证管理插件,支持多种登录方式(如Email、Phone、Google、Facebook等),并提供了用户数据备份和恢复的功能。以下是使用该插件的详细步骤。

导入库

首先需要导入 auth_management 库:

import 'package:auth_management/core.dart';

创建授权用户的键(可选)

可以创建自定义的用户键类来管理用户信息:

class UserKeys extends AuthKeys {
  final address = "address";
  final contact = "contact";

  const UserKeys._();

  static UserKeys? _i;

  static UserKeys get i => _i ??= const UserKeys._();
}

创建授权用户模型(可选)

定义用户模型类,继承自 Auth<UserKeys>

class UserModel extends Auth<UserKeys> {
  final Address? _address;
  final Contact? _contact;

  Address get address => _address ?? Address();
  Contact get contact => _contact ?? Contact();

  UserModel({
    super.id,
    super.timeMills,
    super.accessToken,
    super.biometric,
    super.email,
    super.extra,
    super.idToken,
    super.loggedIn,
    super.loggedInTime,
    super.loggedOutTime,
    super.name,
    super.password,
    super.phone,
    super.photo,
    super.provider,
    super.username,
    super.verified,
    Address? address,
    Contact? contact,
  }) : _address = address, _contact = contact;

  factory UserModel.from(Object? source) {
    final key = UserKeys.i;
    final root = Auth.from(source);
    return UserModel(
      id: root.id,
      timeMills: root.timeMills,
      accessToken: root.accessToken,
      biometric: root.biometric,
      email: root.email,
      extra: root.extra,
      idToken: root.idToken,
      loggedIn: root.loggedIn,
      loggedInTime: root.loggedInTime,
      loggedOutTime: root.loggedOutTime,
      name: root.name,
      password: root.password,
      phone: root.phone,
      photo: root.photo,
      provider: root.provider,
      username: root.username,
      verified: root.verified,
      address: source.entityObject(key.address, Address.from),
      contact: source.entityObject(key.contact, Contact.from),
    );
  }

  [@override](/user/override)
  UserModel copy({
    String? id,
    int? timeMills,
    String? accessToken,
    String? biometric,
    String? email,
    Map<String, dynamic>? extra,
    String? idToken,
    bool? loggedIn,
    int? loggedInTime,
    int? loggedOutTime,
    String? name,
    String? password,
    String? phone,
    String? photo,
    String? provider,
    String? username,
    bool? verified,
    Address? address,
    Contact? contact,
  }) {
    return UserModel(
      id: id ?? this.id,
      timeMills: timeMills ?? this.timeMills,
      accessToken: accessToken ?? this.accessToken,
      biometric: biometric ?? this.biometric,
      email: email ?? this.email,
      extra: extra ?? this.extra,
      idToken: idToken ?? this.idToken,
      loggedIn: loggedIn ?? this.loggedIn,
      loggedInTime: loggedInTime ?? this.loggedInTime,
      loggedOutTime: loggedOutTime ?? this.loggedOutTime,
      name: name ?? this.name,
      password: password ?? this.password,
      phone: phone ?? this.phone,
      photo: photo ?? this.photo,
      provider: provider ?? this.provider,
      username: username ?? this.username,
      verified: verified ?? this.verified,
      address: address ?? this.address,
      contact: contact ?? this.contact,
    );
  }

  [@override](/user/override)
  UserKeys makeKey() => UserKeys.i;

  [@override](/user/override)
  Map<String, dynamic> get source {
    return super.source
      ..addAll({
        key.address: _address?.source,
        key.contact: _contact?.source,
      });
  }
}

class Address extends Entity {
  Address();

  factory Address.from(Object? source) {
    return Address();
  }
}

class Contact extends Entity {
  Contact();

  factory Contact.from(Object? source) {
    return Contact();
  }
}

创建授权用户备份代理

实现 BackupDelegate<UserModel> 接口来处理用户的备份逻辑:

class UserBackupDelegate extends BackupDelegate<UserModel> {
  [@override](/user/override)
  Future<UserModel?> get(String id) async {
    // fetch authorized user data from remote server
    log("Authorized user id : $id");
    return null;
  }

  [@override](/user/override)
  Future<void> create(UserModel data) async {
    // Store authorized user data in remote server
    log("Authorized user data : $data");
  }

  [@override](/user/override)
  Future<void> update(String id, Map<String, dynamic> data) async {
    // Update authorized user data in remote server
    log("Authorized user data : $data");
  }

  [@override](/user/override)
  Future<void> delete(String id) async {
    // Clear unauthorized user data from remote server
    log("Unauthorized user id : $id");
  }

  [@override](/user/override)
  UserModel build(Map<String, dynamic> source) => UserModel.from(source);
}

初始化Firebase应用和Widget绑定

main.dart 中初始化 Firebase 和 Widget 绑定:

import 'package:firebase_core/firebase_core.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(const Application());
}

在根级别添加认证提供者

AuthProvider<UserModel> 添加到应用的根级:

import 'package:auth_management/core.dart';
import 'package:auth_management_biometric_delegate/auth_management_biometric_delegate.dart';
import 'package:auth_management_google_delegate/auth_management_google_delegate.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:shared_preferences/shared_preferences.dart';

class Application extends StatelessWidget {
  const Application({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return AuthProvider<UserModel>(
      initialCheck: true,
      authorizer: Authorizer(
        authRepository: AuthRepository.create(
          biometricAuthDelegate: BiometricAuthDelegate(),
          googleAuthDelegate: GoogleAuthDelegate(
            googleSignIn: GoogleSignIn(scopes: ['email']),
          ),
        ),
        backupRepository: BackupRepository.create(
          key: "_local_user_key_",
          delegate: UserBackupDelegate(),
          reader: (key) async {
            final db = await SharedPreferences.getInstance();
            return db.getString(key);
          },
          writer: (key, value) async {
            final db = await SharedPreferences.getInstance();
            if (value == null) {
              return db.remove(key);
            }
            return db.setString(key, value);
          },
        ),
      ),
      child: MaterialApp(
        title: 'Auth Management',
        theme: ThemeData(
          primaryColor: Colors.deepOrange,
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange, primary: Colors.deepOrange),
          elevatedButtonTheme: ElevatedButtonThemeData(
            style: ElevatedButton.styleFrom(backgroundColor: Colors.deepOrange, foregroundColor: Colors.white),
          ),
          inputDecorationTheme: InputDecorationTheme(border: OutlineInputBorder(borderRadius: BorderRadius.circular(8))),
        ),
        initialRoute: "startup",
        onGenerateRoute: routes,
      ),
    );
  }
}

Route<T>? routes<T>(RouteSettings settings) {
  final name = settings.name;
  if (name == "home") {
    return MaterialPageRoute(builder: (_) => const HomePage());
  } else if (name == "login") {
    return MaterialPageRoute(builder: (_) => const LoginPage());
  } else if (name == "register") {
    return MaterialPageRoute(builder: (_) => const RegisterPage());
  } else if (name == "oauth") {
    return MaterialPageRoute(builder: (_) => const OAuthPage());
  } else if (name == "startup") {
    return MaterialPageRoute(builder: (_) => const StartupPage());
  }
  return null;
}

创建启动屏幕

创建一个启动屏幕来检查用户是否已登录:

import 'package:auth_management/core.dart';

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

  [@override](/user/override)
  State<StartupPage> createState() => _StartupPageState();
}

class _StartupPageState extends State<StartupPage> {
  void _showError(BuildContext context, String error) {
    log("AUTH ERROR : $error");
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(error)));
  }

  void _showLoading(BuildContext context, bool loading) {
    log("AUTH LOADING : $loading");
  }

  void _showMessage(BuildContext context, String message) {
    log("AUTH MESSAGE : $message");
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
  }

  void _status(BuildContext context, AuthState state, UserModel? user) {
    log("AUTH STATUS : $state");
    if (state.isAuthenticated) {
      Navigator.pushNamedAndRemoveUntil(context, "home", (route) => false);
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return AuthObserver<UserModel>(
      onError: _showError,
      onMessage: _showMessage,
      onLoading: _showLoading,
      onStatus: _status,
      child: Scaffold(
        backgroundColor: Colors.white,
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              ElevatedButton(onPressed: () { Navigator.pushNamed(context, "login"); }, child: const Text("Login")),
              const SizedBox(height: 24),
              ElevatedButton(onPressed: () { Navigator.pushNamed(context, "login"); }, child: const Text("Register")),
            ],
          ),
        ),
      ),
    );
  }
}

创建登录/注册屏幕

创建登录和注册页面,允许用户通过不同的方式登录或注册:

import 'package:auth_management/core.dart';

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

  [@override](/user/override)
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final etName = TextEditingController();
  final etEmail = TextEditingController();
  final etPhone = TextEditingController();
  final etPassword = TextEditingController();
  final etOTP = TextEditingController();
  String? token;

  void signInByEmail() async {
    final email = etEmail.text;
    final password = etPassword.text;
    context.signInByEmail<UserModel>(EmailAuthenticator(email: email, password: password));
  }

  void signUpByEmail() async {
    final name = etName.text;
    final email = etEmail.text;
    final password = etPassword.text;
    context.signUpByEmail<UserModel>(EmailAuthenticator(email: email, password: password, name: name));
  }

  // 其他登录和注册方法...

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("LOGIN", style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), centerTitle: true),
      body: ListView(padding: const EdgeInsets.all(32), children: [
        TextField(controller: etEmail, keyboardType: TextInputType.emailAddress, decoration: const InputDecoration(hintText: "Email")),
        const SizedBox(height: 24),
        TextField(controller: etName, keyboardType: TextInputType.name, decoration: const InputDecoration(hintText: "Name")),
        const SizedBox(height: 24),
        TextField(controller: etPassword, keyboardType: TextInputType.visiblePassword, obscureText: true, decoration: const InputDecoration(hintText: "Password")),
        const SizedBox(height: 24),
        TextField(controller: etPhone, keyboardType: TextInputType.phone, decoration: const InputDecoration(hintText: "Phone")),
        const SizedBox(height: 24),
        TextField(controller: etOTP, keyboardType: TextInputType.number, decoration: const InputDecoration(hintText: "OTP")),
        const SizedBox(height: 32),
        SizedBox(width: double.infinity, child: ElevatedButton(onPressed: signInByEmail, child: const Text("Login (Email)"))),
        const SizedBox(height: 12),
        SizedBox(width: double.infinity, child: ElevatedButton(onPressed: signUpByEmail, child: const Text("Sign Up (Email)"))),
        // 其他按钮...
      ]),
    );
  }
}

创建主页

在主页中显示用户信息,并提供注销和更新账户的功能:

import 'package:auth_management/core.dart';

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

  [@override](/user/override)
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  void _signOut() {
    context.signOut<UserModel>();
  }

  void _updateUser() {
    context.updateAccount<UserModel>({UserKeys.i.name: "Updated name"});
  }

  void _biometricEnable(bool? value) {
    context.biometricEnable<UserModel>(value ?? false).then((value) {
      log("Biometric enable status : ${value.exception}");
    });
  }

  void _biometricChange(BuildContext context) {
    context.addBiometric<UserModel>(
      config: const BiometricConfig(signInTitle: "Biometric", localizedReason: "Scan your face or fingerprint"),
      callback: (value) => showDialog<BiometricStatus>(context: context, builder: (context) {
        return AlertDialog(title: const Text("Biometric permission from user!"), actions: [
          ElevatedButton(child: const Text("Cancel"), onPressed: () { Navigator.pop(context, BiometricStatus.initial); }),
          ElevatedButton(child: const Text("Inactivate"), onPressed: () { Navigator.pop(context, BiometricStatus.inactivated); }),
          ElevatedButton(child: const Text("Activate"), onPressed: () { Navigator.pop(context, BiometricStatus.activated); }),
        ]);
      }),
    ).then((value) {
      log("Add biometric status : ${value.exception}");
    });
  }

  void _showSnackBar(BuildContext context, String msg) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(msg)));
  }

  void _showLoading(BuildContext context, bool loading) {}

  void _status(BuildContext context, AuthState state, UserModel? user) {
    if (state.isUnauthenticated) {
      Navigator.pushNamedAndRemoveUntil(context, "login", (route) => false);
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: AuthObserver<UserModel>(
          onError: _showSnackBar,
          onMessage: _showSnackBar,
          onLoading: _showLoading,
          onStatus: _status,
          child: AuthConsumer<UserModel>(
            builder: (context, value) {
              return Container(
                padding: const EdgeInsets.all(32),
                alignment: Alignment.center,
                child: Column(mainAxisSize: MainAxisSize.min, children: [
                  Container(width: 150, height: 150, clipBehavior: Clip.antiAlias, decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.black.withOpacity(0.1)), child: value?.photo == null ? null : Image.network(value?.photo ?? "", fit: BoxFit.cover)),
                  const SizedBox(height: 24),
                  Text(value?.name ?? "", style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold)),
                  Text(value?.email ?? "", style: Theme.of(context).textTheme.titleMedium),
                  Text("Account created at ".join(DateProvider.toRealtime(value?.timeMills ?? 0)), style: Theme.of(context).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.normal)),
                  const SizedBox(height: 12),
                  Opacity(opacity: value?.mBiometric.isInitial ?? false ? 0.5 : 1, child: SwitchListTile.adaptive(value: value?.isBiometric ?? false, onChanged: _biometricEnable, title: const Text("Biometric mode"), contentPadding: const EdgeInsets.only(left: 24, right: 16))),
                  const SizedBox(height: 24),
                  SizedBox(width: double.infinity, child: ElevatedButton(onPressed: _updateUser, child: const Text("Update"))),
                  const SizedBox(height: 8),
                  SizedBox(width: double.infinity, child: ElevatedButton(onPressed: () => _biometricChange(context), child: const Text("Add biometric"))),
                  const SizedBox(height: 8),
                  SizedBox(width: double.infinity, child: ElevatedButton(onPressed: _signOut, child: const Text("Logout"))),
                ]),
              );
            },
          ),
        ),
      ),
    );
  }
}

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

1 回复

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


当然,auth_management 是一个用于 Flutter 的身份验证管理插件,它可以帮助开发者更轻松地管理用户的身份验证流程。下面是一个简单的代码案例,展示了如何使用 auth_management 插件进行身份验证管理。

首先,确保你已经在 pubspec.yaml 文件中添加了 auth_management 依赖:

dependencies:
  flutter:
    sdk: flutter
  auth_management: ^x.y.z  # 请替换为最新版本号

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

接下来,假设你已经设置好了 Firebase Authentication,下面是如何使用 auth_management 进行用户注册和登录的示例代码。

1. 初始化 Firebase Authentication

在你的 Flutter 应用的入口文件(通常是 main.dart)中,初始化 Firebase:

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

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

2. 创建 AuthService 类

创建一个 AuthService 类来封装身份验证逻辑:

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

class AuthService {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  // 用户注册
  Future<void> registerWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.createUserWithEmailAndPassword(
        email: email,
        password: password,
      );
      User? user = result.user;

      // 在这里可以添加额外的用户信息,比如保存到 Firestore
      // await FirebaseFirestore.instance.collection('users').doc(user!.uid).set({
      //   'email': user.email,
      // });

      print('User registered: ${user!.uid}');
    } catch (e) {
      print(e.toString());
    }
  }

  // 用户登录
  Future<User?> signInWithEmailAndPassword(String email, String password) async {
    try {
      UserCredential result = await _auth.signInWithEmailAndPassword(
        email: email,
        password: password,
      );
      return result.user;
    } catch (e) {
      print(e.toString());
      return null;
    }
  }

  // 登出用户
  Future<void> signOut() async {
    await _auth.signOut();
  }
}

3. 使用 AuthService 类

在你的 UI 组件中使用 AuthService 类来处理用户注册和登录:

import 'package:flutter/material.dart';
import 'auth_service.dart';  // 假设你将 AuthService 类放在这个文件里

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  final AuthService _authService = AuthService();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Auth Demo',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Auth Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                onPressed: () {
                  // 显示注册表单
                  showDialog(
                    context: context,
                    builder: (context) => AlertDialog(
                      title: Text('Register'),
                      content: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          TextField(
                            decoration: InputDecoration(labelText: 'Email'),
                            onChanged: (email) {
                              _emailController.text = email;
                            },
                          ),
                          TextField(
                            obscureText: true,
                            decoration: InputDecoration(labelText: 'Password'),
                            onChanged: (password) {
                              _passwordController.text = password;
                            },
                          ),
                        ],
                      ),
                      actions: <Widget>[
                        TextButton(
                          onPressed: () {
                            Navigator.of(context).pop();
                          },
                          child: Text('Cancel'),
                        ),
                        TextButton(
                          onPressed: () async {
                            await _authService.registerWithEmailAndPassword(
                              _emailController.text,
                              _passwordController.text,
                            );
                            Navigator.of(context).pop();
                            // 可以添加跳转到主屏幕的逻辑
                          },
                          child: Text('Register'),
                        ),
                      ],
                    ),
                  );

                  // 临时控制器,用于在对话框中捕获文本输入
                  final TextEditingController _emailController =
                      TextEditingController();
                  final TextEditingController _passwordController =
                      TextEditingController();
                },
                child: Text('Register'),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  // 显示登录表单
                  showDialog(
                    context: context,
                    builder: (context) => AlertDialog(
                      title: Text('Login'),
                      content: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          TextField(
                            decoration: InputDecoration(labelText: 'Email'),
                            onChanged: (email) {
                              _emailController.text = email;
                            },
                          ),
                          TextField(
                            obscureText: true,
                            decoration: InputDecoration(labelText: 'Password'),
                            onChanged: (password) {
                              _passwordController.text = password;
                            },
                          ),
                        ],
                      ),
                      actions: <Widget>[
                        TextButton(
                          onPressed: () {
                            Navigator.of(context).pop();
                          },
                          child: Text('Cancel'),
                        ),
                        TextButton(
                          onPressed: () async {
                            User? user = await _authService.signInWithEmailAndPassword(
                              _emailController.text,
                              _passwordController.text,
                            );
                            if (user != null) {
                              Navigator.of(context).pop();
                              // 可以添加跳转到主屏幕的逻辑
                            }
                          },
                          child: Text('Login'),
                        ),
                      ],
                    ),
                  );

                  // 临时控制器,用于在对话框中捕获文本输入
                  final TextEditingController _emailController =
                      TextEditingController();
                  final TextEditingController _passwordController =
                      TextEditingController();
                },
                child: Text('Login'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

这个示例展示了如何使用 auth_management(虽然实际上 auth_management 插件本身并未直接在此示例中使用,因为它更多地是一个概念或框架,而具体的身份验证操作通常是通过 Firebase Auth 等服务完成的)结合 Firebase Auth 进行用户注册和登录。希望这对你有所帮助!

回到顶部