在 Android 中透過電子郵件連結向 Firebase 驗證

您可以使用 Firebase 驗證功能,向使用者傳送電子郵件 內含連結,只要按一下即可登入。在過程中,使用者的 電子郵件地址也會通過驗證

使用電子郵件登入有以下優點:

  • 簡化註冊和登入程序。
  • 降低在不同應用程式間重複使用密碼的風險,可能導致安全性降低 甚至是已選取的密碼
  • 能夠驗證使用者身分,同時驗證使用者身分 電子郵件地址的合法擁有者。
  • 使用者只需具備可存取的電子郵件帳戶即可登入。不具備 必須提供電話號碼或社群媒體帳戶。
  • 使用者不需提供 (或記得) 存取 密碼,對行動裝置來說可能很麻煩。
  • 先前以電子郵件 ID (密碼) 登入的現有使用者 或聯合) 的電子郵件,只要以電子郵件登入即可。舉例來說 使用者就算忘記密碼,仍然可以登入, 重設密碼。

事前準備

設定 Android 專案

  1. 如果還沒試過 將 Firebase 新增至您的 Android 專案

  2. 模組 (應用程式層級) Gradle 檔案中 (通常為 <project>/<app-module>/build.gradle.kts<project>/<app-module>/build.gradle)、 新增 Android 版 Firebase 驗證程式庫的依附元件。建議您使用 Firebase Android BoM 管理程式庫版本管理

    此外,設定 Firebase 驗證時,您需要將 導入 Google Play 服務 SDK

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.1.2"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.2.0")
    }

    使用 Firebase Android BoM 應用程式一律會使用相容的 Firebase Android 程式庫版本。

    (替代做法) 新增 Firebase 程式庫依附元件,「不使用」BoM

    如果選擇不使用 Firebase BoM,則須指定各個 Firebase 程式庫版本 都屬於依附元件行

    請注意,如果您在應用程式中使用多個 Firebase 程式庫,強烈建議您 建議使用 BoM 管理程式庫版本 相容。

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth:23.0.0")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.2.0")
    }
    在尋找 Kotlin 專用的程式庫模組嗎?距離開始還有 2023 年 10 月 (Firebase BoM 32.5.0),Kotlin 和 Java 開發人員都能 依附於主要程式庫模組 (詳情請參閱 這項計畫的常見問題)。

如要透過電子郵件連結登入使用者,您必須先啟用電子郵件服務供應商,並 以電子郵件登入 Firebase 專案:

  1. Firebase 控制台開啟「驗證」專區。
  2. 在「Sign in method」分頁中啟用「Email/Password」供應商。注意事項 必須啟用電子郵件/密碼登入功能才能使用電子郵件連結登入。
  3. 在同一部分中啟用「電子郵件連結 (無密碼登入)」登入功能 方法。
  4. 按一下 [儲存]

如要啟動驗證流程,請向使用者顯示 提示使用者提供電子郵件地址,然後撥打電話 sendSignInLinkToEmail:要求 Firebase 傳送驗證連結 使用者的電子郵件。

  1. 建構 ActionCodeSettings 物件,向 Firebase 提供建構 電子郵件連結。設定下列欄位:

    • url:要嵌入的深層連結,以及要一併傳遞的任何其他狀態。 請在 Firebase 控制台的 只要前往 [登入方式] 分頁即可找到 (「驗證」->「登入方式」)。該連結會將使用者重新導向至 使用者的裝置未安裝應用程式,也未安裝應用程式 其他生態系統
    • androidPackageNameIOSBundleId:登入時使用的應用程式 連結是由 Android 或 Apple 裝置開啟。進一步瞭解如何 設定 Firebase Dynamic Links ,透過行動應用程式開啟電子郵件動作連結。
    • handleCodeInApp:設為 true。每次登入作業都必須 在 app 中完成與其他頻帶電子郵件動作的方式不同 (密碼) 重設和電子郵件驗證)。因為在流程結束時 使用者應可登入,且驗證狀態會保留在 應用程式
    • dynamicLinkDomain:定義多個自訂動態連結網域時 請指定要在透過連結開啟連結時使用的 指定行動應用程式 (例如 example.page.link)。否則, 系統會自動選取第一個網域。

    Kotlin+KTX

    val actionCodeSettings = actionCodeSettings {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url = "https://www.example.com/finishSignUp?cartId=1234"
        // This must be true
        handleCodeInApp = true
        setIOSBundleId("com.example.ios")
        setAndroidPackageName(
            "com.example.android",
            true, // installIfNotAvailable
            "12", // minimumVersion
        )
    }

    Java

    ActionCodeSettings actionCodeSettings =
            ActionCodeSettings.newBuilder()
                    // URL you want to redirect back to. The domain (www.example.com) for this
                    // URL must be whitelisted in the Firebase Console.
                    .setUrl("https://www.example.com/finishSignUp?cartId=1234")
                    // This must be true
                    .setHandleCodeInApp(true)
                    .setIOSBundleId("com.example.ios")
                    .setAndroidPackageName(
                            "com.example.android",
                            true, /* installIfNotAvailable */
                            "12"    /* minimumVersion */)
                    .build();

    如要進一步瞭解 ActionCodeSettings,請參閱 電子郵件動作中的通過狀態 專區。

  2. 要求使用者提供電子郵件地址。

  3. 傳送驗證連結至使用者的電子郵件,並儲存使用者的電子郵件 在使用者在同一部裝置上完成電子郵件地址登入程序。

    Kotlin+KTX

    Firebase.auth.sendSignInLinkToEmail(email, actionCodeSettings)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Email sent.")
            }
        }

    Java

    FirebaseAuth auth = FirebaseAuth.getInstance();
    auth.sendSignInLinkToEmail(email, actionCodeSettings)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Email sent.");
                    }
                }
            });

安全疑慮

防止他人透過非預期使用者身分登入 非預期裝置;Firebase 驗證會要求使用者的電子郵件地址 所提供的密碼。為確保登入成功,這封電子郵件 位址必須與最初登入連結的收件地址相符。

當使用者以相同方式開啟登入連結時, 使用者要求連結的裝置,方法是將電子郵件地址儲存在本機, 執行個體。接著: 使用此位址完成流程 請勿在重新導向網址參數中傳遞使用者的電子郵件,然後重新使用 這可能會啟用工作階段插入功能

登入完成後,系統會採用先前的任何未經驗證登入機制 ,且所有現有工作階段都會失效。 舉例來說,假設有人 電子郵件地址,系統會移除使用者密碼,以免 以模擬人的身分,提出擁有權並建立了未經驗證的帳戶 使用未經驗證的電子郵件地址和密碼重新登入。

此外,請務必在正式環境中使用 HTTPS 網址,避免使用者看到你的連結 也可能會遭到中介伺服器攔截

在 Android 應用程式中完成登入程序

Firebase 驗證會使用 Firebase Dynamic Links 將電子郵件連結傳送至 使用行動裝置如要透過行動應用程式完成登入程序,應用程式 您必須設定成偵測傳入的應用程式連結,剖析 ,然後完成登入。

Firebase 驗證會使用 Firebase Dynamic Links 傳送 要用在行動應用程式中開啟的連結為了使用這份 功能,您必須在 Firebase 控制台設定 Dynamic Links。

  1. 啟用 Firebase Dynamic Links:

    1. Firebase 控制台開啟「Dynamic Links」部分。
    2. 如果您尚未接受 Dynamic Links 條款並建立 Dynamic Links 網域,請立即採取相關行動。

      若您已建立 Dynamic Links 網域,請記下該網域。動態連結 網域通常如下所示:

      example.page.link

      將 Apple 或 Android 應用程式設為 攔截傳入連結。

  2. 設定 Android 應用程式:

    1. 為了從 Android 應用程式處理這些連結, 您必須在 Firebase 控制台中指定 Android 套件名稱 專案設定。此外,應用程式的 SHA-1 和 SHA-256 所需憑證
    2. 加入動態連結網域後 Android 應用程式設定正確無誤,動態連結會重新導向至 。
    3. 如要讓動態連結重新導向至特定活動, 您必須在 AndroidManifest.xml 中設定意圖篩選器 檔案。指定動態連結網域 傳送意圖篩選器的電子郵件動作處理常式。根據預設 動作處理常式是由如下列範例所示的網域代管:
      PROJECT_ID.firebaseapp.com/
    4. 注意事項:
      1. 請勿指定您在應用程式的 actionCodeSettings 設定的網址 意圖篩選器
      2. 建立動態連結網域時,您可能也建立了 短網址連結系統不會傳送這個簡短網址;不要 請設定意圖篩選器,以擷取 android:pathPrefix 屬性。也就是說 無法在 應用程式不過,您可以檢查 mode 查詢參數 查看嘗試執行的作業,或 使用 isSignInWithEmailLink 等 SDK 方法 應用程式收到的連結能滿足您的需求
    5. 如要進一步瞭解如何接收動態連結,請參閱 取得 Android Dynamic Links 操作說明

收到上述連結後,請確認該連結是用於電子郵件 連結驗證,並完成登入。

Kotlin+KTX

val auth = Firebase.auth
val intent = intent
val emailLink = intent.data.toString()

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    val email = "someemail@domain.com"

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Successfully signed in with email link!")
                val result = task.result
                // You can access the new user via result.getUser()
                // Additional user info profile *not* available via:
                // result.getAdditionalUserInfo().getProfile() == null
                // You can check if the user is new or existing:
                // result.getAdditionalUserInfo().isNewUser()
            } else {
                Log.e(TAG, "Error signing in with email link", task.exception)
            }
        }
}

Java

FirebaseAuth auth = FirebaseAuth.getInstance();
Intent intent = getIntent();
String emailLink = intent.getData().toString();

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    String email = "someemail@domain.com";

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
            .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Successfully signed in with email link!");
                        AuthResult result = task.getResult();
                        // You can access the new user via result.getUser()
                        // Additional user info profile *not* available via:
                        // result.getAdditionalUserInfo().getProfile() == null
                        // You can check if the user is new or existing:
                        // result.getAdditionalUserInfo().isNewUser()
                    } else {
                        Log.e(TAG, "Error signing in with email link", task.getException());
                    }
                }
            });
}

進一步瞭解如何在 Apple 中運用電子郵件連結登入 請參閱 Apple 平台指南

瞭解如何處理網頁中的電子郵件連結登入作業 請參閱網頁指南

您也可以將這種驗證方法連結至現有的使用者。例如: 使用者先前已透過其他供應商 (如電話號碼) 完成驗證。 可以在現有帳戶中新增這種登入方式。

差異如下:作業的後半部:

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Link the credential to the current user.
Firebase.auth.currentUser!!.linkWithCredential(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Log.d(TAG, "Successfully linked emailLink credential!")
            val result = task.result
            // You can access the new user via result.getUser()
            // Additional user info profile *not* available via:
            // result.getAdditionalUserInfo().getProfile() == null
            // You can check if the user is new or existing:
            // result.getAdditionalUserInfo().isNewUser()
        } else {
            Log.e(TAG, "Error linking emailLink credential", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Link the credential to the current user.
auth.getCurrentUser().linkWithCredential(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    Log.d(TAG, "Successfully linked emailLink credential!");
                    AuthResult result = task.getResult();
                    // You can access the new user via result.getUser()
                    // Additional user info profile *not* available via:
                    // result.getAdditionalUserInfo().getProfile() == null
                    // You can check if the user is new or existing:
                    // result.getAdditionalUserInfo().isNewUser()
                } else {
                    Log.e(TAG, "Error linking emailLink credential", task.getException());
                }
            }
        });

在執行 機密作業

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Re-authenticate the user with this credential.
Firebase.auth.currentUser!!.reauthenticateAndRetrieveData(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            // User is now successfully reauthenticated
        } else {
            Log.e(TAG, "Error reauthenticating", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Re-authenticate the user with this credential.
auth.getCurrentUser().reauthenticateAndRetrieveData(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // User is now successfully reauthenticated
                } else {
                    Log.e(TAG, "Error reauthenticating", task.getException());
                }
            }
        });

不過,由於流程最終可能會發生在原始使用者的裝置上 未登入,可能無法完成這個流程。在此情況下,錯誤可能 才能強制使用者在相同裝置上開啟連結。只有部分通知 狀態,以提供作業類型相關資訊 和使用者 uid

如果您是在 2023 年 9 月 15 日當天或之後建立專案,請透過電子郵件列舉項目 系統會預設啟用保護措施。這項功能可以提高 專案的使用者帳戶,但將 fetchSignInMethodsForEmail() 停用 方法 (先前建議用來實作 ID 優先流程)。

雖然您可以為專案停用電子郵件列舉防護功能, 並建議不要這樣做

請參閱電子郵件列舉防護功能說明文件 ,掌握更多詳細資訊。

後續步驟

使用者首次登入後,系統會建立新的使用者帳戶 也就是使用者的名稱和密碼 號碼或驗證提供者資訊,也就是使用者登入時使用的網址。這項新功能 帳戶儲存為 Firebase 專案的一部分,可用來識別 使用者登入專案中的所有應用程式

  • 在您的應用程式中,您可以透過 FirebaseUser 物件。詳情請參閱 管理使用者。

  • 在您的 Firebase 即時資料庫和 Cloud Storage 中 查看安全性規則即可 透過 auth 變數取得已登入使用者的不重複使用者 ID。 控管使用者可以存取的資料

您可以讓使用者透過多重驗證機制登入您的應用程式 將驗證供應商憑證連結至 現有的使用者帳戶

如要登出使用者,請呼叫 signOut

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();