Flutter ー Authentication 認證
Flutter ー Authentication 認證
原文 https://medium.com/@simbu/flutter-authentication-adb8df7cf673
前言
如果我相信我知道你是誰那我就能讓你檢視你的個人 應用 application 資料。
身份驗證可能是應用程式必須處理的最大的交叉問題。
將它作為一個特性新增到 DigestablePrologue 允許我們多次抽象和重用它,並通過更新一組程式碼來減少維護。
正文
業務需求
讓我們從一個高層次的、故意模糊的業務需求開始:
“該應用程式將能夠使用現代身份驗證保護對螢幕和 API 的訪問”
經過最初的交談,我們決定接受這個要求:
- 滑動登入螢幕。
- 使用 Microsoft AD 或 Google Firebase 進行身份驗證。
- 在設定中登出。
然後,我們舉辦了一個研討會,通過示例建立規範:
Login slide up specification
認證服務規範
登出設定規範
並將它們轉換為可執行規範:
登入螢幕功能測試
身份驗證服務特性測試
登出設定特性測試
為了縮短這篇文章的篇幅,我已經部分實現了登出設定,跳過了即將新增的 AD & Firebase 身份驗證服務。
因此,特性測試的結果不再完全反映最初的規範,但是一旦深入細節,範圍或方向的改變是正常的。
我發表的所有關於認證和資料訪問主題的文章將很快通過一篇摘要文章(一個迷你係列文章)結合在一起。
開始
從 app_config 讀取環境。Json 檔案,該檔案在應用程式啟動時載入,並由為 live 和 UAT 進行的 CodeMagic 整合構建注入:
根據環境選擇身份驗證服務:
```dart AuthenticationServiceStateNotifier selectAuthenticationServiceByEnvironment() {
var environment = GlobalEnvironmentValues.instance.environment;
AuthenticationService authenticationService = environment == Environments.live
? LiveAuthenticationService()
: environment == Environments.uat
? UatAuthenticationService()
: StubbedAuthenticationService();
return AuthenticationServiceStateNotifier(authenticationService);
}
final authenticationServiceProvider = StateNotifierProvider<
AuthenticationServiceStateNotifier, AuthenticationService>(
(ref) => selectAuthenticationServiceByEnvironment(),
); ```
當應用程式啟動時,它會檢測存根身份驗證服務並自動驗證使用者:
```dart if (ref.read(authenticationServiceProvider).typeName ==
AuthenticationService.authenticationServiceTypeNameStubbed) {
ref.read(authenticationProvider.notifier).setIsAuthenticated(true);
} ```
這個設定螢幕是使用一個很棒的包 sets_ui 新增的,它允許使用者登出,並呼叫身份驗證服務上的 signOut 方法:
登出設定
我們的自動化特性測試涵蓋了所有內容:
登入功能測試報告
認證特性測試報告
在未來的帖子中,當我們新增 UAT 和 Live 環境時,它會在未經身份驗證時路由到登入螢幕,並呼叫真正的身份驗證服務來獲取訪問令牌,這些令牌將被 Flutter Data 用來進行安全的 API 請求。
登入螢幕和身份驗證服務已經新增到 DigestablePrologue,設定螢幕新增到 DigestableMe。
引發導航事件 navigation events
為了響應導航,我在路由器上增加了一個觀察者
```dart MaterialApp.router(
...
navaigationObservers: [
NavigationEventsObserver(ref.read(eventStoreProvider))
],
...
) ```
每次導航發生時,它都會在事件總線上引發 Navigated 事件:
```dart /// Raises Nativigated events when the GoRouter navigates.
class NavigationEventsObserver extends NavigatorObserver {
final EventStore eventStore;
NavigationEventsObserver(this.eventStore);
@override
void didPush(Route
raiseNavigatedEvent(route.settings.name ?? "");
}
@override
void didPop(Route
raiseNavigatedEvent(route.settings.name ?? "");
}
@override
void didReplace({ Route
raiseNavigatedEvent(newRoute?.settings.name ?? "");
}
void raiseNavigatedEvent(String routeName) {
even(fn)tStore.bus.fire(Navigated(routeName));
}
} ```
然後測試可以使用它來證明導航操作已經發生,當前事件儲存僅保留最後一個 Navigated 事件。
通過偵聽事件並記錄它們,我很可能會 extension 這個功能來新增應用程式監視。
Flutter App 生命週期
為了在喚醒時強制執行所需的身份驗證,我需要使用重寫來捕獲應用程式狀態(AppLificycleState)。
```dart @override
void didChangeAppLifecycleState(AppLifecycleState state) {
ref.read(appLifecycleStateProvider.notifier)
.setLifecycleState(state);
ref.read(authenticationServiceProvider.notifier)
.checkAuthenticated();
} ```
可觀察的生命週期事件(AppLificycleState) :
- Inactive ー應用程式處於非活動狀態,不接收使用者輸入。這個事件只能在 iOS 上執行,因為在 Android 上沒有等效的事件可以對映到
- 暫停ー應用程式當前對使用者不可見,不響應使用者輸入,並在後臺執行。這相當於 Android 中的 onPace()
- 應用程式可見並響應使用者輸入,這相當於 Android 中的 onPostResume()
- 暫停ー 應用 application 暫停。這相當於 Android 中的 onStop; 它不會在 iOS 上觸發,因為在 iOS 上沒有可對映到的等價事件
功能測試支援你
特性測試讓我們知道我們已經破壞了其他特性
這是偉大的,我已經做了一些相當大的變化,但我知道我需要修復,以避免任何迴歸錯誤。
測試的契約確保應用程式仍然能夠完成早期特性所要求的工作。
特性測試認證
事實證明,要使特性測試通過非常困難,但是為了確保身份驗證按計劃工作,將它們放在適當的位置是值得的。
主要問題是在測試步驟執行之前從檔案載入環境,這意味著我們已經運行了檢查身份驗證和重定向到登入螢幕的邏輯。
在幾次嘗試通過程式碼改變環境失敗後,我選擇了一套單獨的特性測試:
Gherkin 特性測試配置,載入實時配置值檔案。
載入不同的環境配置檔案:
實時配置值檔案
它需要更多的維護,但是很有必要,因為我們將在整合和部署構建中注入配置檔案以保護祕密值。
使用事件來解決難以實現的、特徵化的測試步驟
登入特性的一些步驟很難實現,因為功能將在使用微應用程式 DigestablePrologue 的父應用程式 DigestableMe 中實現:
dart
When: Making an API request
這意味著我們無法在 DigestablePrologue 中導航到螢幕或發出 API 請求。
這是一個耦合問題,我們可以用事件匯流排來解決。
應用程式現在只是偵聽事件並採取適當的操作,允許我們在步驟中引發事件,而不是實際的導航或 API 呼叫。
何時: 發出 API 請求事件: API 請求
使用 EventBus 還有其他優點,我們可以在以後新增這些優點,例如記錄引發的事件。
規程 ーー 執行特性步驟
使用 Flutter Gherkin 最乏味的部分是建立所有的步驟方法,我將嘗試使用構建器來自動建立包含要填寫的框架步驟的檔案。
與此同時,我使用視覺化程式碼中的高亮來規範所需的步驟,例如:
這樣說:
```dart Given: Always on authentication
And: Not authenticated
And: authenticated
When: The application is started
When: The application awakes
When: Making an API request
When: Displaying a restricted screen
When: Displaying an unrestricted screen
Then: The application routes to the 'Login Screen'
And: Records the current screen for redirection ```
然後將骨架方法新增到步驟檔案中
路線授權
具有自定義屬性的路由角色,則可以實現基於非角色的路由,大家暫時可以,但可以 extension 。
沒有實現登入/id/auth 的受限螢幕,因為它的一些不同之處,它的授權和路由保護,在需要時通過 GoRouter 重定向作為保護。
Packages
結束語
如果本文對你有幫助,請轉發讓更多的朋友閱讀。
也許這個操作只要你 3 秒鐘,對我來說是一個激勵,感謝。
祝你有一個美好的一天~
© 貓哥
-
微信 ducafecat
-
https://wiki.ducafecat.tech
-
https://video.ducafecat.tech
- Flutter 中使用 OpenAI GPT-3 進行語義化處理
- Flutter 構建設計系統
- Flutter ー Authentication 認證
- Flutter 離線資料方案 Flutter_Data 包
- 基於 Hive 的 Flutter 文件型別儲存
- Flutter AlarmManager = ⏰
- Flutter 8 個優秀動畫 Packages
- Flutter 建立自己的對話方塊,不使用任何包!
- 在 Flutter App 中編寫自定義平臺特定程式碼[Method Channel]
- Flutter 最有用的 5 個優秀的依賴包
- Neumorphism 元件 ーー Dart extension 擴充套件
- 用抽象工廠方法構建 Flutter 主題
- Dart 語言的7個很酷的特點
- 17 個提高效能的 Flutter 最佳實踐
- Flutter 應用程式建立一個擴充套件面板列表
- 在 Flutter 使用 GetX 對話方塊
- flutter 互動式使用者指導,以及如何在佈局中創造一個洞
- Flutter開源專案 - appFlowy 真的是 Notion 的替代品? 一週暴漲 star 9k 多!
- 桌面 Flutter 應用程式
- Flutter 2020 開源專案推薦 第一彈