1、配置app套餐的Identifiers支持Sign In With Apple
如下圖
2、項目配置
3、集成代碼
主要步驟:
-
使用ASAuthorizationAppleIDButton創建button,布局,添加點擊事件;
-
實現點擊事件:授權請求
-
授權代理實現(授權成功,授權失?。〢SAuthorizationControllerDelegate
-
驗證
-
已經Sign In with Apple登陸過app的用戶,處理
-
監聽授權狀態改變
4、實現
使用ASAuthorizationAppleIDButton創建button,布局,添加點擊事件;
- (void)createView {
if (@available(iOS 13.0, *)) {
ASAuthorizationAppleIDButton *appleIDButton = [[ASAuthorizationAppleIDButton alloc] init];
appleIDButton.frame = CGRectMake(50, 100+CGRectGetHeight(self.view.frame) * 0.4, CGRectGetWidth(self.view.frame)-100, 50);
[appleIDButton addTarget:self action:@selector(appleIDButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:appleIDButton];
}
}
實現點擊事件:授權請求
- (void)appleIDButtonClicked API_AVAILABLE(ios(13.0)) {
//基于用戶的Apple ID授權用戶,生成用戶授權請求的一種機制
ASAuthorizationAppleIDProvider *provide = [[ASAuthorizationAppleIDProvider alloc] init];
//創建新的AppleID 授權請求
ASAuthorizationAppleIDRequest *request = provide.createRequest;
//在用戶授權期間請求的聯系信息
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
//由ASAuthorizationAppleIDProvider創建的授權請求 管理授權請求的控制器
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
//設置授權控制器通知授權請求的成功與失敗的代理
controller.delegate = self;
//設置提供 展示上下文的代理,在這個上下文中 系統可以展示授權界面給用戶
controller.presentationContextProvider = self;
//在控制器初始化期間啟動授權流
[controller performRequests];
}
授權代理實現(授權成功,授權失?。〢SAuthorizationControllerDelegate
驗證
#pragma mark - ASAuthorizationControllerDelegate
//授權成功的回調
/**
當授權成功后,我們可以通過這個拿到用戶的 userID、email、fullName、authorizationCode、identityToken 以及 realUserStatus 等信息。
*/
-(void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
// 用戶登錄使用ASAuthorizationAppleIDCredential
ASAuthorizationAppleIDCredential *credential = authorization.credential;
//蘋果用戶唯一標識符,該值在同一個開發者賬號下的所有 App 下是一樣的,開發者可以用該唯一標識符與自己后臺系統的賬號體系綁定起來。
NSString *userId = credential.user;
NSString *state = credential.state;
NSPersonNameComponents *fullName = credential.fullName;
//蘋果用戶信息,郵箱
NSString *email = credential.email;
NSString *authorizationCode = [[NSString alloc] initWithData:credential.authorizationCode encoding:NSUTF8StringEncoding]; // refresh token
/**
驗證數據,用于傳給開發者后臺服務器,然后開發者服務器再向蘋果的身份驗證服務端驗證本次授權登錄請求數據的有效性和真實性,詳見 Sign In with Apple REST API。如果驗證成功,可以根據 userIdentifier 判斷賬號是否已存在,若存在,則返回自己賬號系統的登錄態,若不存在,則創建一個新的賬號,并返回對應的登錄態給 App。
*/
NSString *identityToken = [[NSString alloc] initWithData:credential.identityToken encoding:NSUTF8StringEncoding];
/**
用于判斷當前登錄的蘋果賬號是否是一個真實用戶
取值有:unsupported、unknown、likelyReal。
*/
ASUserDetectionStatus realUserStatus = credential.realUserStatus;
// 存儲userId到keychain中,代碼省略
······
} else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
// 用戶登錄使用現有的密碼憑證
ASPasswordCredential *passwordCredential = authorization.credential;
// 密碼憑證對象的用戶標識 用戶的唯一標識
NSString *user = passwordCredential.user;
// 密碼憑證對象的密碼
NSString *password = passwordCredential.password;
_appleIDInfoTextView.text = [NSString stringWithFormat:@"%@",passwordCredential];
} else {
}
}
//失敗的回調
-(void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) {
}
#pragma mark - ASAuthorizationControllerPresentationContextProviding
//告訴代理應該在哪個window 展示授權界面給用戶
-(ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)) {
return self.view.window;
}
已經Sign In with Apple登陸過app的用戶
1、如果設備中存在iCloud Keychain憑證或者AppleID憑證,提示用戶直接使用TouchID或FaceID登錄即可。
2、新增ASAuthorizationPasswordRequest,如果 KeyChain 里面有登錄信息的話,可以直接使用里面保存的用戶名和密碼進行登錄。
- (void)perfomExistingAccountSetupFlows {
if (@available(iOS 13.0, *)) {
// 授權請求依賴于用于的AppleID
ASAuthorizationAppleIDRequest *authAppleIDRequest = [[ASAuthorizationAppleIDProvider new] createRequest];
// 為了執行鑰匙串憑證分享生成請求的一種機制
ASAuthorizationPasswordRequest *passwordRequest = [[ASAuthorizationPasswordProvider new] createRequest];
NSMutableArray <ASAuthorizationRequest *> *mArr = [NSMutableArray arrayWithCapacity:2];
if (authAppleIDRequest) {
[mArr addObject:authAppleIDRequest];
}
if (passwordRequest) {
[mArr addObject:passwordRequest];
}
// ASAuthorizationRequest:對于不同種類授權請求的基類
NSArray <ASAuthorizationRequest *> *requests = [mArr copy];
// 由ASAuthorizationAppleIDProvider創建的授權請求 管理授權請求的控制器
ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:requests];
// 設置授權控制器通知授權請求的成功與失敗的代理
authorizationController.delegate = self;
// 設置提供 展示上下文的代理,在這個上下文中 系統可以展示授權界面給用戶
authorizationController.presentationContextProvider = self;
// 在控制器初始化期間啟動授權流
[authorizationController performRequests];
}
}
在 App 使用過程中,通過通知方法來監聽 revoked 狀態
- (void)observeAppleSignInState {
if (@available(iOS 13.0, *)) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(handleSignInWithAppleStateChanged:) name:ASAuthorizationAppleIDProviderCredentialRevokedNotification object:nil];
}
}
// 觀察SignInWithApple狀態改變
- (void)handleSignInWithAppleStateChanged:(id)noti {
}
程序啟動時,監聽授權狀態
用戶終止 App 中使用 Sign in with Apple 功能;
用戶在設置里注銷了 AppleId時
App 需要獲取到這些狀態,然后做退出登錄操作,或者重新登錄。
我們需要在 App 啟動的時候,通過 getCredentialState:completion: 來獲取當前用戶的授權狀態。
- (void)observeAuthticationState {
// 基于用戶的Apple ID 生成授權用戶請求的機制
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
// 注意 存儲用戶標識信息需要使用鑰匙串來存儲 這里使用NSUserDefaults 做的簡單示例
NSString *userIdentifier = [[NSUserDefaults standardUserDefaults] valueForKey:@"ShareCurrentIdentifier"];
if (userIdentifier) {
// 在回調中返回用戶的授權狀態
[appleIDProvider getCredentialStateForUserID:userIdentifier completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
// 蘋果證書的授權狀態
switch (credentialState) {
case ASAuthorizationAppleIDProviderCredentialRevoked:
// 蘋果授權憑證失效
dispatch_async(dispatch_get_main_queue(), ^{
//做對應處理
});
break;
case ASAuthorizationAppleIDProviderCredentialAuthorized:
// 蘋果授權憑證狀態良好
dispatch_async(dispatch_get_main_queue(), ^{
//做對應處理
});
break;
case ASAuthorizationAppleIDProviderCredentialNotFound:
// 未發現蘋果授權憑證
// 可以引導用戶重新登錄
dispatch_async(dispatch_get_main_queue(), ^{
//做對應處理
});
break;
default:
break;
}
}];
}
}
參考文章:
Sign In With Apple(一)
Sign In with Apple - 使用蘋果賬號登錄你的應用
iOS 13 適配
Sign in with Apple
iOS 13-Sign In with Apple