公司項(xiàng)目需要接入sign in with Apple,花了幾天時(shí)間疮茄,查看各種文檔博客,最終完成接入根暑。
客戶端接入遇到的一些問題
1.首次登錄時(shí)調(diào)用的代碼:
if (@available(iOS 13.0, *)) {
// 基于用戶的Apple ID授權(quán)用戶力试,生成用戶授權(quán)請(qǐng)求的一種機(jī)制
ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
// 創(chuàng)建新的AppleID 授權(quán)請(qǐng)求
ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];
// 在用戶授權(quán)期間請(qǐng)求的聯(lián)系信息
appleIDRequest.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
// 由ASAuthorizationAppleIDProvider創(chuàng)建的授權(quán)請(qǐng)求 管理授權(quán)請(qǐng)求的控制器
ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest]];
// 設(shè)置授權(quán)控制器通知授權(quán)請(qǐng)求的成功與失敗的代理
authorizationController.delegate = self;
// 設(shè)置提供 展示上下文的代理,在這個(gè)上下文中 系統(tǒng)可以展示授權(quán)界面給用戶
authorizationController.presentationContextProvider = self;
// 在控制器初始化期間啟動(dòng)授權(quán)流
[authorizationController performRequests];
}else{
// 處理不支持系統(tǒng)版本
NSLog(@"該系統(tǒng)版本不可用Apple登錄");
}
2.已經(jīng)授權(quán)過排嫌,再次登錄的時(shí)候畸裳,如果你已經(jīng)開啟了Touch id或者Face ID,直接使用Touch id或者Face ID登錄淳地,沒有開啟的話怖糊,使用密碼登錄,sign in Apple沒有自動(dòng)登錄接口薇芝,如果自己項(xiàng)目中需要自動(dòng)登錄功能蓬抄,不考慮服務(wù)器驗(yàn)證的情況下,可以使用自己的pid和token登錄夯到,但是這會(huì)有一定的安全性嚷缭,具體代碼如下:
if (@available(iOS 13.0, *)) {
// 基于用戶的Apple ID授權(quán)用戶,生成用戶授權(quán)請(qǐng)求的一種機(jī)制
ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
// 授權(quán)請(qǐng)求AppleID
ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];
// 為了執(zhí)行鑰匙串憑證分享生成請(qǐng)求的一種機(jī)制
ASAuthorizationPasswordProvider *passwordProvider = [[ASAuthorizationPasswordProvider alloc] init];
ASAuthorizationPasswordRequest *passwordRequest = [passwordProvider createRequest];
// 由ASAuthorizationAppleIDProvider創(chuàng)建的授權(quán)請(qǐng)求 管理授權(quán)請(qǐng)求的控制器
ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest, passwordRequest]];
// 設(shè)置授權(quán)控制器通知授權(quán)請(qǐng)求的成功與失敗的代理
authorizationController.delegate = self;
// 設(shè)置提供 展示上下文的代理耍贾,在這個(gè)上下文中 系統(tǒng)可以展示授權(quán)界面給用戶
authorizationController.presentationContextProvider = self;
// 在控制器初始化期間啟動(dòng)授權(quán)流
[authorizationController performRequests];
}else{
// 處理不支持系統(tǒng)版本
NSLog(@"該系統(tǒng)版本不可用Apple登錄");
}
3.sign in Apple登錄授權(quán)成功回調(diào)的代碼阅爽,值得注意的是familyName ,givenName 荐开,email 只有第一次登錄的時(shí)候才有值付翁,再次登錄返回都是空值;ASPasswordCredential 回調(diào)我是一直測(cè)試不出來晃听,目前不知道怎樣登錄才能收到ASPasswordCredential 的回調(diào)百侧,具體代碼如下:
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)){
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
NSString *user = appleIDCredential.user;
NSString *state = appleIDCredential.state;
// 使用過授權(quán)的砰识,可能獲取不到以下三個(gè)參數(shù)
NSString *familyName = appleIDCredential.fullName.familyName;
NSString *givenName = appleIDCredential.fullName.givenName;
NSString *email = appleIDCredential.email;
ASUserDetectionStatus realUserStatus = appleIDCredential.realUserStatus;
NSLog(@"familyName=%@", familyName);
NSLog(@"givenName=%@", givenName);
NSLog(@"email=%@", email);
NSLog(@"state=%@", state);
NSLog(@"user=%@", user);
if (user) {
[AppleKeychain save:KEYCHAIN_IDENTIFIER(@"userIdentifier") data:user];
}
NSLog(@"realUserStatus=%ld", (long)realUserStatus);
NSData *identityToken = appleIDCredential.identityToken;
NSData *authorizationCode = appleIDCredential.authorizationCode;
// 服務(wù)器驗(yàn)證需要使用的參數(shù)
NSString *identityTokenStr = [[NSString alloc] initWithData:identityToken encoding:NSUTF8StringEncoding];
NSString *authorizationCodeStr = [[NSString alloc] initWithData:authorizationCode encoding:NSUTF8StringEncoding];
NSLog(@"%@\n\n%@", identityTokenStr, authorizationCodeStr);
if (identityTokenStr&&authorizationCodeStr) {
[self doLoginVerify:identityTokenStr AndCode:authorizationCodeStr];
}
}else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]){
// 這個(gè)獲取的是iCloud記錄的賬號(hào)密碼,需要輸入框支持iOS 12 記錄賬號(hào)密碼的新特性
//這個(gè)回調(diào)我是沒有測(cè)試出來過佣渴,不知道怎么搞
// Sign in using an existing iCloud Keychain credential.
// 用戶登錄使用現(xiàn)有的密碼憑證
NSLog(@"Sign in using an existing iCloud Keychain credential");
ASPasswordCredential *passwordCredential = authorization.credential;
// 密碼憑證對(duì)象的用戶標(biāo)識(shí) 用戶的唯一標(biāo)識(shí)
NSString *user = passwordCredential.user;
// 密碼憑證對(duì)象的密碼
NSString *password = passwordCredential.password;
NSLog(@"user=%@", user);
NSLog(@"password=%@", password);
}else{
NSLog(@"授權(quán)信息均不符");
}
}
4.蘋果登錄觀察授權(quán)狀態(tài)監(jiān)聽辫狼,如果你切換一個(gè)新的Apple id或者停止使用Apple id,那么回調(diào)的結(jié)果是不一樣的辛润,根據(jù)自己項(xiàng)目做處理膨处,正常情況,你只要使用sign in Apple登錄過一次砂竖,那么下次再登錄的時(shí)候真椿,回調(diào)都是授權(quán)狀態(tài)良好,具體代碼如下:
if (@available(iOS 13.0, *)) {
// A mechanism for generating requests to authenticate users based on their Apple ID.
// 基于用戶的Apple ID 生成授權(quán)用戶請(qǐng)求的機(jī)制
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
// 注意 存儲(chǔ)用戶標(biāo)識(shí)信息需要使用鑰匙串來存儲(chǔ) 這里筆者簡(jiǎn)單期間 使用NSUserDefaults 做的簡(jiǎn)單示例
NSString *userIdentifier = [AppleKeychain load:KEYCHAIN_IDENTIFIER(@"userIdentifier")];
NMGLog(@"observeAuthticationState----:%@",userIdentifier);
if (userIdentifier) {
NSString* __block errorMsg = nil;
//Returns the credential state for the given user in a completion handler.
// 在回調(diào)中返回用戶的授權(quán)狀態(tài)
[appleIDProvider getCredentialStateForUserID:userIdentifier completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
switch (credentialState) {
// 蘋果證書的授權(quán)狀態(tài)
case ASAuthorizationAppleIDProviderCredentialRevoked:
// 蘋果授權(quán)憑證失效
errorMsg = @"蘋果授權(quán)憑證失效";
[self logout];
break;
case ASAuthorizationAppleIDProviderCredentialAuthorized:
// 蘋果授權(quán)憑證狀態(tài)良好
errorMsg = @"蘋果授權(quán)憑證狀態(tài)良好";
break;
case ASAuthorizationAppleIDProviderCredentialNotFound:
// 未發(fā)現(xiàn)蘋果授權(quán)憑證
errorMsg = @"未發(fā)現(xiàn)蘋果授權(quán)憑證";
[self logout];
break;
// 可以引導(dǎo)用戶重新登錄
case ASAuthorizationAppleIDProviderCredentialTransferred:
errorMsg = @"蘋果授權(quán)信息變動(dòng)";
break;
}
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"SignInWithApple授權(quán)狀態(tài)變化情況");
NSLog(@"%@", errorMsg);
});
}];
}
}
5.能不能自定義sign in Apple按鈕這個(gè)問題乎澄,我們也發(fā)郵件去咨詢了蘋果公司突硝,回復(fù)的是:you best to use the familiar buttons that Apple provides for Sign in with Apple,但是最終我們沒有使用系統(tǒng)自帶的ASAuthorizationAppleIDButton 置济,而是按照設(shè)計(jì)規(guī)范自己設(shè)計(jì)按鈕狞换。目前無法確定是否可以提審成功。
一些參考文檔:
https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/
https://developer.apple.com/documentation/signinwithapplerestapi/authenticating_users_with_sign_in_with_apple#see-also