为 Flutter 实现 Facebook 身份验证
身份验证是一个安全过程,用户必须提供他们的身份才能访问特定的应用程序、系统或一段特定的信息或资源。在计算机安全方面,身份验证是验证用户身份的过程或动作。如果没有身份验证,计算机网络就容易受到攻击,黑客可能想要获得对机密信息或资源的访问权限。
Flutter为我们提供了一个名为 的包flutter_facebook_auth
,我们可以在其中轻松地将 Facebook 登录添加到我们的 Flutter 应用程序中。它为我们提供了很多功能,包括:
- 在 IOS、Android 和 Web 上登录
- 在 Android 上快速登录
- 提供访问令牌以向 Graph API 发出请求等等。
如需完整文档,请访问此页面。
在本文中,我们将设置一个应用程序来展示如何在我们的 Flutter 应用程序中使用这个包。
创建我们的 Flutter 应用程序
要开始,请前往GitHub并克隆为此项目创建的启动文件。打开pubspec.yaml
文件并在终端flutter_facebook_auth
下添加cupertino_icons
或运行flutter pub add flutter_facebook_auth
。
name: facebook_auth
description: A new Flutter project.
publish_to: `none
version: 1.0.0+1
environment:
sdk: ">=2.17.6 <3.0.0"
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
flutter_facebook_auth: ^4.4.0+1 # Add This Line
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
flutter:
uses-material-design: true
向我们的应用程序添加依赖项
在向我们的应用程序添加功能之前,我们需要配置项目根文件以授予我们访问 Facebook 登录的权限。在您的浏览器上,前往Facebook 开发者创建一个 Facebook 开发者帐户并开始创建我们的应用程序。
![](https://img.haomeiwen.com/i27820348/f57c71654f7b7405.png)
单击登录按钮。这将提示您使用您的 Facebook 详细信息登录。
![](https://img.haomeiwen.com/i27820348/ac53ccf9f1b57440.png)
输入您的登录详细信息,然后点击登录按钮继续。
![](https://img.haomeiwen.com/i27820348/70ac8960f8c8b4f0.png)
点击My Apps,我们就可以开始在 Facebook 上创建我们的应用了。
![](https://img.haomeiwen.com/i27820348/ac6d6ad9988aacea.png)
在这里,我们没有创建应用程序。点击 Create App 按钮,这样我们就可以开始创建我们的应用程序了
![](https://img.haomeiwen.com/i27820348/b6c6f0276a846e7f.png)
在这里,我们可以选择任何应用类型。我将为本教程选择业务并点击下一步。
![](https://img.haomeiwen.com/i27820348/53e7e6b2bb8f4c04.png)
添加您选择的显示名称,然后点击创建应用程序以继续。系统可能会提示您输入密码,输入密码,然后单击提交。
![](https://img.haomeiwen.com/i27820348/951c266532b9e24f.png)
在这里您可以看到我们的应用程序已经创建。我们在左上角有我们的应用程序名称和我们的应用程序 ID。单击Facebook Login以便我们可以在我们的应用程序上设置 Facebook 登录功能。
![](https://img.haomeiwen.com/i27820348/7966433dde716145.png)
我将在本教程的 android 平台上工作。单击 Android 徽标继续。
![](https://img.haomeiwen.com/i27820348/b4defab3b424ee39.png)
在您的project-level > build.gradle文件中将代码添加到buildscript{repositories{ }}
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral() // Add Here
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral() // Add Here
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
在您的app-level>build.gradle
文件中,将代码添加到依赖项部分。
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.facebook_auth"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.facebook.android:facebook-android-sdk:latest.release' // Add This Line Here.
}
如果您已成功完成,请单击下一步。
![](https://img.haomeiwen.com/i27820348/65e8068b1ae7718c.png)
在第 3 步中,输入Package Name和 ,Default Activity Class Name如上所示。您可以通过转到android>app>build.gradleFlutter
项目中的文件来获取包名称。
点击保存以继续设置应用程序。
![](https://img.haomeiwen.com/i27820348/a3ed341cfc08e5ba.png)
在第 4 步中,我们需要生成一个开发密钥哈希,以确保我们的应用程序与 Facebook 之间交互的真实性。我在 Windows 机器上,所以我将单击openssl-for-windows并下载并解压缩特定于我的 PC(32 位或 64 位)的 zip 文件。复制下面的代码并将其粘贴到您的终端上。
keytool -exportcert -alias androiddebugkey -keystore "C:\Users\USERNAME\.android\debug.keystore" | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" sha1 -binary | "PATH_TO_OPENSSL_LIBRARY\bin\openssl" base64
将 USERNAME 更改为您自己的并将路径添加到openss\bin文件夹。就我而言,我有这个:
![](https://img.haomeiwen.com/i27820348/9a4072f546f074e5.png)
在这里,我将用户名更改为我的系统用户并添加了openssl\bin文件夹的路径。当提示输入密码时,使用android. 这将生成一个密钥供您复制并粘贴到您网页的“密钥哈希”部分。
![](https://img.haomeiwen.com/i27820348/53480366f3866e45.png)
点击保存并继续。
![](https://img.haomeiwen.com/i27820348/993db6a215da0ecc.png)
第五步,启用单点登录,点击保存并下一步。
![](https://img.haomeiwen.com/i27820348/0d93ab2a8aabb093.png)
在第 6 步中,我们将编辑资源和清单文件。在您的 上app>src>main>res>values,创建一个string.xml文件并添加以下代码:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">App Name</string>
<string name="facebook_app_id">App ID</string>
<string name="fb_login_protocol_scheme">Login Protocol Scheme</string>
<string name="facebook_client_token">Client Token</string>
</resources>
您facebook_app_id可以在浏览器的上方找到,并且您fb_login_protocol_scheme是带有前缀的应用程序 ID fb(例如,如果您的应用程序 ID 为1234,则您的协议方案将为fb1234)。要获取您的facebook_client_token,在您的仪表板上,导航到Settings>Advanced>Security>Client Token。就我而言:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Auth Tutorial</string>
<string name="facebook_app_id">1924520271082903</string>
<string name="fb_login_protocol_scheme">fb1924520271082903</string>
<string name="facebook_client_token">ab808c0a71a13009bcf8792433ff6b94</string>
</resources>
最后,转到您的AndroidManifest.xml文件并复制以下代码:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.facebook_auth">
<!-- FACEBOOK CONFIGURATIONS -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- FACEBOOK CONFIGURATIONS ENDS HERE -->
<application
android:label="facebook_auth"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!-- FACEBOOK CONFIGURATIONS -->
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
<!--FACEBOOK CONFIGURATION ENDS HERE -->
</application>
</manifest>
注意:我评论了您要复制和粘贴的行。您已完成与 Facebook 相关的所有任务。接下来,我们将开始向我们的应用程序添加功能。
开源会话重播
OpenReplay是一个开源的会话重播套件,可让您查看用户在您的 Web 应用程序上所做的事情,从而帮助您更快地解决问题。OpenReplay 是自托管的,可以完全控制您的数据。
![](https://img.haomeiwen.com/i27820348/186f4e1ad4b7f37a.png)
开始享受您的调试体验 -开始免费使用 OpenReplay。
添加功能
平台配置完成后,让我们设置我们的应用程序。在我们的 main.dart 文件中,我们将向按钮添加功能。在onPressed
参数上,添加以下代码。
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const UserScreen(),
),
);
UserScreen()上面的代码允许我们在单击按钮时移动到下一个屏幕( )。user_screen.dart在 lib 文件夹中创建一个名为的新 dart 文件。该文件将用于显示从 Facebook 获取的用户数据。
// user.dart
import 'package:flutter/material.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
class UserScreen extends StatefulWidget {
const UserScreen({Key? key}) : super(key: key);
@override
State<UserScreen> createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
Map<String, dynamic>? _userData;
AccessToken? _accessToken;
bool? _checking = true;
_ifUserIsLoggedIn() async {
final accessToken = await FacebookAuth.instance.accessToken;
setState(() {
_checking = false;
});
if (accessToken != null) {
final userData = await FacebookAuth.instance.getUserData();
_accessToken = accessToken;
setState(() {
_userData = userData;
});
} else {
_login();
}
}
_login() async {
final LoginResult loginResult = await FacebookAuth.instance.login();
if (loginResult.status == LoginStatus.success) {
_accessToken = loginResult.accessToken;
final userInfo = await FacebookAuth.instance.getUserData();
_userData = userInfo;
} else {
print('ResultStatus: ${loginResult.status}');
print('Message: ${loginResult.message}');
}
}
_logOut() async {
await FacebookAuth.instance.logOut();
_accessToken = null;
_userData = null;
}
@override
void initState() {
super.initState();
_ifUserIsLoggedIn();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _checking!
? const Center(
child: CircularProgressIndicator(),
)
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text('Welcome'),
_userData != null
? Text(
'${_userData!['name']}',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 28),
)
: Container(),
_userData != null
? Container(
child: Image.network(
_userData!\['picture'\]['data']['url']),
)
: Container(),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
_logOut();
Navigator.pop(context);
},
child: const Text('Log Out'),
),
],
),
));
}
}
让我们分解上面的代码。
Map<String, dynamic>? _userData;
AccessToken? _accessToken;
bool? _checking = true;
在上面的代码中,我们有三个可为空的变量:
- _userData: 登录时保存用户信息。
- _accessToken:登录时会自动生成访问令牌;此变量将为我们保存该访问令牌。
- _checking:这将检查用户之前是否登录过。
_ifUserIsLoggedIn() async {
final accessToken = await FacebookAuth.instance.accessToken;
setState(() {
_checking = false;
});
if (accessToken != null) {
final userData = await FacebookAuth.instance.getUserData();
_accessToken = accessToken;
setState(() {
_userData = userData;
});
} else {
_login();
}
}
_login() async {
final LoginResult loginResult = await FacebookAuth.instance.login();
if (loginResult.status == LoginStatus.success) {
_accessToken = loginResult.accessToken;
final userInfo = await FacebookAuth.instance.getUserData();
_userData = userInfo;
} else {
print('ResultStatus: ${loginResult.status}');
print('Message: ${loginResult.message}');
}
}
_logOut() async {
await FacebookAuth.instance.logOut();
_accessToken = null;
_userData = null;
}
查看上面的代码,我们有三个异步函数:
- _ifUserIsLoggedIn():这将检查用户是否已登录并获取访问令牌和用户数据。
- _login():登录函数让我们登录,如果登录状态为成功,它应该获取用户数据和生成的访问令牌。
- _logOut():这会将用户数据和访问令牌设置为 null,然后将我们带回第一页。
Scaffold(
body: _checking!
? const Center(
child: CircularProgressIndicator(),
)
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text('Welcome'),
_userData != null
? Text(
'${_userData!['name']}',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 28),
)
: Container(),
_userData != null
? Container(
child: Image.network(
_userData!\['picture'\]['data']['url']),
)
: Container(),
const SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
_logOut();
Navigator.pop(context);
},
child: const Text('Log Out'),
),
],
),
));
上面的代码在屏幕上显示了我们的值。我们使用三元运算符,它是 dart 中简化的 if 和 else 语句。它检查变量的值_checking是否为真,然后显示进度指示器;否则,显示用户数据。我们还有一个注销按钮,可以使用该_logOut功能并将我们带回主屏幕。
测试应用程序
完成所有配置和设置后,让我们测试我们的应用程序。使用终端中的命令在模拟器或实际设备上运行应用程序。该命令flutter run将构建应用程序并将其安装在您的设备上。
https://blog.openreplay.com/7105fbcdb9ac741da805612f9533d7d2/video.mp4
结论
我们的应用程序需要身份验证。没有它,您会使数据容易受到破坏和未经授权的访问。
来源:https://blog.openreplay.com/implementing-facebook-authentication-for-flutter