iOS 13-Sign In with Apple
最近了解了iOS 13
新增功能之Sign In with Apple
千绪,Sign In with Apple
是跨平臺的杂彭,可以支持iOS锥腻、macOS初坠、watchOS涵防、tvOS、JS
栏账。本文主要內(nèi)容為Sign In with Apple
在iOS
上的基礎使用。詳情參考WWDC 2019
- 審核備注
Sign In with Apple will be available for beta testing this summer. It will be required as an option for users in apps that support third-party sign-in when it is commercially available later this year.
也就是說栈源,當 Sign In with Apple 服務正式上線以后挡爵,所有已接入其它第三方登錄的 App,Sign In with Apple 將被要求作為一種登錄選擇甚垦,否則有可能就不給過茶鹃。詳情參考App Store審核指南更新
-
開發(fā)
Sign In with Apple
的注意事項
需要在蘋果后臺打開該選項,并且重新生成Profiles
配置文件艰亮,并安裝到Xcode
闭翩,如下圖image -
iOS
使用Sign In with Apple
在Xcode
的準備工作
在Xcode11 Signing & Capabilities
中添加Sign In With Apple
,如下圖image iOS Sign In with Apple
流程
- 添加 Sign In with Apple 登錄按鈕迄埃,設置 ASAuthorizationAppleIDButton 相關布局疗韵,并添加按鈕點擊響應事件
- 獲取授權碼
- 驗證
- 添加
Sign In with Apple
登錄按鈕,設置ASAuthorizationAppleIDButton
相關布局侄非,并添加按鈕點擊響應事件蕉汪。當然蘋果也允許自定義蘋果登錄按鈕的樣式,樣式要求詳見這個文檔:Human Interface Guidelines
- (void)configUI{
// 用于展示Sign In With Apple 登錄過程的信息
_appleIDInfoLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 40.0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) * 0.4)];
_appleIDInfoLabel.font = [UIFont systemFontOfSize:22.0];
_appleIDInfoLabel.numberOfLines = 0;
_appleIDInfoLabel.lineBreakMode = NSLineBreakByWordWrapping;
_appleIDInfoLabel.text = @"顯示Sign In With Apple 登錄信息\n";
[self.view addSubview:_appleIDInfoLabel];
if (@available(iOS 13.0, *)) {
// Sign In With Apple Button
ASAuthorizationAppleIDButton *appleIDBtn = [ASAuthorizationAppleIDButton buttonWithType:ASAuthorizationAppleIDButtonTypeDefault style:ASAuthorizationAppleIDButtonStyleWhite];
appleIDBtn.frame = CGRectMake(30, self.view.bounds.size.height - 180, self.view.bounds.size.width - 60, 100);
// appleBtn.cornerRadius = 22.f;
[appleIDBtn addTarget:self action:@selector(handleAuthorizationAppleIDButtonPress) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:appleIDBtn];
}
}
// 處理授權
- (void)handleAuthorizationAppleIDButtonPress{
NSLog(@"http:////////");
if (@available(iOS 13.0, *)) {
// 基于用戶的Apple ID授權用戶逞怨,生成用戶授權請求的一種機制
ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
// 創(chuàng)建新的AppleID 授權請求
ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];
// 在用戶授權期間請求的聯(lián)系信息
appleIDRequest.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
// 由ASAuthorizationAppleIDProvider創(chuàng)建的授權請求 管理授權請求的控制器
ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest]];
// 設置授權控制器通知授權請求的成功與失敗的代理
authorizationController.delegate = self;
// 設置提供 展示上下文的代理者疤,在這個上下文中 系統(tǒng)可以展示授權界面給用戶
authorizationController.presentationContextProvider = self;
// 在控制器初始化期間啟動授權流
[authorizationController performRequests];
}
}
- 已經(jīng)使用
Sign In with Apple
登錄過app
的用戶
如果設備中存在iCloud Keychain
憑證或者AppleID
憑證,提示用戶直接使用TouchID
或FaceID
登錄即可叠赦,代碼如下
// 如果存在iCloud Keychain 憑證或者AppleID 憑證提示用戶
- (void)perfomExistingAccountSetupFlows{
NSLog(@"http:///已經(jīng)認證過了/////");
if (@available(iOS 13.0, *)) {
// 基于用戶的Apple ID授權用戶驹马,生成用戶授權請求的一種機制
ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
// 授權請求AppleID
ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];
// 為了執(zhí)行鑰匙串憑證分享生成請求的一種機制
ASAuthorizationPasswordProvider *passwordProvider = [[ASAuthorizationPasswordProvider alloc] init];
ASAuthorizationPasswordRequest *passwordRequest = [passwordProvider createRequest];
// 由ASAuthorizationAppleIDProvider創(chuàng)建的授權請求 管理授權請求的控制器
ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest, passwordRequest]];
// 設置授權控制器通知授權請求的成功與失敗的代理
authorizationController.delegate = self;
// 設置提供 展示上下文的代理,在這個上下文中 系統(tǒng)可以展示授權界面給用戶
authorizationController.presentationContextProvider = self;
// 在控制器初始化期間啟動授權流
[authorizationController performRequests];
}
}
- 獲取授權碼
獲取授權碼需要在代碼中實現(xiàn)兩個代理回調(diào)ASAuthorizationControllerDelegate除秀、ASAuthorizationControllerPresentationContextProviding
分別用于處理授權登錄成功和失敗糯累、以及提供用于展示授權頁面的Window
,代碼如下
#pragma mark - delegate
//@optional 授權成功地回調(diào)
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization{
NSLog(@"授權完成:::%@", authorization.credential);
NSLog(@"%s", __FUNCTION__);
NSLog(@"%@", controller);
NSLog(@"%@", authorization);
// 測試配置UI顯示
NSMutableString *mStr = [NSMutableString string];
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
// 用戶登錄使用ASAuthorizationAppleIDCredential
ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
NSString *user = appleIDCredential.user;
NSString *familyName = appleIDCredential.fullName.familyName;
NSString *givenName = appleIDCredential.fullName.givenName;
NSString *email = appleIDCredential.email;
// NSData *identityToken = appleIDCredential.identityToken;
// NSData *authorizationCode = appleIDCredential.authorizationCode;
// Create an account in your system.
// For the purpose of this demo app, store the userIdentifier in the keychain.
// 需要使用鑰匙串的方式保存用戶的唯一信息
[YostarKeychain save:KEYCHAIN_IDENTIFIER(@"userIdentifier") data:user];
[mStr appendString:user];
[mStr appendString:@"\n"];
[mStr appendString:familyName];
[mStr appendString:@"\n"];
[mStr appendString:givenName];
[mStr appendString:@"\n"];
[mStr appendString:email];
NSLog(@"mStr:::%@", mStr);
[mStr appendString:@"\n"];
_appleIDInfoLabel.text = mStr;
}else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]){
// Sign in using an existing iCloud Keychain credential.
// 用戶登錄使用現(xiàn)有的密碼憑證
ASPasswordCredential *passwordCredential = authorization.credential;
// 密碼憑證對象的用戶標識 用戶的唯一標識
NSString *user = passwordCredential.user;
// 密碼憑證對象的密碼
NSString *password = passwordCredential.password;
[mStr appendString:user];
[mStr appendString:@"\n"];
[mStr appendString:password];
[mStr appendString:@"\n"];
NSLog(@"mStr:::%@", mStr);
_appleIDInfoLabel.text = mStr;
}else{
NSLog(@"授權信息均不符");
mStr = [@"授權信息均不符" copy];
_appleIDInfoLabel.text = mStr;
}
}
// 授權失敗的回調(diào)
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error{
// Handle error.
NSLog(@"Handle error:%@", error);
NSString *errorMsg = nil;
switch (error.code) {
case ASAuthorizationErrorCanceled:
errorMsg = @"用戶取消了授權請求";
break;
case ASAuthorizationErrorFailed:
errorMsg = @"授權請求失敗";
break;
case ASAuthorizationErrorInvalidResponse:
errorMsg = @"授權請求響應無效";
break;
case ASAuthorizationErrorNotHandled:
errorMsg = @"未能處理授權請求";
break;
case ASAuthorizationErrorUnknown:
errorMsg = @"授權請求失敗未知原因";
break;
default:
break;
}
NSMutableString *mStr = [_appleIDInfoLabel.text mutableCopy];
[mStr appendString:@"\n"];
[mStr appendString:errorMsg];
[mStr appendString:@"\n"];
_appleIDInfoLabel.text = mStr;
}
// 告訴代理應該在哪個window 展示內(nèi)容給用戶
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller{
NSLog(@"88888888888");
// 返回window
return self.view.window;
}
在授權登錄成功回調(diào)中册踩,我們可以拿到以下幾類數(shù)據(jù)
-
UserID:
Unique, stable, team-scoped user ID
泳姐,蘋果用戶唯一標識符,該值在同一個開發(fā)者賬號下的所有App
下是一樣的棍好,開發(fā)者可以用該唯一標識符與自己后臺系統(tǒng)的賬號體系綁定起來(這與國內(nèi)的微信仗岸、QQ、微博
等第三方登錄流程基本一致) -
Verification data:
Identity token, code
借笙,驗證數(shù)據(jù)扒怖,用于傳給開發(fā)者后臺服務器,然后開發(fā)者服務器再向蘋果的身份驗證服務端驗證业稼,本次授權登錄請求數(shù)據(jù)的有效性和真實性盗痒,詳見Sign In with Apple REST API -
Account information:
Name, verified email
,蘋果用戶信息,包括全名俯邓、郵箱等骡楼,注意:如果玩家登錄時拒絕提供真實的郵箱賬號,蘋果會生成虛擬的郵箱賬號
- 驗證
關于驗證的這一步稽鞭,需要傳遞授權碼給自己的服務端鸟整,自己的服務端調(diào)用蘋果API
去校驗授權碼Generate and validate tokens。如果驗證成功朦蕴,可以根據(jù)userIdentifier
判斷賬號是否已存在篮条,若存在,則返回自己賬號系統(tǒng)的登錄態(tài)吩抓,若不存在涉茧,則創(chuàng)建一個新的賬號,并返回對應的登錄狀態(tài)給App
附:官方示例代碼 Swift 版
附:What the Heck is Sign In with Apple?
附:蘋果授權登陸后端驗證
附:App Store審核指南的更新
附:Generate and validate tokens
附:SignInAppleDemo
附:我的博客地址
</article>