Flutter身份验证插件firebase_ui_auth的使用
Flutter身份验证插件firebase_ui_auth的使用
Firebase UI Auth简介
Firebase UI Auth
是一组Flutter小部件和实用工具,旨在帮助您构建和集成用户界面与Firebase Authentication。它简化了实现多种身份验证方式的过程,包括电子邮件、电话号码、OAuth提供商(如Google、Apple、Facebook和Twitter)等。
请参与讨论并提供反馈:discussion
平台支持
Feature/platform | Android | iOS | Web | macOS | Windows | Linux |
---|---|---|---|---|---|---|
✓ | ✓ | ✓ | ✓ | ✓ (1) | ✓ (1) | |
Phone | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |
Email link | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ |
Email verification | ✓ | ✓ | ✓ (2) | ✓ (2) | ✓ (1) | ✓ (1) |
Sign in with Apple | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ |
Google Sign in | ✓ | ✓ | ✓ | ✓ | ✓ (1) | ✓ (1) |
Twitter Login | ✓ | ✓ | ✓ | ✓ | ✓ (1) | ✓ (1) |
Facebook Sign in | ✓ | ✓ | ✓ | ✓ | ✓ (1) | ✓ (1) |
注:
- 使用 flutterfire_desktop
- 无应用内深度链接,因此电子邮件验证链接将打开网页
安装
flutter pub add firebase_ui_auth
示例代码
以下是一个简单的示例,展示了如何在应用程序中构建 SignInScreen
和 ProfileScreen
:
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
final providers = [EmailAuthProvider()];
void onSignedIn() {
Navigator.pushReplacementNamed(context, '/profile');
}
return MaterialApp(
initialRoute: FirebaseAuth.instance.currentUser == null ? '/sign-in' : '/profile',
routes: {
'/sign-in': (context) {
return SignInScreen(
providers: providers,
actions: [
AuthStateChangeAction<UserCreated>((context, state) {
// 新用户逻辑可以放在这里
onSignedIn();
}),
AuthStateChangeAction<SignedIn>((context, state) {
onSignedIn();
}),
],
);
},
'/profile': (context) {
return ProfileScreen(
providers: providers,
actions: [
SignedOutAction((context) {
Navigator.pushReplacementNamed(context, '/sign-in');
}),
],
);
},
},
);
}
}
Profile Screen Icons
如果您使用 ProfileScreen
,请确保在 pubspec.yaml
中添加以下内容:
fonts:
- family: SocialIcons
fonts:
- asset: packages/firebase_ui_auth/fonts/SocialIcons.ttf
文档
更多文档请参阅:官方文档
问题与反馈
- 如果遇到问题,请在仓库中创建新的 issue。
- 对于功能请求和问题,请使用 discussion。
- 要为插件贡献更改,请查看我们的 contribution guide 并提交 pull request。
完整示例Demo
下面是一个更完整的示例,涵盖了多个身份验证提供者,并包含了国际化支持和自定义样式:
import 'package:firebase_auth/firebase_auth.dart'
hide PhoneAuthProvider, EmailAuthProvider;
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_localizations/firebase_ui_localizations.dart';
import 'package:firebase_ui_oauth_apple/firebase_ui_oauth_apple.dart';
import 'package:firebase_ui_oauth_facebook/firebase_ui_oauth_facebook.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart';
import 'package:firebase_ui_oauth_twitter/firebase_ui_oauth_twitter.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
// Firebase配置
final actionCodeSettings = ActionCodeSettings(
url: 'https://flutterfire-e2e-tests.firebaseapp.com',
handleCodeInApp: true,
androidMinimumVersion: '1',
androidPackageName: 'io.flutter.plugins.firebase_ui.firebase_ui_example',
iOSBundleId: 'io.flutter.plugins.fireabaseUiExample',
);
final emailLinkProviderConfig = EmailLinkAuthProvider(
actionCodeSettings: actionCodeSettings,
);
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
FirebaseUIAuth.configureProviders([
EmailAuthProvider(),
emailLinkProviderConfig,
PhoneAuthProvider(),
GoogleProvider(clientId: GOOGLE_CLIENT_ID),
AppleProvider(),
FacebookProvider(clientId: FACEBOOK_CLIENT_ID),
TwitterProvider(
apiKey: TWITTER_API_KEY,
apiSecretKey: TWITTER_API_SECRET_KEY,
redirectUri: TWITTER_REDIRECT_URI,
),
]);
runApp(const FirebaseAuthUIExample());
}
class LabelOverrides extends DefaultLocalizations {
const LabelOverrides();
@override
String get emailInputLabel => 'Enter your email';
}
class FirebaseAuthUIExample extends StatelessWidget {
const FirebaseAuthUIExample({super.key});
String get initialRoute {
final user = FirebaseAuth.instance.currentUser;
return switch (user) {
null => '/',
User(emailVerified: false, email: final String _) => '/verify-email',
_ => '/profile',
};
}
@override
Widget build(BuildContext context) {
final buttonStyle = ButtonStyle(
padding: WidgetStateProperty.all(const EdgeInsets.all(12)),
shape: WidgetStateProperty.all(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
);
final mfaAction = AuthStateChangeAction<MFARequired>(
(context, state) async {
final nav = Navigator.of(context);
await startMFAVerification(
resolver: state.resolver,
context: context,
);
nav.pushReplacementNamed('/profile');
},
);
return MaterialApp(
theme: ThemeData(
brightness: Brightness.light,
visualDensity: VisualDensity.standard,
useMaterial3: true,
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
),
elevatedButtonTheme: ElevatedButtonThemeData(style: buttonStyle),
textButtonTheme: TextButtonThemeData(style: buttonStyle),
outlinedButtonTheme: OutlinedButtonThemeData(style: buttonStyle),
),
initialRoute: initialRoute,
routes: {
'/': (context) {
return SignInScreen(
actions: [
ForgotPasswordAction((context, email) {
Navigator.pushNamed(
context,
'/forgot-password',
arguments: {'email': email},
);
}),
VerifyPhoneAction((context, _) {
Navigator.pushNamed(context, '/phone');
}),
AuthStateChangeAction((context, state) {
final user = switch (state) {
SignedIn(user: final user) => user,
CredentialLinked(user: final user) => user,
UserCreated(credential: final cred) => cred.user,
_ => null,
};
switch (user) {
case User(emailVerified: true):
Navigator.pushReplacementNamed(context, '/profile');
case User(emailVerified: false, email: final String _):
Navigator.pushNamed(context, '/verify-email');
}
}),
mfaAction,
EmailLinkSignInAction((context) {
Navigator.pushReplacementNamed(context, '/email-link-sign-in');
}),
],
styles: const {
EmailFormStyle(signInButtonVariant: ButtonVariant.filled),
},
headerBuilder: headerImage('assets/images/flutterfire_logo.png'),
sideBuilder: sideImage('assets/images/flutterfire_logo.png'),
subtitleBuilder: (context, action) {
final actionText = switch (action) {
AuthAction.signIn => 'Please sign in to continue.',
AuthAction.signUp => 'Please create an account to continue',
_ => throw Exception('Invalid action: $action'),
};
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text('Welcome to Firebase UI! $actionText.'),
);
},
footerBuilder: (context, action) {
final actionText = switch (action) {
AuthAction.signIn => 'signing in',
AuthAction.signUp => 'registering',
_ => throw Exception('Invalid action: $action'),
};
return Center(
child: Padding(
padding: const EdgeInsets.only(top: 16),
child: Text(
'By $actionText, you agree to our terms and conditions.',
style: const TextStyle(color: Colors.grey),
),
),
);
},
);
},
'/verify-email': (context) {
return EmailVerificationScreen(
headerBuilder: headerIcon(Icons.verified),
sideBuilder: sideIcon(Icons.verified),
actionCodeSettings: actionCodeSettings,
actions: [
EmailVerifiedAction(() {
Navigator.pushReplacementNamed(context, '/profile');
}),
AuthCancelledAction((context) {
FirebaseUIAuth.signOut(context: context);
Navigator.pushReplacementNamed(context, '/');
}),
],
);
},
'/phone': (context) {
return PhoneInputScreen(
actions: [
SMSCodeRequestedAction((context, action, flowKey, phone) {
Navigator.of(context).pushReplacementNamed(
'/sms',
arguments: {
'action': action,
'flowKey': flowKey,
'phone': phone,
},
);
}),
],
headerBuilder: headerIcon(Icons.phone),
sideBuilder: sideIcon(Icons.phone),
);
},
'/sms': (context) {
final arguments = ModalRoute.of(context)?.settings.arguments
as Map<String, dynamic>?;
return SMSCodeInputScreen(
actions: [
AuthStateChangeAction<SignedIn>((context, state) {
Navigator.of(context).pushReplacementNamed('/profile');
})
],
flowKey: arguments?['flowKey'],
action: arguments?['action'],
headerBuilder: headerIcon(Icons.sms_outlined),
sideBuilder: sideIcon(Icons.sms_outlined),
);
},
'/forgot-password': (context) {
final arguments = ModalRoute.of(context)?.settings.arguments
as Map<String, dynamic>?;
return ForgotPasswordScreen(
email: arguments?['email'],
headerMaxExtent: 200,
headerBuilder: headerIcon(Icons.lock),
sideBuilder: sideIcon(Icons.lock),
);
},
'/email-link-sign-in': (context) {
return EmailLinkSignInScreen(
actions: [
AuthStateChangeAction<SignedIn>((context, state) {
Navigator.pushReplacementNamed(context, '/');
}),
],
provider: emailLinkProviderConfig,
headerMaxExtent: 200,
headerBuilder: headerIcon(Icons.link),
sideBuilder: sideIcon(Icons.link),
);
},
'/profile': (context) {
final platform = Theme.of(context).platform;
return ProfileScreen(
actions: [
SignedOutAction((context) {
Navigator.pushReplacementNamed(context, '/');
}),
mfaAction,
],
actionCodeSettings: actionCodeSettings,
showMFATile: kIsWeb ||
platform == TargetPlatform.iOS ||
platform == TargetPlatform.android,
showUnlinkConfirmationDialog: true,
showDeleteConfirmationDialog: true,
);
},
},
title: 'Firebase UI demo',
debugShowCheckedModeBanner: false,
supportedLocales: const [Locale('en')],
localizationsDelegates: [
FirebaseUILocalizations.withDefaultOverrides(const LabelOverrides()),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
FirebaseUILocalizations.delegate,
],
);
}
}
这个完整示例涵盖了从登录到配置多因素认证(MFA)、电子邮件验证等多个场景,并且还包括了国际化支持和自定义样式。希望这对您有所帮助!
更多关于Flutter身份验证插件firebase_ui_auth的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter身份验证插件firebase_ui_auth的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用firebase_ui_auth
插件进行身份验证的示例代码。firebase_ui_auth
插件简化了Firebase身份验证流程,支持电子邮件/密码、Google、Facebook等多种身份提供者。
首先,确保你已经在Flutter项目中添加了firebase_ui_auth
和相关的Firebase依赖。
- 在
pubspec.yaml
文件中添加依赖:
dependencies:
flutter:
sdk: flutter
firebase_core: ^1.10.0 # 确保使用最新版本
firebase_auth: ^3.3.3 # 确保使用最新版本
firebase_ui_auth: ^0.2.0 # 确保使用最新版本,注意:此版本号和API可能会随时间变化
- 在
android/app/build.gradle
文件中添加Firebase SDK配置:
dependencies {
// 添加Firebase身份验证库
implementation 'com.google.firebase:firebase-auth:21.0.3' // 确保使用最新版本
// 根据需要添加其他Firebase服务库
}
// 在文件底部添加apply plugin
apply plugin: 'com.google.gms.google-services'
- 在
ios/Runner/Podfile
中确保包含Firebase SDK(如果你也支持iOS):
platform :ios, '10.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug': :debug,
'Profile': :release,
'Release': :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try running flutter pub get in your app directory."
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
# 添加Firebase依赖
pod 'Firebase/Auth'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
- 初始化Firebase并配置
firebase_ui_auth
:
在你的Flutter项目的main.dart
文件中:
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化Firebase
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Firebase UI 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;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Firebase UI Auth Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
// 使用firebase_ui_auth进行身份验证
await signIn(context: context);
},
child: Text('Sign In'),
),
),
);
}
Future<void> signIn({required BuildContext context}) async {
try {
// 配置firebase_ui_auth的登录选项
final List<ProviderConfiguration> providers = [
EmailProviderConfiguration(),
GoogleProviderConfiguration(
clientId: 'YOUR_GOOGLE_CLIENT_ID', // 替换为你的Google客户端ID
),
// 可以根据需要添加其他身份提供者配置,如Facebook等
];
// 启动Firebase UI Auth流程
final UserCredential result = await FirebaseAuthUI.signIn(
context: context,
providers: providers,
);
// 用户登录成功后的处理
final User? user = result.user;
if (user != null) {
// 用户信息
print('User signed in: ${user.displayName} (${user.email})');
}
} catch (e) {
// 错误处理
print('Error signing in: $e');
}
}
}
注意:
- 确保你已经在Firebase控制台中设置了你的项目,并启用了所需的身份验证提供者(如电子邮件/密码、Google登录等)。
- 替换
YOUR_GOOGLE_CLIENT_ID
为你的Google客户端ID。 - 根据需要添加其他身份提供者配置,如Facebook、Twitter等。
这段代码展示了如何使用firebase_ui_auth
插件在Flutter应用中实现用户身份验证。它初始化Firebase,配置身份验证提供者,并启动身份验证流程。