iOS 13-Sign In with Apple


最近了解了iOS 13新增功能之Sign In with AppleSign In with Apple是跨平台的,可以支持iOS、macOS、watchOS、tvOS、JS。本文主要內容為Sign In with AppleiOS上的基礎使用。詳情參考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審核指南更新

 

開發Sign In with Apple的注意事項

需要在蘋果后台打開該選項,並且重新生成Profiles配置文件,並安裝到Xcode,如下圖

iOS使用Sign In with AppleXcode的准備工作
Xcode11 Signing & Capabilities中添加Sign In With Apple,如下圖

  • iOS Sign In with Apple流程

1、添加 Sign In with Apple 登錄按鈕,設置 ASAuthorizationAppleIDButton 相關布局,並添加按鈕點擊響應事件
2、獲取授權碼
3、驗證

 

1、添加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(@"////////");
    
    if (@available(iOS 13.0, *)) {
        // 基於用戶的Apple ID授權用戶,生成用戶授權請求的一種機制
        ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
        // 創建新的AppleID 授權請求
        ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];
        // 在用戶授權期間請求的聯系信息
        appleIDRequest.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
        // 由ASAuthorizationAppleIDProvider創建的授權請求 管理授權請求的控制器
        ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest]];
        // 設置授權控制器通知授權請求的成功與失敗的代理
        authorizationController.delegate = self;
        // 設置提供 展示上下文的代理,在這個上下文中 系統可以展示授權界面給用戶
        authorizationController.presentationContextProvider = self;
        // 在控制器初始化期間啟動授權流
        [authorizationController performRequests];
    }
}
  • 已經使用Sign In with Apple登錄過app的用戶
    如果設備中存在iCloud Keychain憑證或者AppleID憑證,提示用戶直接使用TouchIDFaceID登錄即可,代碼如下
// 如果存在iCloud Keychain 憑證或者AppleID 憑證提示用戶
- (void)perfomExistingAccountSetupFlows{
    NSLog(@"///已經認證過了/////");
    
    if (@available(iOS 13.0, *)) {
        // 基於用戶的Apple ID授權用戶,生成用戶授權請求的一種機制
        ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
        // 授權請求AppleID
        ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];
        // 為了執行鑰匙串憑證分享生成請求的一種機制
        ASAuthorizationPasswordProvider *passwordProvider = [[ASAuthorizationPasswordProvider alloc] init];
        ASAuthorizationPasswordRequest *passwordRequest = [passwordProvider createRequest];
        // 由ASAuthorizationAppleIDProvider創建的授權請求 管理授權請求的控制器
        ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest, passwordRequest]];
        // 設置授權控制器通知授權請求的成功與失敗的代理
        authorizationController.delegate = self;
        // 設置提供 展示上下文的代理,在這個上下文中 系統可以展示授權界面給用戶
        authorizationController.presentationContextProvider = self;
        // 在控制器初始化期間啟動授權流
        [authorizationController performRequests];
    }
}

 

2、獲取授權碼
獲取授權碼需要在代碼中實現兩個代理回調ASAuthorizationControllerDelegate、ASAuthorizationControllerPresentationContextProviding分別用於處理授權登錄成功和失敗、以及提供用於展示授權頁面的Window,代碼如下

#pragma mark - delegate
//@optional 授權成功地回調
- (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.
        // 用戶登錄使用現有的密碼憑證
        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;
    }
}

// 授權失敗的回調
- (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 展示內容給用戶
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller{
    NSLog(@"88888888888");
    // 返回window
    return self.view.window;
}

 

在授權登錄成功回調中,我們可以拿到以下幾類數據

  • UserID:Unique, stable, team-scoped user ID,蘋果用戶唯一標識符,該值在同一個開發者賬號下的所有App下是一樣的,開發者可以用該唯一標識符與自己后台系統的賬號體系綁定起來(這與國內的微信、QQ、微博等第三方登錄流程基本一致)
  • Verification data:Identity token, code,驗證數據,用於傳給開發者后台服務器,然后開發者服務器再向蘋果的身份驗證服務端驗證,本次授權登錄請求數據的有效性和真實性,詳見Sign In with Apple REST API
  • Account information:Name, verified email,蘋果用戶信息,包括全名、郵箱等,注意:如果玩家登錄時拒絕提供真實的郵箱賬號,蘋果會生成虛擬的郵箱賬號

 

3、驗證
關於驗證的這一步,需要傳遞授權碼給自己的服務端,自己的服務端調用蘋果API去校驗授權碼Generate and validate tokens。如果驗證成功,可以根據userIdentifier判斷賬號是否已存在,若存在,則返回自己賬號系統的登錄態,若不存在,則創建一個新的賬號,並返回對應的登錄狀態給App

 

附:官方示例代碼 Swift 版
附:What the Heck is Sign In with Apple?
附:蘋果授權登陸后端驗證
附:App Store審核指南的更新
附:Generate and validate tokens
附:SignInAppleDemo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM