在 WWDC 2019 上,苹果推出了自家的 Sign in with Apple 功能,这很 Apple。可能苹果看到第三方登录百家争鸣,琢磨着自己也搞了个,这对很多第三方登录来说可能是个威胁。

使用 Sign in with Apple 会更加方便、快捷、安全,苹果不会追踪用户在应用中的行为。所以,对于用户来说使用 Sign in with Apple 会更加安全。

另外,Sign in with Apple 支持跨平台

∙ Native SDK 支持 iOS/MacOS/watchOS/tvOS

∙ Javascript SDK 支持  Android, Windows, Web

话说这个 iOS 13 才支持的功能,我们有必要集成吗?

看了下面这句话,你或许就有答案了

Sign In with Apple will be available for beta testing this summer.It will be required as an option for users in apps thatsupport third-party sign-in when it is commercially available later this year.

简单来说,如果你的 App 没有提供第三方登录,那就不用集成。如果用到了第三方登录,那么需要提供 Sign in with Apple。

集成

一、后台设置

开启 Sign in with Apple 功能

1. 登录开发者网站,在需要添加 Sign in with Apple 功能的 Identifier 开启功能。

2. Xcode 里面 Signing & Capabilities 开启 Sign in with Apple 功能。

二、实现

1、苹果提供的按钮

官方提供了一个 ASAuthorizationAppleIDButton (继承自UIControl),使用这个来创建一个登录按钮。

ASAuthorizationAppleIDButton *loginBtn = [[ASAuthorizationAppleIDButton alloc]initWithAuthorizationButtonType:ASAuthorizationAppleIDButtonTypeSignIn authorizationButtonStyle:ASAuthorizationAppleIDButtonStyleWhite];[loginBtn addTarget:self action:@selector(signInWithApple) forControlEvents:UIControlEventTouchUpInside];loginBtn.center = self.view.center;loginBtn.bounds = CGRectMake(0, 0, 200, 40);[self.view addSubview:loginBtn];

这个按钮具有两种文案类型和三个样式,分别是:

typedef NS_ENUM(NSInteger, ASAuthorizationAppleIDButtonType) {ASAuthorizationAppleIDButtonTypeSignIn,ASAuthorizationAppleIDButtonTypeContinue,ASAuthorizationAppleIDButtonTypeDefault = ASAuthorizationAppleIDButtonTypeSignIn,
} typedef NS_ENUM(NSInteger, ASAuthorizationAppleIDButtonStyle) {ASAuthorizationAppleIDButtonStyleWhite,ASAuthorizationAppleIDButtonStyleWhiteOutline,ASAuthorizationAppleIDButtonStyleBlack,
} 

样式

从图上可以看出:

∙ Apple 提供的登录按钮有三种外观:白色,带有黑色轮廓线的白色和黑色。

∙ 文案有两种:Sign In with Apple 和 Continue with Apple。(具体使用哪个文案,根据自身业务需求来定)

另外,按钮宽高默认值为 {width:130, height:30}

对于 ASAuthorizationAppleIDButton 我们能够自定义的东西比较少,比如背景色不能更改,文案只有两种可选,并且值不能修改,可以调整的只有圆角cornerRadiussize 。

本地化:必要且重要的一点

2、Authorization 发起授权登录请求

#pragma mark- 点击登录
-(void)signInWithApple API_AVAILABLE(ios(13.0))
{ASAuthorizationAppleIDProvider *provider = [[ASAuthorizationAppleIDProvider alloc]init];ASAuthorizationAppleIDRequest * request = [provider createRequest];request.requestedScopes = @[ASAuthorizationScopeFullName,ASAuthorizationScopeEmail];ASAuthorizationController *vc= [[ASAuthorizationController alloc]initWithAuthorizationRequests:@[request]];vc.delegate = self;vc.presentationContextProvider = self;[vc performRequests];
}

ASAuthorizationAppleIDProvider 这个类比较简单,头文件中可以看出,主要用于创建一个 ASAuthorizationAppleIDRequest 以及获取对应 userID 的用户授权状态。在上面的方法中我们主要是用于创建一个 ASAuthorizationAppleIDRequest ,用户授权状态的获取后面会提到。

∙ 给创建的 request 设置 requestedScopes ,这是个 ASAuthorizationScope 数组,目前只有两个值,ASAuthorizationScopeFullName 和 ASAuthorizationScopeEmail,根据需求去设置即可。

∙ 然后,创建 ASAuthorizationController ,它是管理授权请求的控制器,给其设置 delegate 和 presentationContextProvider ,最后启动授权 performRequests 。

设置上下文

ASAuthorizationControllerPresentationContextProviding 就一个方法,主要是告诉 ASAuthorizationController 展示在哪个 window 上。

-(ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller
API_AVAILABLE(ios(13.0)){return  self.view.window;
}

3. Verification 授权

用户发起授权请求后,系统就会弹出用户登录验证的页面。

在用户没有同意授权之前或者取消授权之后,点击登录的时候,都会弹出上面这个界面,在这个授权页面,我们可以修改自己的用户名,以及可以选择共享我的电子邮箱或者隐藏邮件地址。这样一来,就可以达到隐藏自己真实信息的目的。

授权一次后,再次点击登录按钮,则会直接弹出下面这个窗口:

授权回调处理

下面是 ASAuthorizationControllerDelegate 方法,一个是授权成功的回调,一个是失败的回调。

#pragma mark- 授权成功的回调
-(void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization
API_AVAILABLE(ios(13.0)){if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {ASAuthorizationAppleIDCredential * credential = authorization.credential;NSString *state = credential.state;NSString * userID = credential.user;NSPersonNameComponents *fullName = credential.fullName;NSString * email = credential.email;//refresh tokenNSString * authorizationCode = [[NSString alloc]initWithData:credential.authorizationCode encoding:NSUTF8StringEncoding];// access tokenNSString * identityToken = [[NSString alloc]initWithData:credential.identityToken encoding:NSUTF8StringEncoding];ASUserDetectionStatus realUserStatus = credential.realUserStatus;NSLog(@"state: %@", state);NSLog(@"userID: %@", userID);NSLog(@"fullName: %@", fullName);NSLog(@"email: %@", email);NSLog(@"authorizationCode: %@", authorizationCode);NSLog(@"identityToken: %@", identityToken);NSLog(@"realUserStatus: %@", @(realUserStatus));}}#pragma mark- 授权失败的回调
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error
API_AVAILABLE(ios(13.0)){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;}}

当我们授权成功后,我们可以在 authorizationController:didCompleteWithAuthorization: 这个代理方法中获取到 ASAuthorizationAppleIDCredential ,通过这个可以拿到用户的 userIDemailfullNameauthorizationCodeidentityToken 以及 realUserStatus 等信息。

这些信息具体含义和用途:

∙ User ID: Unique, stable, team-scoped user ID,苹果用户唯一标识符,该值在同一个开发者账号下的所有 App 下是一样的,开发者可以用该唯一标识符与自己后台系统的账号体系绑定起来。

∙ Verification data: Identity token, code,验证数据,用于传给开发者后台服务器,然后开发者服务器再向苹果的身份验证服务端验证本次授权登录请求数据的有效性和真实性,详见 Sign In with Apple REST API。如果验证成功,可以根据 userIdentifier 判断账号是否已存在,若存在,则返回自己账号系统的登录态,若不存在,则创建一个新的账号,并返回对应的登录态给 App。

∙ Account information: Name, verified email,苹果用户信息,包括全名、邮箱等。

∙ Real user indicator: High confidence indicator that likely real user,用于判断当前登录的苹果账号是否是一个真实用户,取值有:unsupportedunknownlikelyReal

失败情况会走 authorizationController:didCompleteWithError: 这个方法,具体看代码吧。

5. Handling Changes

通过上面的步骤一个完整的授权,已经完成。BUT,我们还需要处理一些 Case。

∙ 用户终止 App 中使用 Sign in with Apple 功能

∙ 用户在设置里注销了 AppleId

这些情况下,App 需要获取到这些状态,然后做退出登录操作,或者重新登录。
我们需要在 App 启动的时候,通过 getCredentialState:completion: 来获取当前用户的授权状态。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {if (@available(iOS 13.0, *)) {NSString *userIdentifier = 钥匙串中取出的 userIdentifier;if (userIdentifier) {ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];[appleIDProvider getCredentialStateForUserID:userIdentifiercompletion:^(ASAuthorizationAppleIDProviderCredentialState credentialState,NSError * _Nullable error){switch (credentialState) {case ASAuthorizationAppleIDProviderCredentialAuthorized:// The Apple ID credential is validbreak;case ASAuthorizationAppleIDProviderCredentialRevoked:// Apple ID Credential revoked, handle unlinkbreak;case ASAuthorizationAppleIDProviderCredentialNotFound:// Credential not found, show login UIbreak;}}];}}return YES;
}

ASAuthorizationAppleIDProviderCredentialState 解析如下:

ASAuthorizationAppleIDProviderCredentialAuthorized 授权状态有效;∙ASAuthorizationAppleIDProviderCredentialRevoked 上次使用苹果账号登录的凭据已被移除,需解除绑定并重新引导用户使用苹果登录;

ASAuthorizationAppleIDProviderCredentialNotFound 未登录授权,直接弹出登录页面,引导用户登录。

另外,在 App 使用过程中,你还可以通过通知方法来监听 revoked 状态,可以添加 ASAuthorizationAppleIDProviderCredentialRevokedNotification 这个通知,收到这个通知的时候,我们可以:

∙ Sign user out on this device

∙ Guide to sign in again

具体怎么添加和处理,可以根据业务需求来决定。

- (void)observeAppleSignInState
{if (@available(iOS 13.0, *)) {[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(handleSignInWithAppleStateChanged:)name:ASAuthorizationAppleIDProviderCredentialRevokedNotificationobject:nil];}
}- (void)handleSignInWithAppleStateChanged:(NSNotification *)notification
{// Sign the user out, optionally guide them to sign in againNSLog(@"%@", notification.userInfo);
}

One more thing
除此之外,苹果还把 iCloud KeyChain password 集成到了这套 API 里,我们在使用的时候,只需要在创建 request 的时候,多创建一个 ASAuthorizationPasswordRequest,这样如果 KeyChain 里面也有登录信息的话,可以直接使用里面保存的用户名和密码进行登录。代码如下:

- (void)perfomExistingAccountSetupFlows API_AVAILABLE(ios(13.0))
{ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];ASAuthorizationAppleIDRequest *authAppleIDRequest = [appleIDProvider createRequest];ASAuthorizationPasswordRequest *passwordRequest = [[ASAuthorizationPasswordProvider new] createRequest];NSMutableArray <ASAuthorizationRequest *>* array = [NSMutableArray arrayWithCapacity:2];if (authAppleIDRequest) {[array addObject:authAppleIDRequest];}if (passwordRequest) {[array addObject:passwordRequest];}NSArray <ASAuthorizationRequest *>* requests = [array copy];ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:requests];authorizationController.delegate = self;authorizationController.presentationContextProvider = self;[authorizationController performRequests];
}#pragma mark - ASAuthorizationControllerDelegate- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0))
{if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {ASPasswordCredential *passwordCredential = authorization.credential;NSString *userIdentifier = passwordCredential.user;NSString *password = passwordCredential.password;NSLog(@"userIdentifier: %@", userIdentifier);NSLog(@"password: %@", password);}
}

Sign in with Apple (通过Apple 登录)相关推荐

  1. apple帐号登录服务器端接入

    新博客地址(shankusu.me) 原文转载自 http://cwqqq.com/2020/09/27/apple_login_api_server_side apple帐号登录服务器端接入 最近有 ...

  2. 苹果apple账号授权登录第三方APP

    Apple官方文档 前言:由于公司最近有个业务需求是要进行Apple账号授权登录,于是我看边看文档边借鉴其他人的写法,发现好多文章都有一个共性,一个是在解析JWT的时候自己设置参数后进行判断,这样做没 ...

  3. [Apple]通过Apple ID登录App时提示“共享”和“隐藏”邮件地址的问题

    [Apple]通过Apple ID登录App时提示"共享"和"隐藏"邮件地址的问题 点击此处跳转 希望对您有所帮助.

  4. JAVA集成apple授权认证登录【后端认证授权】

    1.需求描述 APP需要提交苹果的App Store审核时,因为集成了微信授权登录,导致审核失败了,审核失败的理由是:集成了第三方授权的APP,也需要集成Apple授权认证,不然审核通过不了,强制捆绑 ...

  5. Apple?apple!

    Apple?apple! 今天是day1 通过使用Codingstartup的TriggerJs 先跟着Steven实现了Iphone13的开场推送 无意间找到了Steven老师的页面制作 感觉收益颇 ...

  6. 关于Sign in with Apple (Apple 登录) PHP的后端验证

    1. 首先阅读官网文档 https://developer.apple.com/documentation/signinwithapplerestapi 重点讲解苹果授权登陆 后端PHP如何验证 1. ...

  7. apple oauth 三方登录

    网站需要使用apple 三方登录,研究了一下,记录如下: 目录 配置 正式开发(oauth2.0) 1.登录授权页面 2.接收授权码code,向apple服务器申请token 配置 我们拥有一个苹果开 ...

  8. ios 自架验证服务器,iOS 13-Sign In with Apple(苹果登录)APP+后端验证

    关于Sign In with Apple的介绍就不讲了,直接进入正题吧! Certificates,IDs & Profiels->Keys->+号 1585892549402.j ...

  9. 解决iOS6 Apple ID无法登录!十年了,爷青回!还是那个iPhone 4s,竟然能登陆成功!

    iPhone 4s IOS 6.1.3 iPhone 4s 如何用户登录 前言 登录App Store 总结 前言 今年是2021年,十年前的今天,iPhone 4s发售,如今10年过去,ios系统已 ...

最新文章

  1. find指定具体时间参数-newermt
  2. 关于集体生活和个人生活的思考
  3. 使用Dynamic LINQ创建高级查询服务
  4. B. Box Fitting
  5. 剑桥女博士创立情绪识别 AI 公司,帮助自闭症患者理解他人表情
  6. 黄聪:C#中用ILMerge将所有引用的DLL和exe文件打成一个exe文件,有图解
  7. dns缓存时间 linux,如何在Linux服务器上刷新DNS缓存
  8. 暑期训练第四次团队赛
  9. 电子设计自动化实验 实验三 频率计制作
  10. 微信公众平台测试号申请、使用HBuilder X与微信开发者工具实现授权登陆功能以及单点登录
  11. 林中鸟计算机弹奏,用现象证实现象这叫复试,计算机的计算只是计算,与经络的现象无关。气感循行...
  12. CSAPP:BombLab 详细解析
  13. 差分与反差分计算(MATLAB)
  14. bem css_CSS体系结构:块元素修饰符(BEM)和原子CSS
  15. 程序员最爱用的在线代码编辑器合集,哪款是你的最爱?
  16. 名帖33 赵孟頫 隶书《千字文》
  17. Linux下GUI开发:GTK+ 2.0 + anjuta + glade
  18. Retrofit+OKHttp+RxJava的使用
  19. 综述|领略目标检测的前世今生
  20. caxa工程知识管理服务器配置信息怎么填,CAXA CAPP教程:如何使用知识库填写卡片...

热门文章

  1. 插入缺失InDel insertion deletion
  2. 数据、源代码防泄密解决方案
  3. Java必知必会的问题
  4. c语言满屏爱心,微信聊天可以发满屏动态爱心了 个性又浪漫!
  5. JVM调优参数大全及G1GC调优
  6. 用计算机丢失ZLB1,LJ-ZLB1预应力智能张拉控制系统
  7. 如何压缩GIF/GIF压缩软件教程方法全面解析
  8. portknocking(端口试探)简介
  9. 算法分析:大O符号/大Ω符号/大Θ符号/小o符号/小w符号
  10. 你不可不知的《哈利波特》秘密(二)