Sign In With Apple總結

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;
            }
            
        }];
    }
}

官網swift版demo和改編的OC版

參考文章:

Sign In With Apple(一)
Sign In with Apple - 使用蘋果賬號登錄你的應用
iOS 13 適配
Sign in with Apple
iOS 13-Sign In with Apple

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容