Flutter简化认证流程插件easy_auth的使用
Flutter简化认证流程插件easy_auth的使用
EasyAuth
Widgets和classes使得在任何Flutter应用中添加认证变得简单。它基于package:bloc架构构建,并且完全不依赖于任何特定的认证框架,但它为常用的框架如package:firebase_auth提供了一些即插即用的机制。
⚠️ 如果你喜欢这个仓库,请考虑帮助维护/改进/推广它!
使用方法 #
让我们看看如何将基本的Firebase Auth状态集成到你的应用中。其他例子可以查看examples文件夹。
首先,我们创建一个基本的MaterialApp(或者你可能使用的任何其他应用)并初始化默认的Firebase应用:
// -> main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
GestureBinding.instance!.resamplingEnabled = true;
await Firebase.initializeApp();
runApp(
MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const _MyApp(),
),
);
}
然后我们创建我们的<_MyApp>组件,该组件扩展了<AuthenticationBasedApp>:
// -> main.dart
class _MyApp extends AuthenticationBasedApp<UserData> {
const _MyApp({Key? key}) : super(key: key);
@override
BasicFirebaseAuth<UserData> get repository => BasicFirebaseAuth<UserData>(
transformer: (user) => UserData('1-1-1970', user.metadata.creationTime!, user.email));
@override
Widget buildState(BuildContext context, AuthStatus status, UserData? user) {
switch (status) {
case AuthStatus.uninitialized:
return const SplashScreenView();
case AuthStatus.authenticated:
return const HomeView();
case AuthStatus.newAccount:
return const HomeView.newAccount();
case AuthStatus.authenticating:
case AuthStatus.unauthenticated:
return const LoginView();
}
}
}
这样就完成了!现在你可以像使用<FirebaseAuth>一样使用<EasyAuth>进行登录、注销、创建账户等操作。
注意,我们在<AuthenticationBasedApp>中传递了<UserData>类作为泛型,让我们来讨论一下为什么。
EquatableUser #
这个类被用作用户的一个默认表示。它可以很容易地扩展以添加自己的参数。
由于它继承自Equatable,如果你想让某个属性成为==操作的一部分,你需要将其添加到props数组中。
// -> custom_user.dart
class CustomUser extends EquatableUser {
const CustomUser({required this.birthday}) : super(id: '1', email: 'first@user.com');
final String birthday;
@override
List<Object?> get props => [...super.props, birthday];
}
EasyAuth 方法 #
EasyAuth是一个工具类,允许你静态访问<AuthenticationRepository>上的方法。
ElevatedButton(
child: const Text('Log in'),
onPressed: () {
final provider = EmailPasswordAuth('test@easyauth.com', 'some-password');
EasyAuth.login(context, provider: provider);
},
)
AuthenticationRepository #
AuthenticationRepository是一个抽象类,定义了添加自定义认证提供程序所需的所有方法。
注意:在覆盖此类中的任何方法时,你不需要处理错误!
abstract class AuthenticationRepository<T extends EquatableUser> {
Future<void> login({required EasyAuthProvider provider});
Future<void> register({required T user, required String password});
Future<void> signOut();
Future<void> deleteAccount();
bool isUserNew(T user);
T get currentUser;
Stream<T> get user;
Future<AuthException?> performSafeAuth(Future<void> future, AuthAction action) async {...}
}
唯一不需要重新实现的方法是performSafeAuth(...)
。它用于处理执行认证操作时可能抛出的任何错误。
以下是BasicFirebaseAuth
的一个示例:
class BasicFirebaseAuth<T extends EquatableUser> extends AuthenticationRepository<T> {
final _firebaseAuth = FirebaseAuth.instance;
@override
Stream<T> get user => _firebaseAuth.authStateChanges().map<T>((user) {
if (user == null) {
return EquatableUser.empty;
} else {
return EquatableUser(
id: user.uid,
name: user.displayName,
email: user.email,
createdAt: user.metadata.creationTime,
);
}
});
@override
bool isUserNew(T user) => user.createdAt?.isAfter(DateTime.now().subtract(const Duration(seconds: 5))) ?? false;
@override
T get currentUser {
final _user = _firebaseAuth.currentUser!;
return EquatableUser(id: _user.uid, name: _user.displayName, email: _user.email);
}
@override
Future<void> login({required EasyAuthProvider provider}) async {
if (provider is EmailPasswordAuth) {
await _firebaseAuth.signInWithEmailAndPassword(email: provider.email, password: provider.password);
} else if (provider is GoogleAuth) {
//sign in with google
}
}
@override
Future<void> register({required T user, required String password}) async {
if (user.email == null) throw FirebaseAuthException(code: 'no-email-registration');
await _firebaseAuth.createUserWithEmailAndPassword(email: user.email!, password: password);
}
@override
Future<void> signOut() => _firebaseAuth.signOut();
@override
Future<void> deleteAccount() => _firebaseAuth.currentUser!.delete();
}
EasyAuthProvider #
如果你需要添加比预包装的更多认证提供程序,只需覆盖<EasyAuthProvider>类。
EasyAuth Widgets #
AuthenticationBasedApp
AuthenticationBasedApp是一个抽象类,你需要扩展它以向你的应用添加认证响应性。
有一些你需要了解的方法:
/// 每当认证状态发生变化时,都会重建应用程序的状态。
/// 这是一个高效的方法,因为`T`扩展了`Equatable`,因此只有在必要时才会重建。
Widget buildState(BuildContext context, AuthStatus status, T user);
注意:此方法需要重写。
/// 当与认证相关的异常被抛出时调用。
/// 可以覆盖以提供自己的自定义错误处理逻辑(例如日志记录、自定义Snackbar等)。
void handleError(BuildContext context, AuthException exception) {...}
注意:此方法有一个默认实现,会打印执行的动作,当异常被抛出时,并显示以下来自package:another_flushbar的Flushbar
。
Flushbar(
icon: const Padding(padding: EdgeInsets.only(left: 14.0), child: Text('😱')),
message: exception.message,
backgroundColor: Theme.of(context).errorColor,
margin: const EdgeInsets.all(8),
borderRadius: BorderRadius.circular(8.0),
flushbarPosition: FlushbarPosition.TOP,
flushbarStyle: FlushbarStyle.FLOATING,
);
EasyAuthBuilder
EasyAuthBuilder是一个Flutter小部件,需要一个builder
函数。EasyAuthBuilder
处理响应新的认证状态而构建小部件。EasyAuthBuilder
是package:bloc中的<BlocBuilder>的一个简单包装器。builder函数可能会被多次调用,应该是一个返回小部件的纯函数,响应状态。
EasyAuthBuilder(
builder: (context, status, user) {
// 在这里返回基于当前AuthStatus和User的小部件
}
)
更多关于Flutter简化认证流程插件easy_auth的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter简化认证流程插件easy_auth的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用Flutter插件easy_auth
来简化认证流程的示例代码。easy_auth
是一个假设的插件名称,用于说明目的,因为在实际Flutter生态系统中可能没有一个确切名为easy_auth
的插件提供完整的认证流程简化功能。然而,我们可以根据常见的认证流程(如OAuth、Email/Password等)给出一个示例。
在实际应用中,你可能会使用如firebase_auth
、google_sign_in
、flutter_facebook_login
等插件来实现不同的认证方式。下面的代码将展示如何结合这些插件来简化认证流程。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加所需的依赖:
dependencies:
flutter:
sdk: flutter
firebase_auth: ^3.3.5 # 请检查最新版本
google_sign_in: ^5.0.5 # 请检查最新版本
flutter_facebook_login: ^3.0.0 # 假设有一个Facebook登录插件,请检查最新版本
2. 配置Firebase和Google Sign-In
按照Firebase和Google Sign-In的官方文档配置你的项目。
3. 创建认证服务
创建一个新的Dart文件,比如auth_service.dart
,来封装认证逻辑:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:flutter_facebook_login/flutter_facebook_login.dart';
class AuthService {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FacebookLogin _facebookLogin = FacebookLogin();
// Google Sign In
Future<UserCredential?> signInWithGoogle() async {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) return null;
final GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
idToken: googleAuth.idToken,
accessToken: googleAuth.accessToken,
);
return await _firebaseAuth.signInWithCredential(credential);
}
// Facebook Login
Future<UserCredential?> signInWithFacebook() async {
final AccessToken? accessToken = await _facebookLogin.logIn();
if (accessToken == null) return null;
final AuthCredential credential = FacebookAuthProvider.credential(accessToken.token);
return await _firebaseAuth.signInWithCredential(credential);
}
// Email/Password Sign In
Future<UserCredential?> signInWithEmailAndPassword(String email, String password) async {
return await _firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
}
// Sign Out
Future<void> signOut() async {
await _firebaseAuth.signOut();
await _googleSignIn.signOut();
await _facebookLogin.logOut();
}
}
4. 使用认证服务
在你的主应用文件中(如main.dart
),使用上述认证服务:
import 'package:flutter/material.dart';
import 'auth_service.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final AuthService _authService = AuthService();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Auth Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => _authService.signInWithGoogle().then((credential) {
if (credential != null) {
// Handle successful sign-in
print('Google Sign-In Successful');
}
}),
child: Text('Sign In with Google'),
),
ElevatedButton(
onPressed: () => _authService.signInWithFacebook().then((credential) {
if (credential != null) {
// Handle successful sign-in
print('Facebook Sign-In Successful');
}
}),
child: Text('Sign In with Facebook'),
),
ElevatedButton(
onPressed: () {
// Show a dialog for Email/Password input and then call signInWithEmailAndPassword
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Sign In'),
content: SingleChildScrollView(
child: ListBody(
children: [
TextField(
decoration: InputDecoration(labelText: 'Email'),
onSubmitted: (email) {
TextEditingController passwordController = TextEditingController();
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Enter Password'),
content: TextField(
controller: passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Cancel'),
),
TextButton(
onPressed: () async {
String password = passwordController.text;
await _authService.signInWithEmailAndPassword(email, password).then((credential) {
if (credential != null) {
Navigator.of(context).pop();
Navigator.of(context).pop();
print('Email/Password Sign-In Successful');
}
});
},
child: Text('Sign In'),
),
],
);
},
);
},
),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Cancel'),
),
],
);
},
);
},
child: Text('Sign In with Email/Password'),
),
ElevatedButton(
onPressed: () => _authService.signOut(),
child: Text('Sign Out'),
),
],
),
),
),
);
}
}
注意事项
- 实际项目中的错误处理:在实际项目中,你需要添加更多的错误处理逻辑,比如处理网络错误、认证失败等。
- UI/UX优化:上述示例中的UI/UX非常基础,你可能需要根据你的应用需求进行优化。
- 安全性:确保你的应用遵循最佳的安全实践,特别是在处理用户凭证时。
这个示例展示了如何使用Flutter和相关的认证插件来简化认证流程。虽然示例中使用了firebase_auth
、google_sign_in
和假设的flutter_facebook_login
插件,但你可以根据实际需求替换为其他插件或添加更多的认证方式。