iOS13 sign in with Apple客户端接入遇到的一些问题

公司项目需要接入sign in with Apple,花了几天时间,查看各种文档博客,最终完成接入。
客户端接入遇到的一些问题
1.首次登录时调用的代码:

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];
    }else{
        // 处理不支持系统版本
        NSLog(@"该系统版本不可用Apple登录");
    }

2.已经授权过,再次登录的时候,如果你已经开启了Touch id或者Face ID,直接使用Touch id或者Face ID登录,没有开启的话,使用密码登录,sign in Apple没有自动登录接口,如果自己项目中需要自动登录功能,不考虑服务器验证的情况下,可以使用自己的pid和token登录,但是这会有一定的安全性,具体代码如下:

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];
        
    }else{
        // 处理不支持系统版本
        NSLog(@"该系统版本不可用Apple登录");
    }

3.sign in Apple登录授权成功回调的代码,值得注意的是familyName ,givenName ,email 只有第一次登录的时候才有值,再次登录返回都是空值;ASPasswordCredential 回调我是一直测试不出来,目前不知道怎样登录才能收到ASPasswordCredential 的回调,具体代码如下:

- (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;
        // 使用过授权的,可能获取不到以下三个参数
        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;
        
        // 服务器验证需要使用的参数
        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]]){
        // 这个获取的是iCloud记录的账号密码,需要输入框支持iOS 12 记录账号密码的新特性
        //这个回调我是没有测试出来过,不知道怎么搞
        // Sign in using an existing iCloud Keychain credential.
        // 用户登录使用现有的密码凭证
        NSLog(@"Sign in using an existing iCloud Keychain credential");
        ASPasswordCredential *passwordCredential = authorization.credential;
        // 密码凭证对象的用户标识 用户的唯一标识
        NSString *user = passwordCredential.user;
        // 密码凭证对象的密码
        NSString *password = passwordCredential.password;
        NSLog(@"user=%@", user);
        NSLog(@"password=%@", password);
    }else{
        NSLog(@"授权信息均不符");
        
    }
}

4.苹果登录观察授权状态监听,如果你切换一个新的Apple id或者停止使用Apple id,那么回调的结果是不一样的,根据自己项目做处理,正常情况,你只要使用sign in Apple登录过一次,那么下次再登录的时候,回调都是授权状态良好,具体代码如下:

 if (@available(iOS 13.0, *)) {
        // A mechanism for generating requests to authenticate users based on their Apple ID.
        // 基于用户的Apple ID 生成授权用户请求的机制
        ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
        // 注意 存储用户标识信息需要使用钥匙串来存储 这里笔者简单期间 使用NSUserDefaults 做的简单示例
        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.
            // 在回调中返回用户的授权状态
            [appleIDProvider getCredentialStateForUserID:userIdentifier completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
                switch (credentialState) {
                        // 苹果证书的授权状态
                    case ASAuthorizationAppleIDProviderCredentialRevoked:
                        // 苹果授权凭证失效
                        errorMsg = @"苹果授权凭证失效";
                        [self logout];
                        break;
                    case ASAuthorizationAppleIDProviderCredentialAuthorized:
                        // 苹果授权凭证状态良好
                        errorMsg = @"苹果授权凭证状态良好";
                        break;
                    case ASAuthorizationAppleIDProviderCredentialNotFound:
                        // 未发现苹果授权凭证
                        errorMsg = @"未发现苹果授权凭证";
                        [self logout];
                        break;
                        // 可以引导用户重新登录
                    case ASAuthorizationAppleIDProviderCredentialTransferred:
                        errorMsg = @"苹果授权信息变动";
                        break;
                }
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSLog(@"SignInWithApple授权状态变化情况");
                    NSLog(@"%@", errorMsg);
                });
            }];
            
        }
    }

5.能不能自定义sign in Apple按钮这个问题,我们也发邮件去咨询了苹果公司,回复的是:you best to use the familiar buttons that Apple provides for Sign in with Apple,但是最终我们没有使用系统自带的ASAuthorizationAppleIDButton ,而是按照设计规范自己设计按钮。目前无法确定是否可以提审成功。
一些参考文档:
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章