Flutter身份验证插件fire_autho的使用

发布于 1周前 作者 nodeper 来自 Flutter

Flutter身份验证插件fire_autho的使用

Firebase Authentication Manager

状态 版本

注意:此项目正在开发中,是未官方认证的。您可以发送拉取请求来贡献。

功能

所有功能在移动设备和网页上均可用,但我无法在iOS上进行测试。

  • 使用邮箱注册和登录。
  • 匿名登录(可以与其它凭证关联)。
  • 使用Google、Twitter和手机号码登录。
  • 关联多个账户。
  • 删除账户。
  • 验证账户。
  • 使用提供者监听认证状态。

初始化

首先,初始化Firebase设置。有关教程,请参阅 Firebase文档

index.html
<script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.2.6/firebase-analytics.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.1.1/firebase-auth.js"></script>

<script>
    var firebaseConfig = {
        apiKey: "********",
        authDomain: "******.firebaseapp.com",
        projectId: "****",
        storageBucket: "****.appspot.com",
        messagingSenderId: "******",
        appId: "********",
        measurementId: "****"
    };

    firebase.initializeApp(firebaseConfig);
    firebase.analytics();
</script>

您需要在小部件树的顶部使用 ChangeNotifierProvider

main.dart
void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(ChangeNotifierProvider(create: (context) => AuthManager(), child: MyApp()));
}

class MyHomePage extends StatefulWidget {
  AuthManager manager = AuthManager(); // Singleton class.

  MyHomePage(){
    manager.setTwitterConsumerKeys("consumer_key","consumer_secret_key");
      // 如果您将使用Twitter登录,则必须调用此函数。
  }
}

在网页上配置Google登录

请按照 此视频 配置您的项目和Google云API。确保您已在云端添加本地主机。

<script src="https://apis.google.com/js/platform.js" async defer></script>
<meta name="google-signin-client_id" content="xxxxxxxxxx.apps.googleusercontent.com">

示例用法

所有方法的使用都在示例项目中展示。

onPressed: () async {
  AuthResponse response = await manager.signInWithMailPass(
      mailFieldController.text, passFieldController.text);  // 提供邮箱和密码。
 // 您也可以通过 Provider.of<AuthManager>(context) 获取manager。
 if (response.status == Status.Failed) {
     showSnack(response);  // 显示失败消息或处理。
   }
},

AuthResponse response = await Provider.of<AuthManager>(context).signInWithGoogle();
print(response.message + response.code); // response.status 可以是 Failed, Successed, Waiting

手机登录

AuthResponse response = await Provider.of<AuthManager>(context, listen:false).signInWithPhone(phoneNumberString, context);
// 这将发送一条短信。如果成功,您会得到 response.type == Status.Waiting 而不是 Status.Successed。操作将在您确认短信验证码时完成。

AuthResponse response = await Provider.of<AuthManager>(context, listen:false).verifyPhoneSignForWeb(_smsController.text);
// 当您收到短信验证码时调用此方法。我在按钮点击事件中使用它。

示例代码

example/lib/main.dart

import 'package:example/RaisedButton.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:fire_autho/fire_autho.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:provider/provider.dart';
import 'package:sms_autofill/sms_autofill.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized(); // !!!

  runApp(ChangeNotifierProvider(
      create: (context) => AuthManager(), child: MyApp()));
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fire Autho Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  AuthManager manager = AuthManager(); // Singleton class. 初始化在这里。

  MyHomePage() {
    //  manager.setTwitterConsumerKeys("consumer_key","consumer_secret_key"); // 如果您将使用Twitter登录,则必须调用此函数。
  }

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

class _MyHomePageState extends State<MyHomePage> {
  final mailFieldController = TextEditingController();
  final passFieldController = TextEditingController();
  final resetFieldController = TextEditingController();

  final TextEditingController _phoneNumberController = TextEditingController();
  final TextEditingController _smsController = TextEditingController();

  String? _verificationId;
  final SmsAutoFill _autoFill = SmsAutoFill();

  [@override](/user/override)
  void dispose() {
    mailFieldController.dispose();
    passFieldController.dispose();
    _phoneNumberController.dispose();
    _smsController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: SafeArea(
          child: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: buildUserListener(),
                ),
                SizedBox(
                    width: 300,
                    child: TextField(
                      controller: mailFieldController,
                      decoration: InputDecoration(hintText: "mail"),
                    )),
                SizedBox(
                    width: 300,
                    child: TextField(
                        controller: passFieldController,
                        decoration: InputDecoration(hintText: "pass"))),
                buildMailPassSignIn(),
                buildMailPass(),
                buildAnonSignIn(),
                buildLogOut(),
                buildGoogleSignIn(),
                buildPhoneInput(),
                buildResetMailSection(),
                buildVerificationInput(),
                Container(
                  padding: const EdgeInsets.only(top: 16.0),
                  alignment: Alignment.center,
                  child: buildsignInWithPhoneNumber(),
                ),
                buildVerifyCodeButton(),
                kIsWeb
                    ? Container()
                    : buildGetNumberButton(), // 检测平台。仅在移动设备上。
                SizedBox(
                  height: 20,
                ),
                buildLinkMailAuth(),
                buildLinkPhoneAuth(),
                buildVerifyLinkPhoneAuth(),
                buildLinkGoogleAuth(),
                buildDeleteButton(),
                buildVerificationMailButton(),
                buildReloadButton(),
                buildReSignButton(),
                SizedBox(
                  height: 50,
                )
              ],
            ),
          ),
        ),
      ),
    );
  }

  Padding buildVerificationInput() {
    return Padding(
      padding: const EdgeInsets.all(40.0),
      child: TextFormField(
        controller: _smsController,
        decoration: const InputDecoration(labelText: 'Verification code'),
      ),
    );
  }

  Widget buildGetNumberButton() {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 16.0),
      alignment: Alignment.center,
      child: RaisedButton(
          child: Text("Get current number"),
          onPressed: () async =>
          {_phoneNumberController.text = (await _autoFill.hint)!},
          color: Colors.greenAccent[700]),
    );
  }

  // TODO 它有效。可以使用。
  Widget buildStreamBuilder() {
    return Consumer<AuthManager>(
      builder: (context, cart, child) => Stack(
        children: [
          cart.auth != null
              ? StreamBuilder<User?>(
            stream: widget.manager.onAuthStateChanged,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.active) {
                User? user = snapshot.data;
                if (user == null) {
                  return Text("No user");
                }
                return Padding(
                  padding: const EdgeInsets.all(30.0),
                  child: Text("::" + widget.manager.user.toString()),
                );
              } else {
                return SizedBox(
                  height: 200,
                  width: 200,
                  child: Scaffold(
                    body: Center(
                      child: CircularProgressIndicator(),
                    ),
                  ),
                );
              }
            },
          )
              : Text("No No No"),
        ],
      ),
      // 构建昂贵的小部件。
    );
  }

  // 显示用户状态
  Widget buildUserListener() {
    return Consumer<AuthManager>(
      builder: (context, userSnap, child) => Stack(
        children: [
          userSnap.auth != null
              ? Text(
              userSnap.user != null ? userSnap.user.toString() : "No user")
              : Text("No No No"),
        ],
      ),
      // 构建昂贵的小部件。
    );
  }

  Widget buildAnonSignIn() {
    return CustomRaisedButton(
      child: Text("Sign in anonymously"),
      onPressed: () async {
        AuthResponse response = await widget.manager.signInAnonymous();
        if (response.status == Status.Failed) {
          showSnack(response);
        }
        widget.manager.printAuthStats();
      },
    );
  }

  Widget buildMailPass() {
    return CustomRaisedButton(
      child: Text("Sign in"),
      onPressed: () async {
        AuthResponse response = await widget.manager.signInWithMailPass(
            mailFieldController.text, passFieldController.text);
        widget.manager.printAuthStats();
        if (response.status == Status.Failed) {
          showSnack(response);
        }
      },
    );
  }

  void showSnack(AuthResponse response) {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text("Failed:" + response.message!),
    ));
  }

  Widget buildMailPassSignIn() {
    return CustomRaisedButton(
      child: Text("Sign Up"),
      onPressed: () async {
        AuthResponse response = await widget.manager.signUpWithMailPass(
            mailFieldController.text, passFieldController.text);
        widget.manager.printAuthStats();
        if (response.status == Status.Failed) {
          showSnack(response);
        }
      },
    );
  }

  Widget buildLogOut() {
    return CustomRaisedButton(
      child: Text("Log out"),
      onPressed: () async {
        await widget.manager.signOut();
      },
    );
  }

  Widget buildGoogleSignIn() {
    return CustomRaisedButton(
      child: Text("Sign in with Google"),
      onPressed: () async {
        AuthResponse response = await widget.manager.signInWithGoogle();
        if (response.status == Status.Failed) {
          showSnack(response);
        }
        widget.manager.printAuthStats();
      },
    );
  }

  Widget buildPhoneInput() {
    return Padding(
      padding: const EdgeInsets.all(40.0),
      child: TextFormField(
        controller: _phoneNumberController,
        decoration:
        const InputDecoration(labelText: 'Phone number (+xx xxx-xxx-xxxx)'),
      ),
    );
  }

  Widget buildVerifyCodeButton() {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: CustomRaisedButton(
        child: Text("Verify Code"),
        onPressed: () async {
          Provider.of<AuthManager>(context, listen: false).phoneCode =
              _smsController.text;
          if (!kIsWeb) {
            AuthResponse response =
            await Provider.of<AuthManager>(context, listen: false)
                .verifyPhoneSign(context, _smsController.text);

            if (response.status != Status.Successed) {
              showSnack(response);
            }
          } else {
            AuthResponse response =
            await Provider.of<AuthManager>(context, listen: false)
                .verifyPhoneSignForWeb(_smsController.text);
            if (response.status != Status.Successed) {
              showSnack(response);
            }
          }
        },
      ),
    );
  }

  Widget buildsignInWithPhoneNumber() {
    return CustomRaisedButton(
      child: Text("Sign in With Phone Number"),
      onPressed: () async {
        AuthResponse response = await widget.manager
            .signInWithPhone(_phoneNumberController.text, context);
        if (response.status != Status.Successed) {
          showSnack(response);
        }
        widget.manager.printAuthStats();
      },
    );
  }

  Widget buildResetMailSection() {
    return Container(
      width: 300,
      height: 200,
      child: Column(
        children: [
          TextField(
            controller: resetFieldController,
            decoration: InputDecoration(hintText: "Reset Mail"),
          ),
          FlatButton(
            onPressed: () async {
              AuthResponse? response =
              await Provider.of<AuthManager>(context, listen: false)
                  .sendPasswordResetEmail(resetFieldController.text);
              if (response!.status != Status.Successed) {
                ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                  content: Text(":" + response.message!),
                ));
              } else {
                showSnack(response);
              }
            },
            child: Text("Send Reset Mail"),
          ),
        ],
      ),
    );
  }

  Widget buildLinkMailAuth() {
    return CustomRaisedButton(
        onPressed: () async {
          AuthResponse response = await widget.manager
              .linkCredentialWithEmailPass(
              mailFieldController.text, passFieldController.text);
          widget.manager.printAuthStats();
          if (response.status == Status.Failed) {
            showSnack(response);
          }
        },
        child: Text("LinkWithEmailPass"));
  }

  Widget buildLinkPhoneAuth() {
    return CustomRaisedButton(
      child: Text("Link With Phone"),
      onPressed: () async {
        AuthResponse response = await widget.manager
            .linkCredentialWithPhone(_phoneNumberController.text, context);
        widget.manager.printAuthStats();

        showSnack(response);
      },
    );
  }

  Widget buildVerifyLinkPhoneAuth() {
    return CustomRaisedButton(
      child: Text("Verify Link Phone "),
      onPressed: () async {
        AuthResponse response = await widget.manager
            .verifyLinkCredentialWithPhone(_smsController.text);
        widget.manager.printAuthStats();

        showSnack(response);
      },
    );
  }

  Widget buildLinkGoogleAuth() {
    return CustomRaisedButton(
        onPressed: () async {
          AuthResponse response =
          await widget.manager.linkCredentialWithGoogle();
          widget.manager.printAuthStats();
          if (response.status == Status.Failed) {
            showSnack(response);
          }
        },
        child: Text("Link Google Account"));
  }

  Widget buildDeleteButton() {
    return CustomRaisedButton(
        onPressed: () async {
          AuthResponse response = await widget.manager.deleteUser();
          widget.manager.printAuthStats();
          if (response.status == Status.Failed) {
            showSnack(response);
          }
        },
        child: Text("Delete Account"));
  }

  Widget buildVerificationMailButton() {
    return CustomRaisedButton(
        onPressed: () async {
          AuthResponse response = await widget.manager.sendEmailVerification();
          widget.manager.printAuthStats();
          if (response.status == Status.Failed) {
            showSnack(response);
          }
        },
        child: Text("Send Verification Email"));
  }

  Widget buildReloadButton() {
    return CustomRaisedButton(
        onPressed: () async {
          AuthResponse response = await widget.manager.reloadUser();
          widget.manager.printAuthStats();
          if (response.status == Status.Failed) {
            showSnack(response);
          }
        },
        child: Text("Reload"));
  }

  Widget buildReSignButton() {
    return CustomRaisedButton(
        onPressed: () async {
          AuthResponse response = await widget.manager.reSignWithCredential();
          widget.manager.printAuthStats();
          if (response.status == Status.Failed) {
            showSnack(response);
          }
        },
        child: Text("ReSign"));
  }
}

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

1 回复

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


当然,fire_autho 并不是一个广泛认可的 Flutter 插件名称,不过从名字上看,它可能是与 Firebase Authentication 相关的自定义封装或第三方库。然而,在 Flutter 社区中,更常用的是 Firebase 官方提供的 firebase_auth 插件来进行身份验证。

以下是一个使用 firebase_auth 插件进行身份验证的基本示例,包括注册(创建用户)和登录(身份验证)功能。如果你确实在使用 fire_autho,并且它的 API 与 firebase_auth 类似,这个示例也可以作为一个参考。

首先,确保在 pubspec.yaml 文件中添加 firebase_auth 依赖:

dependencies:
  flutter:
    sdk: flutter
  firebase_auth: ^4.0.0  # 请检查最新版本号

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

接下来,在 Flutter 应用中设置 Firebase。这通常涉及到在 Firebase 控制台中为你的应用创建一个项目,并下载 google-services.json(Android)和 GoogleService-Info.plist(iOS)文件,将它们分别放置在 android/app/ios/Runner/ 目录下。

下面是一个简单的 Flutter 应用示例,展示了如何使用 firebase_auth 进行用户注册和登录:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Auth Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AuthScreen(),
    );
  }
}

class AuthScreen extends StatefulWidget {
  @override
  _AuthScreenState createState() => _AuthScreenState();
}

class _AuthScreenState extends State<AuthScreen> {
  final FirebaseAuth _auth = FirebaseAuth.instance;
  String _email = '';
  String _password = '';
  String _message = '';

  void _registerUser() async {
    try {
      UserCredential result = await _auth.createUserWithEmailAndPassword(
        email: _email,
        password: _password,
      );
      User user = result.user;
      // 在这里可以保存用户信息到数据库或执行其他操作
      setState(() {
        _message = '注册成功!';
      });
    } catch (e) {
      setState(() {
        _message = e.message;
      });
    }
  }

  void _loginUser() async {
    try {
      UserCredential result = await _auth.signInWithEmailAndPassword(
        email: _email,
        password: _password,
      );
      User user = result.user;
      // 在这里可以加载用户信息或执行其他操作
      setState(() {
        _message = '登录成功!';
      });
    } catch (e) {
      setState(() {
        _message = e.message;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('身份验证示例'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: <Widget>[
            TextField(
              decoration: InputDecoration(labelText: 'Email'),
              onChanged: (value) {
                setState(() {
                  _email = value;
                });
              },
            ),
            TextField(
              decoration: InputDecoration(labelText: 'Password'),
              obscureText: true,
              onChanged: (value) {
                setState(() {
                  _password = value;
                });
              },
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _registerUser,
              child: Text('注册'),
            ),
            SizedBox(height: 10),
            ElevatedButton(
              onPressed: _loginUser,
              child: Text('登录'),
            ),
            SizedBox(height: 20),
            Text(
              _message,
              style: TextStyle(color: Colors.red),
            ),
          ],
        ),
      ),
    );
  }
}

这个示例展示了如何创建一个简单的用户界面,允许用户使用电子邮件和密码进行注册和登录。请确保在实际应用中处理密码存储和传输时的安全性,以及根据需求添加更多的错误处理和用户体验改进。

如果你确实在使用 fire_autho 插件,并且它的 API 与 firebase_auth 不同,请参考该插件的官方文档或源代码以获取正确的使用方法。

回到顶部