iOS应用接入Sign In With Apple

iOS应用接入Sign In With Apple流程

  • 前言
  • 准备工作
  • 开始编写
  • 总结
  • 参考文献

前言

App Store审核要求:

New Guidelines for Sign in with Apple
We’ve updated the App Store Review Guidelines to provide criteria for when apps are required to use Sign in with Apple. Starting today, new apps submitted to the App Store must follow these guidelines. Existing apps and app updates must follow them by April 2020. We’ve also provided new guidelines for using Sign in with Apple on the web and other platforms.
September 12, 2019

所以已接入其它第三方登录的 App,必须提供Sign In with Apple 作为一种登录选择,否则审核无法通过,从2019-9-12开始提交到App Store的新应用必须遵循这些准则,现有的应用程序更新必须在2020年4月之前进行,参考App Store审核指南。

所以我上架应用时被拒绝了,就是因为应用中使用了微信登录却没有提供Sign In with Apple,在这里记录一下正确的流程。

准备工作

1.登录到Apple Developer 在应用的App ID Configuration 中打开Sign In With Apple开关。

2.返回Certificates, Identifiers & Profiles主屏幕,从侧面导航中选择Keys,选择Register a new key。

3.勾选Sign In With Apple后单击Configure按钮,选择需要的Primary App ID,保存之后,Apple将生成一个新的私钥,并仅提供一次下载,一定要保存此文件,因为以后你将无法再次将其取回!(需要将这个文件提供给公司后台)

4.到Xcode中项目的Signing&Capabilities中点击 +Capability 创建Sign In With Apple选项,并添加AuthenticationServices.framework

开始编写

1.导入系统头文件

#import 

2.添加Sign In with Apple登录按钮,系统提供了ASAuthorizationAppleIDButton,你可以直接使用这种按钮,但是要注意处理系统版本支持要在iOS 13及以上。

if (@available(iOS 13.0, *)) {
	ASAuthorizationAppleIDButton *appleIDBtn = [ASAuthorizationAppleIDButton buttonWithType:ASAuthorizationAppleIDButtonTypeDefault style:ASAuthorizationAppleIDButtonStyleWhite];
	appleIDBtn.frame = CGRectMake(30, 100, 200, 50);
	[appleIDBtn addTarget:self action:@selector(appleIDBtnClicked) forControlEvents:UIControlEventTouchUpInside];
	[self.view addSubview:appleIDBtn];
}

当然,你也可使用自定义的按钮来实现,但是自定义的苹果登录按钮要符合的要求,强烈建议公司设计详细阅读Apple的《人机交互准则》后给出设计界面。就因为自定义的按钮不符合这个准则,我又被拒了两次。

3.处理按钮点击事件,开始走请求流程,这里建议将登录事件封装并写成一个单例或者全局变量保证其生命周期,在项目的旧代码里所有的登录都耦合在了一个Xib创建的View里,写了600多行,这样的处理是极其恶心的。

// 授权处理
if (@available(iOS 13.0, *)) {
        ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
        ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];
        appleIDRequest.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
        ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest]];
        authorizationController.delegate = self;
        authorizationController.presentationContextProvider = self;
        [authorizationController performRequests];
}else{
	NSLog(@"该系统版本不可用Apple登录");
}

其中的requestedScopes如果你不需要用户的邮箱,就不需要写ASAuthorizationScopeEmail

appleIDRequest.requestedScopes = @[ASAuthorizationScopeFullName];

4.在代理方法中处理授权结果

#pragma mark - delegate
/// 授权成功回调
- (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 *familyName = appleIDCredential.fullName.familyName;
        NSString *givenName = appleIDCredential.fullName.givenName;
        NSString *email = appleIDCredential.email;
        // token
        NSData *identityToken = appleIDCredential.identityToken;
        // 用户唯一标识
        NSData *authorizationCode = appleIDCredential.authorizationCode;
        // 服务器验证需要使用的参数
        NSString *identityTokenStr = [[NSString alloc] initWithData:identityToken encoding:NSUTF8StringEncoding];
        NSString *authorizationCodeStr = [[NSString alloc] initWithData:authorizationCode encoding:NSUTF8StringEncoding];
        // 在这里处理向后台注册或登录事件,具体看项目后台的支持

    }else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]){
        // 这个获取的是iCloud记录的账号密码,需要输入框支持iOS 12 记录账号密码的新特性,如果不支持,可以忽略
        ASPasswordCredential *passwordCredential = authorization.credential;
        NSString *user = passwordCredential.user;
        NSString *password = passwordCredential.password;
        
    }else{
        NSLog(@"授权信息不符");
    }
}

/// 授权失败回调
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)){
    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;
    }
    NSLog(@"errorMsg = %@", errorMsg);
}

/// 设置展示内容给用户的Window
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){
    return [UIApplication sharedApplication].windows.lastObject;
}

5.向项目后台服务器验证登录,接受服务器的返回,再处理相应的事件即可。

总结

总体来说,Sign In With Apple 并不难以实现,它甚至比微信、QQ等三方登录容易实现。
遇到的问题主要集中在:“登录按钮的设计不规范问题””与项目后台的交互产生的各种错误和问题”。所以一定要让设计师在详细阅读人机交互规范,设计出符合App Store审核要求的代理按钮,可以参考已经上线的其他App。还要和项目后台负责人仔细沟通核对数据接口,联调解决问题,提供必要的文件。本人新手,如果有写错的地方欢迎指正,期待和大家一起交流开发。

参考文献

《What The Heck Is Sign In With Apple》
《iOS 13-Sign In with Apple》
《Human Interface Guidelines》
《App Store Review Guidelines》
《Sign In With Apple 从登陆到服务器验证》
《Sign in with Apple(object-c) 从开发者后台到服务端验证》

你可能感兴趣的:(iOS,Sign,In,With,Apple,ios)