在 Android 應用中使用 Firebase 確保簡訊驗證安全性


摘要

在 Android 應用中使用 Firebase 確保簡訊驗證安全性,是現代開發者不可忽視的重要議題。這篇文章探討了如何利用 Firebase 的各項功能來提升應用程式的安全性。 歸納要點:

  • 隱藏 Firebase 驗證 API Key 防止未經授權存取,加強資料保護。
  • 使用動態連結與 reCAPTCHA 強化驗證流程,防範機器人和釣魚攻擊。
  • 伺服器端驗證避免惡意攔截簡訊驗證碼,確保敏感資料隱私。
透過這些方法,開發者能有效提升 Android 應用的簡訊驗證安全性,保障使用者資料的完整與隱私。


使用 Firebase 簡化 Android 使用者驗證:逐步指南

在本文中,我將逐步解釋如何在您的 Android 應用程式中使用 Firebase 的 SMS 驗證功能進行使用者驗證。SMS 驗證是一種有效的方法,用於驗證使用者的手機號碼並確保安全登入。在這個例子中,我們將建立一個專案並完成所有必要的步驟。

**登入 Firebase 控制檯:**
1. 前往 Firebase 控制檯。
2. 使用您的 Google 賬戶登入。
3. 在 Firebase 控制檯中點選「新增專案」按鈕。
4. 輸入您的專案名稱,然後點選「繼續」。
5. 您可能會被要求啟用 Google Analytics。根據您的偏好勾選選項,然後點選「繼續」。

一旦專案建立過程完成,點選「管理專案」按鈕以進入您的專案頁面。

**使用Firebase App Check強化安全性:**
Firebase App Check 可驗證請求是否來自您已註冊的應用程式,防止第三方存取和竊取使用者資料。確保您的應用程式安全性,保障使用者隱私。

啟用 App Check 選項並在此部分註冊您的應用程式。使用 Play Integrity API 啟動 Firebase App Check 將增強您應用程式的安全性並防止未經授權訪問 Firebase 服務。

**將應用新增到Firebase:**

整合完上述基礎設定後,即可按照以下步驟正式將您的 Android 應用與 Firebase 連線起來,以實現 SMS 驗證功能...
我們在研究許多文章後,彙整重點如下
網路文章觀點與我們總結
  • 建立Firebase專案並開通Authentication功能。
  • 透過Firebase Auth SDK進行電話號碼驗證。
  • 設置URL Scheme以便Firebase與APNs溝通。
  • 使用Auth.auth()方法取得Auth物件的實體進行登入、登出及查詢使用者資訊。
  • 在App內加入按鈕和TextField即可完成電話驗證流程。
  • 利用Firebase快速實現後端功能,支援多種驗證方式如Email, Facebook, Google等。

如果你正在開發一個需要用手機號碼來進行註冊或登入的APP,使用Firebase會是個很方便的選擇。只要簡單設置幾步驟,就能輕鬆驗證使用者身份,不論是透過Email、Facebook還是Google,都能快速上手。而且,只需一些基本UI元素,你就能在應用程式中直接顯示使用者的登入信息,讓整個流程變得更順暢、更直觀。

觀點延伸比較:
驗證方式安全性實作難易度使用者體驗最新趨勢
簡訊驗證 (SMS)中等,需防範SIM卡交換攻擊及攔截簡訊中等,需要設置Firebase和APNs溝通的URL Scheme並處理回調良好,但需要使用者等待簡訊接收仍然是主流方法之一,特別適用於全球多數地區
E-mail 驗證高,只要不被釣魚攻擊影響即可保障安全性低,非常容易實作,只需設定電子郵件模板和發送功能一般,使用者可能需要切換應用以查閱郵件並輸入驗證碼N/A - 傳統且穩定的方法
Facebook 登入驗證高,由Facebook提供保護,但依賴第三方平台的安全性措施中等,需要整合Facebook SDK並進行相關設定優秀,單一點擊即可登入逐漸增加,由於社交媒體日益普及
Gmail 登入驗證 (Google Sign-In)極高,由Google提供全面保護措施如2FA和風險分析中等,需要整合Google Sign-In SDK並進行相應配置優秀,同樣為單一點擊登入流程快速成長,大量應用開始採用因其強大的安全保障

在你的專案頁面中,點選位於頂部的「專案概覽」部分中的 Android 圖示。輸入套件名稱(例如:com.ek.firebasesmssample)、應用程式暱稱和 SHA-1 證書指紋。要獲取 SHA-1 證書指紋,請按照以下步驟操作:

開啟 Android Studio 中的終端機,並輸入以下命令:

keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

輸出中的 SHA1 值是您的憑證指紋。點選 ′Register App′ 按鈕。下載 google-services.json 檔案,並將其新增到 Android 專案的 app 目錄中。配置您的 Gradle 檔案:在專案級別的 build.gradle 檔案中新增以下行:

classpath 'com.google.gms:google-services:4.3.3'

請將以下幾行新增到您的應用程式級別的 build.gradle 檔案中:

apply plugin: 'com.google.gms.google-services'  dependencies {     implementation platform('com.google.firebase:firebase-bom:26.1.0')     implementation 'com.google.firebase:firebase-auth'     implementation 'com.google.firebase:firebase-analytics' }

設定身份驗證:
前往 Firebase 控制檯左側選單中的「Authentication」部分。
點選「Sign-in Method」標籤。
找到電話號碼登入方法並點選「Enable」。
可選擇性地自定義訊息模板。
點選「Save」按鈕。

建立您的 Android 專案並設定必要的檔案。activity_login.xml

                                  

現在,建立 LoginActivity 類並新增以下程式碼:

import android.os.Bundle import android.text.Editable import android.text.TextWatcher import android.util.Log import android.widget.Button import android.widget.EditText import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.widget.doAfterTextChanged import com.google.android.material.textfield.TextInputLayout import com.google.firebase.FirebaseApp import com.google.firebase.FirebaseException import com.google.firebase.appcheck.FirebaseAppCheck import com.google.firebase.appcheck.playintegrity.PlayIntegrityAppCheckProviderFactory import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.PhoneAuthCredential import com.google.firebase.auth.PhoneAuthProvider import java.util.concurrent.TimeUnit import java.util.regex.Pattern  class LoginActivity : AppCompatActivity() {      private lateinit var phoneNumberInput: EditText     private lateinit var loginButton: Button     private lateinit var phoneNumberLayout: TextInputLayout      private lateinit var auth: FirebaseAuth      override fun onCreate(savedInstanceState: Bundle?) {         super.onCreate(savedInstanceState)         setContentView(R.layout.activity_login)          phoneNumberInput = findViewById(R.id.phone_number_input)         loginButton = findViewById(R.id.login_button)         phoneNumberLayout = findViewById(R.id.phone_number_layout)          auth = FirebaseAuth.getInstance()         FirebaseApp.initializeApp(this)         val firebaseAppCheck = FirebaseAppCheck.getInstance()         firebaseAppCheck.installAppCheckProviderFactory(             PlayIntegrityAppCheckProviderFactory.getInstance()         )         phoneNumberInput.addTextChangedListener(object : TextWatcher {             private var current = ""             override fun afterTextChanged(s: Editable?) {                 if (s.toString() != current) {                     phoneNumberInput.removeTextChangedListener(this)                      val cleanString = s.toString().replace(" ", "").replace("+90", "")                     val formatted = cleanString.chunked(3).joinToString(" ")                      if (cleanString.length > 6) {                         val part1 = cleanString.substring(0, 3)                         val part2 = cleanString.substring(3, 6)                         val part3 = cleanString.substring(6)                         current = "+90 $part1 $part2$part3"                     } else {                         current = "+90 $formatted"                     }                      phoneNumberInput.setText(current)                     phoneNumberInput.setSelection(current.length)                      phoneNumberInput.addTextChangedListener(this)                 }             }              override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}              override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}         })          loginButton.setOnClickListener {             val phoneNumber = phoneNumberInput.text.toString()             if (isValidPhoneNumber(phoneNumber)) {                 startPhoneNumberVerification(phoneNumber)             } else {                 Toast.makeText(this, "Please enter a valid phone number", Toast.LENGTH_SHORT).show()             }         }     }      private fun isValidPhoneNumber(phoneNumber: String): Boolean {         val pattern = Pattern.compile("^\\+?[1-9]\\d{1,14}\$")         return pattern.matcher(phoneNumber.replace(" ", "")).matches()     }      private fun startPhoneNumberVerification(phoneNumber: String) {         val callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {              override fun onVerificationCompleted(credential: PhoneAuthCredential) {                 // This callback is triggered when verification is successful.                 // You can perform the sign-in operation here.                 signInWithPhoneAuthCredential(credential)             }              override fun onVerificationFailed(e: FirebaseException) {                 // This callback is triggered when verification fails.                 // Display an error message.                 Log.e("onVerificationFailed", e.message ?: "An error occurred")             }              override fun onCodeSent(                 verificationId: String,                 token: PhoneAuthProvider.ForceResendingToken             ) {                 Log.e("onCodeSent", "verificationId: $verificationId")                 // This callback is triggered when the verification code is sent.                 // You can create a credential using the received code.                 val credential = PhoneAuthProvider.getCredential(verificationId, "123456")                 signInWithPhoneAuthCredential(credential)             }         }          // Start the verification process with the phone number and callbacks.         PhoneAuthProvider.getInstance().verifyPhoneNumber(             phoneNumber, // Phone number             60, // Timeout duration             TimeUnit.SECONDS, // Timeout unit             this, // Activity (or Fragment)             callbacks         )     }      private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {         auth.signInWithCredential(credential)             .addOnCompleteListener(this) { task ->                 if (task.isSuccessful) {                     // Sign in success                     val user = task.result?.user                     val uid = user?.uid // User ID                     val phoneNumber = user?.phoneNumber // Phone number                     val providerId = user?.providerId // Provider ID                      sendUserToBackend(uid)                 } else {                     Log.e("signInWithCredential", "signInWithCredential:failure", task.exception)                     // Sign in failed                 }             }     }      private fun sendUserToBackend(uid: String?) {         Log.e("sendUserToBackend", "UID: $uid")         // This function can be used to send the user's uid to the backend.     } }

在 `startPhoneNumberVerification` 方法中,定義了在電話號碼驗證過程中將會觸發的事件,這些事件是透過回撥函式如 `onVerificationCompleted`、`onVerificationFailed` 和 `onCodeSent` 來實現的。`signInWithPhoneAuthCredential` 方法則使用 Firebase Authentication 執行登入操作。如果驗證成功,可以檢索使用者資訊並將其傳送到後端。


強化應用程式安全性:運用 Firebase 簡訊驗證的進階功能

在完成所有這些步驟後,你將收到來自 Firebase 的簡訊。當你輸入透過簡訊接收到的驗證碼時,`signInWithPhoneAuthCredential` 方法將會進行驗證,應用程式流程也會繼續進行。按照本文所述的步驟,你現在應該能夠在 Android 應用程式中使用 Firebase 實現安全的簡訊驗證。此方法不僅增強了使用者身份驗證的安全性,還為你的使用者提供了一個無縫的登入體驗。

實施簡訊驗證可以顯著減少未授權訪問,確保只有合法的使用者能夠登入你的應用程式。Firebase 的強大功能和易於整合特性,使其成為管理身份驗證和安全性的有力工具

**探索 Firebase 簡訊驗證的進階安全性功能**:Firebase 簡訊驗證不僅提供基礎驗證,還提供多項進階安全性功能,例如防詐騙保護、生物識別驗證和二要素認證(2FA)。利用這些功能,開發者可以強化應用程式的安全性,降低惡意活動和帳戶盜竊風險。

**與 Google Play 完整性 API 整合**:對於希望進一步提高應用程式安全性的開發者來說,Firebase 簡訊驗証可以與 Google Play 完整性 API 進行整合。透過檢查應用程式的安全性和完整性,此整合後可提高認証過程的可靠性,有助於識別潛在欺詐或惡意軟體威脅。

Firebase 檔案
Google Play 完整性 API
SHA-1 證書指紋
Gradle 對 Firebase 的配置

注意:在開發階段,Google 可能會自動啟動 reCaptcha 服務,因此在執行簡訊驗證時你可能會看到一個 reCaptcha 畫面。我沒有詳細說明這部分,以避免偏離主題。你可以在這裡找到更多相關資訊。


注意事項-2:目前無法自訂透過 Firebase 傳送的訊息模板。如果您希望使用自訂的訊息型別,應該考慮使用其他提供商。希望這篇文章能幫助您在 Android 應用程式中實現 SMS 驗證。如果您有任何問題或需要進一步協助,請隨時在下方留言。


「不要看著鐘錶;做它在做的事。繼續前進。」— 山姆·萊文森(Sam Levenson)

參考來源

Day14】Firebase 的登入驗證服務介紹 - iT 邦幫忙

電信業者登入 · 使用者在App 內選擇使用電話號碼進行驗證後,透過Firebase Auth SDK 進行驗證 · Firebase Auth 與APNs 之間進行溝通,確認是否已有APNs 憑證在Firebase 內 ...

來源: iT 邦幫忙

用Firebase Authentication 做一套簡易會員系統- 電子郵件密碼

本篇大綱:本篇要解決的問題。建立Firebase 專案、應用程式。開通Authentication 功能。註冊、登入。取得使用者資訊。登出。重新驗證使用者。

來源: letswrite.tw

Firebase Auth 系列2:「電話的Authentication」

我們只需要幾個按鈕加上TextField 就能進行電話驗證,然後在下方直接顯示使用者的登入信息即可。 圖2. 設置URL Scheme. 由於Firebase 上的iOS 有多一點 ...

來源: Medium

讓APP能以手機號碼註冊成為會員,使用Firebase 2017的Phone簡訊驗證

古老的 方法. 有許多的網站或APP會在註冊時用到手機號碼驗證,要讓一個APP的會員註冊能夠以使用者的手機號碼,輸入號碼後再傳送帶有驗證碼的簡訊,待 ...

來源: 綠豆湯學院

Firebase Authentication - 丹尼老師的Firebase 指南

要作這件事,就要用Firebase SDK 提供的Auth 物件,這個物件是Firebase 身份驗證的服務界面,登出登入查使用者都要用到它。取得它的實體很簡單,只要用Auth.auth() 方法即 ...

來源: WordPress.com

Firebase | #4 設定手機號碼進行登入驗證. 前言| by 黃暉德Wade Huang

Firebase 可以快速實現後端功能讓iOS App 進行串接,接下來就花幾篇文章來實作Firebase Authentication,透過Email, Facebook, Google, 手機號碼進行 ...

來源: Medium

安全性指南| App quality

驗證是許多重要安全性作業的先決條件。如要控管受保護的資產(例如使用者資料、應用程式功能及其他資源) 的存取權限,您需要在Android ...

來源: Android Developers

請註冊您的Firebase 應用程式以啟用Mobile Publisher Android 推送通知

前往Google Firebase Console,並使用Salesforce 具有散佈品牌應用程式權限的受管理Google Play 帳戶進行驗證。 如果您在2023 年11 月之前提交Mobile Publisher Android ...

來源: Salesforce

J.D.

專家

相關討論

❖ 相關專欄