Flutter身份验证插件fire_autho的使用
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
更多关于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
不同,请参考该插件的官方文档或源代码以获取正确的使用方法。