iOS开发iOS 三方分享登录推送

iOS 苹果第三方登录

2019-11-14  本文已影响0人  NanNan

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审核指南更新

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

// 如果存在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];
    }
}

  1. 获取授权码
    获取授权码需要在代码中实现两个代理回调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;
}

在授权登录成功回调中,我们可以拿到以下几类数据

  1. 验证
    关于验证的这一步,需要传递授权码给自己的服务端,自己的服务端调用苹果API去校验授权码Generate and validate tokens。如果验证成功,可以根据userIdentifier判断账号是否已存在,若存在,则返回自己账号系统的登录态,若不存在,则创建一个新的账号,并返回对应的登录状态给App

附:官方示例代码 Swift 版
附:What the Heck is Sign In with Apple?
附:苹果授权登陆后端验证
附:App Store审核指南的更新
附:Generate and validate tokens
附:SignInAppleDemo
附:我的博客地址

</article>

上一篇下一篇

猜你喜欢

热点阅读