Swift中的授权与认证:工具与库概览
在iOS和macOS开发中,用户数据安全是首要任务。认证(身份确认)和授权(授予访问权限)是任何现代应用程序的基本组成部分。在本文中,我们将介绍用于通过Apple ID、第三方服务(Google、Facebook)实现登录以及本地令牌存储的关键Swift工具、库和框架。
本文面向熟悉Swift和Xcode基础的开发者。所有代码示例均在Swift 5.9+上测试,并兼容iOS 17+/macOS 14+。
1. AuthenticationServices:Apple Sign In
通过Apple ID进行原生授权是App Store对使用第三方提供商(Google、Facebook)的应用程序的强制性要求。AuthenticationServices框架提供了用于实现Sign in with Apple的简单API。
import AuthenticationServicesimport SwiftUI
struct SignInWithAppleView: View { var body: some View { SignInWithAppleButton( onRequest: { request in request.requestedScopes = [.fullName, .email] }, onCompletion: { result in switch result { case .success(let authResults): // 获取用户令牌 guard let credential = authResults.credential as? ASAuthorizationAppleIDCredential, let tokenData = credential.identityToken, let token = String(data: tokenData, encoding: .utf8) else { return } print("Apple token: \\(token)") case .failure(let error): print("Error: \\(error.localizedDescription)") } } ) .signInWithAppleButtonStyle(.black) .frame(width: 280, height: 44) }}重要提示:Apple仅在首次登录时返回fullName和email。对于后续授权,请使用credential.user中的userID。
2. Firebase Authentication:多提供商认证
Firebase Auth是一个跨平台解决方案,用于通过电子邮件、Google、Facebook、GitHub和其他提供商进行授权。包括现成的UI组件和与Firestore的集成。
通过Swift Package Manager安装:
// Package.swift 或通过 Xcode:File > Add Packages// URL:https://github.com/firebase/firebase-ios-sdk.git// 选择 FirebaseAuth, FirebaseFirestore通过电子邮件/密码登录示例:
import FirebaseAuth
func signInWithEmail(email: String, password: String) { Auth.auth().signIn(withEmail: email, password: password) { authResult, error in if let error = error { print("Auth error: \\(error.localizedDescription)") return } guard let user = authResult?.user else { return } print("User signed in: \\(user.uid)") }}
func createUser(email: String, password: String) { Auth.auth().createUser(withEmail: email, password: password) { authResult, error in // 处理注册 }}对于Google Sign-In,额外使用GoogleSignIn SDK。Firebase自动管理会话和令牌刷新。
3. Keychain Services:安全存储令牌
将JWT令牌或刷新令牌存储在UserDefaults中是一个严重的安全错误。请使用Keychain(iOS/macOS加密存储)。
Keychain封装:
import Security
class KeychainManager { static func save(key: String, data: Data) { let query: [String: Any] = [ kSecClass as String: kSecClassGener