利用 Firebase 實現 iOS App 的登入註冊功能

對 iOS App 開發的初學者來說,Firebase 可以幫我們快速實現後台功能,完成具有雲端功能的 App。而登入這個雲端 App 幾乎必備的功能 Firebase 當然也提供了,而且還一口氣提供多種登入選擇,想要帳密,FB,Google 登入都不是問題。

接下來就讓我們一步步實現 Firebase 的帳密 & FB 登入功能吧。

Firebase 登入的官方文件

喜歡照著官方說明一步步操作的朋友,可參考以下連結。

從 Authentication(認證) > iOS 研究 iOS 登入的相關說明。

懶得看官方說明的朋友,則可跟著彼得潘一步步實現 Firebase 登入功能。

建立 Firebase 專案

若已建立 Firebase 專案,則可跳過此步驟。

連到專案頁面

設定 iOS App 的 Firebase 功能

點選左邊側邊欄 Build 下的 Authentication

點選 Get started。

點選 sign-in method

有多種登入的方式可選擇,比方帳密登入,Apple 登入,FB 登入,Google 登入等,接下來讓我們先實現最常見的帳密登入功能。

打開帳號密碼登入功能

點選 Email/ Password。

將允許使用者帳密登入的開關打開後按 Save。

之後若想加入其它登入的方式,可再點選 Add new provider。

從網頁建立帳號

切換到 Users 分頁,點選 Add user。

輸入帳密,點選 Add user。

利用 SPM 加入 Firebase 套件的 FirebaseAuth

加入登入的 framework

撰寫 Firebase 登入程式時,記得先 import FirebaseAuth。

import FirebaseAuth

從程式建立帳號

呼叫 Auth 物件的 createUser,傳入帳密建立新的使用者,成功時可取得使用者的 email & uid。

Auth.auth().createUser(withEmail: "peter@neverland.com", password: "123456") { result, error in

guard let user = result?.user,
error == nil else {
print(error?.localizedDescription)
return
}
print(user.email, user.uid)
}

建立帳號成功後使用者將是已登入狀態,下次重新啟動 App 也會是已登入狀態。

ps: 若是開發 UIKit App,在 class 裡呼叫 Auth.auth().createUser,可在 closure 裡加上 capture list。

從 Firebase 查詢使用者清單

從專案 Authentication 頁面的 Users 分頁可看到使用者清單。

帳密登入

呼叫 Auth 物件的 signIn 登入。

Auth.auth().signIn(withEmail: "peter@neverland.com", password: "123456") { result, error in
guard error == nil else {
print(error?.localizedDescription)
return
}
print("success")
}

登入後使用者將維持登入狀態,就算我們重新啟動 App ,使用者還是能保持登入。

判斷使用者是否登入

  • 方法 1

當 Auth.auth().currentUser 有值時代表使用者已登入。

if let user = Auth.auth().currentUser {
print("\(user.uid) login")
} else {
print("not login")
}
  • 方法 2

呼叫 Auth 物件的 addStateDidChangeListener 申請接收登入狀態改變的通知,當使用者登入 / 登出時我們將可收到通知,若 addAuthStateDidChangeListener 的 closure 參數 user 有值即代表使用者已登入。

Auth.auth().addStateDidChangeListener { auth, user in
if let user {
print("\(user.uid) login")
} else {
print("not login")
}
}

關於 Firebase 上使用者管理的更多說明,比方設定密碼 & 取得個人 profile 資訊,可進一步參考以下連結。

設定使用者的名字跟照片網址

設定 photoURL & displayName。

let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.photoURL = URL(string: "https://images.pexels.com/photos/1170986/pexels-photo-1170986.jpeg")
changeRequest?.displayName = "帥哥"
changeRequest?.commitChanges(completion: { error in
guard error == nil else {
print(error?.localizedDescription)
return
}

})

取得使用者的基本資訊

取得 id,email,名字和照片網址。

if let user = Auth.auth().currentUser {
print(user.uid, user.email, user.displayName, user.photoURL)
}

設定使用者的額外資訊和讀取其它使用者的資料

在 Authentication 頁面儲存的使用者列表有以下限制。

  • 它是不公開的,我們無法從程式讀取其它使用者的資訊。
  • 它的欄位是固定的,我們無法新增欄位儲存其它資訊。

為了儲存其它資訊跟讀取其它使用者的資料,我們必須另外在 FireStore 上儲存使用者資料。

登出

do {
try Auth.auth().signOut()
} catch {
print(error)
}

實現了最基本的帳密登入功能後,接著讓我們也試試很常見的 FB 登入功能吧。

Facebook 登入

首先照著以下連結的說明實現 iOS App 的 Facebook 登入功能。

依據以上連結操作,我們的 App 已經可以 FB 登入,但是它跟 Firebase 完全沒關聯。我們想要的是 FB 登入的使用者能成為 Firebase 上的使用者,因此請進入 Firebase 專案的 Authentication 頁面,切換到 Sign-in method 分頁,點選 Add new provider。

點選 Facebook 新增 FB 登入。

此時我們需輸入 FB 開發網站上 App 的 App ID & App secret,我們可從 FB 網站上 App 的 Settings > Basic 頁面查詢 App 的 App ID & App secret。

在 Firebase Sign-in method 的 FB 設定裡輸入 App ID & App secret,然後點選右下方的 Save。

ps: 圖片裡還有個 OAuth redirect URI 需設定 ,不過目前測試後沒有設定並不影響 FB 登入功能。

以下為 FB 登入的相關程式,主要分為兩個步驟,先用 LoginManager 的 logIn 登入 FB,然後再用 AccessToken.current!.tokenString 產生 Firebase 登入需要的 credential,然後以 Auth.auth().signIn 登入。

SwiftUI 版本

func login() {
let manager = LoginManager()
manager.logIn { result in
if case LoginResult.success(granted: _, declined: _, token: _) = result {
print("fb login ok")

let credential = FacebookAuthProvider.credential(withAccessToken: token!.tokenString)
Auth.auth().signIn(with: credential) { result, error in
guard error == nil else {
print(error?.localizedDescription)
return
}
print("login ok")
}

} else {
print("login fail")
}
}
}

UIKit 版本

func login() {
let manager = LoginManager()
manager.logIn(permissions: [.publicProfile], viewController: self) { result in
if case LoginResult.success(granted: _, declined: _, token: let token) = result {
print("fb login ok")

let credential = FacebookAuthProvider.credential(withAccessToken: token!.tokenString)
Auth.auth().signIn(with: credential) { [weak self] result, error in
guard let self else { return }
guard error == nil else {
print(error?.localizedDescription)
return
}
print("login ok")
}

} else {
print("login fail")
}
}
}

成功登入後在 Firebase 的 Authentication > Users 分頁可看到 FB 登入的使用者。

我們也可以從 Auth.auth().currentUser 的 providerData 進一步取得從 FB 等第三方平台登入的相關資訊。

if let user = Auth.auth().currentUser {
print("\(user.providerID) login")
if user.providerData.count > 0 {
let userInfo = user.providerData[0]
print(userInfo.providerID, userInfo.displayName, userInfo.photoURL)
}
} else {
print("not login")
}

比方彼得潘以 FB 登入後,以上程式列印的 userInfo 如下:

facebook.com Optional("Deeplove Pan") Optional(https://graph.facebook.com/10214280447396741/picture)

對官方說明有興趣的朋友,可進一步參考以下連結。

Google 登入

可參考可愛同學 Cathie 的學習筆記。

Apple ID 登入

現在 iOS App 上最好的登入方式非 Apple ID 登入莫屬,對這部份有興趣的可參考以下連結。

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com