美文网首页Android
为 Flutter 实现 Facebook 身份验证

为 Flutter 实现 Facebook 身份验证

作者: BlueSocks | 来源:发表于2022-08-23 12:11 被阅读0次

    身份验证是一个安全过程,用户必须提供他们的身份才能访问特定的应用程序、系统或一段特定的信息或资源。在计算机安全方面,身份验证是验证用户身份的过程或动作。如果没有身份验证,计算机网络就容易受到攻击,黑客可能想要获得对机密信息或资源的访问权限。

    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 开发者帐户并开始创建我们的应用程序。

    单击登录按钮。这将提示您使用您的 Facebook 详细信息登录。

    输入您的登录详细信息,然后点击登录按钮继续。

    点击My Apps,我们就可以开始在 Facebook 上创建我们的应用了。

    在这里,我们没有创建应用程序。点击 Create App 按钮,这样我们就可以开始创建我们的应用程序了

    在这里,我们可以选择任何应用类型。我将为本教程选择业务并点击下一步。

    添加您选择的显示名称,然后点击创建应用程序以继续。系统可能会提示您输入密码,输入密码,然后单击提交。

    在这里您可以看到我们的应用程序已经创建。我们在左上角有我们的应用程序名称和我们的应用程序 ID。单击Facebook Login以便我们可以在我们的应用程序上设置 Facebook 登录功能。

    我将在本教程的 android 平台上工作。单击 Android 徽标继续。

    在您的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.
    }
    

    如果您已成功完成,请单击下一步。

    在第 3 步中,输入Package Name和 ,Default Activity Class Name如上所示。您可以通过转到android>app>build.gradleFlutter 项目中的文件来获取包名称。

    点击保存以继续设置应用程序。

    在第 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文件夹。就我而言,我有这个:

    在这里,我将用户名更改为我的系统用户并添加了openssl\bin文件夹的路径。当提示输入密码时,使用android. 这将生成一个密钥供您复制并粘贴到您网页的“密钥哈希”部分。

    点击保存并继续。

    第五步,启用单点登录,点击保存并下一步。

    在第 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 是自托管的,可以完全控制您的数据。

    开始享受您的调试体验 -开始免费使用 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

    结论

    我们的应用程序需要身份验证。没有它,您会使数据容易受到破坏和未经授权的访问。

    这是GitHub 源代码的链接

    来源:https://blog.openreplay.com/implementing-facebook-authentication-for-flutter

    相关文章

      网友评论

        本文标题:为 Flutter 实现 Facebook 身份验证

        本文链接:https://www.haomeiwen.com/subject/ojzngrtx.html