【iOS】苹果登录Sign in with Apple
在iOS13中,如果苹果开发者提供任何其他第三方登录,就必须提供“苹果登录”选项。也就是说,如果软件要求“微信登录”或是“QQ登录”时,必须同时提供“苹果登录”的选项给用户自行选择。根据苹果公司最新公布的指南,要求开发者在苹果终端的应用程序登录界面上,将“苹果登录”选项列在任何其他第三方登录的选项之上。
注:以下内容源于官方文档翻译Sign in with Apple
1、添加登录按钮
func setupProviderLoginView() { let authorizationButton = ASAuthorizationAppleIDButton() authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside) self.loginProviderStackView.addArrangedSubview(authorizationButton) }
提示:当你在故事板中添加用苹果按钮登录时,你还必须在Xcode的身份检查器中将控件的类值设置为ASAuthorizationAppleIDButton。
2、请求Apple ID授权
当用户点击Apple按钮登录时,视图控制器调用handleAuthorizationAppleIDButtonPress()函数,该函数通过对用户的全名和电子邮件地址执行授权请求来启动身份验证流程。然后,系统检查用户是否用设备上的Apple ID登录。如果用户没有在系统级登录,应用程序会显示一个警告,指示用户在设置中使用他们的Apple ID登录。
@objc func handleAuthorizationAppleIDButtonPress() { let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() request.requestedScopes = [.fullName, .email] let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() }
提示:用户在使用“登录与苹果”(Sign in with Apple)时,必须启用双重身份验证,这样才能安全访问该账户。
授权控制器调用presentationAnchor(for:)函数来从应用程序获取窗口,在窗口中,它会以模态表单的形式向用户显示带有苹果内容的登录。
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { return self.view.window! }
如果用户使用Apple ID在系统级登录,则会出现描述使用Apple功能登录的工作表,然后是另一个工作表,允许用户编辑其帐户中的信息。用户可以编辑他们的第一个和最后一个名称,选择另一个电子邮件地址作为他们的联系信息,并从应用程序隐藏他们的电子邮件地址。如果用户选择隐瞒自己的电子邮件地址从应用程序,苹果会生成一个代理邮箱地址转发邮件到用户的私人电子邮件地址。最后,用户输入Apple ID的密码,然后单击Continue创建帐户。
3、Handle User Credentials
如果验证成功,授权控制器调用authorizationController(controller:didCompleteWithAuthorization:)委托函数,应用程序使用该函数在密钥链中存储用户数据。
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { switch authorization.credential { case let appleIDCredential as ASAuthorizationAppleIDCredential: // Create an account in your system. let userIdentifier = appleIDCredential.user let fullName = appleIDCredential.fullName let email = appleIDCredential.email // For the purpose of this demo app, store the `userIdentifier` in the keychain. self.saveUserInKeychain(userIdentifier) // For the purpose of this demo app, show the Apple ID credential information in the `ResultViewController`. self.showResultViewController(userIdentifier: userIdentifier, fullName: fullName, email: email) case let passwordCredential as ASPasswordCredential: // Sign in using an existing iCloud Keychain credential. let username = passwordCredential.user let password = passwordCredential.password // For the purpose of this demo app, show the password credential as an alert. DispatchQueue.main.async { self.showPasswordCredentialAlert(username: username, password: password) } default: break } }
在你的实现中,ASAuthorizationControllerDelegate.authorizationController(controller:didCompleteWithAuthorization:)委托函数应该使用用户标识符中包含的数据在你的系统中创建一个帐户。
如果身份验证失败,授权控制器调用authorizationController(controller:didCompleteWithError:)委托函数来处理错误。
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { // Handle error. }
一旦系统验证了用户,应用程序就会显示ResultViewController,它会显示框架请求的用户信息,包括用户提供的全名和电子邮件地址。视图控制器还显示一个Sign Out按钮,并将用户数据存储在密钥链中。当用户点击Sign Out按钮时,应用程序从视图控制器和密钥链中删除用户信息,并将LoginViewController呈现给用户。
4、要求现有的凭证
performexistingaccountsetupflows()函数的作用是:通过请求苹果ID和iCloud密钥链密码来检查用户是否拥有现有的帐户。类似于handleAuthorizationAppleIDButtonPress(),授权控制器设置它的表示内容提供程序和LoginViewController对象的委托。
func performExistingAccountSetupFlows() { // Prepare requests for both Apple ID and password providers. let requests = [ASAuthorizationAppleIDProvider().createRequest(), ASAuthorizationPasswordProvider().createRequest()] // Create an authorization controller with the given requests. let authorizationController = ASAuthorizationController(authorizationRequests: requests) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)