iOS开发:使用 Sign In With Apple(登录)用法以及注意事项
一、为什么要使用Sign in with Apple?
苹果在19年 9 月12 号更新了审核指南,加入 4.8 Sign in with Apple 一条,要求所有使用第三方登录 的 App,都必须接入 Sign in with Apple。已经上架的 App 需在 2020 年 4 月 前完成接入工作,新上架 App(如果支持三方登录)必须接入Sign in with Apple,否则将被拒。
二、如何接入Sign In With Apple ?
1、前期准备
(1)、系统配置:苹果开发文档明确规定:苹果电脑系统macos(10.15)(吓的我赶紧升级我的笔记本系统),手机iOS系统ios(13.0)(毫不犹豫的升级)。由于只有Xcode11才支持Sign In With Apple接入代码的开发,所以Xcode我升级到了11.1正式版。
(2)、证书配置
登录开发者中心,在需要启用 Sign in with Apple 的 Apple ID中勾选 Sign in with Apple.
具体步骤如下图
登录苹果开发者中心,选择Account
选择 Identifiers 这边可以看到自己工程的 Bundle Identifier点进去勾选 Sign in with Apple 若没有添加一个
注意:
描述信息最好使用 XC + Bundle ID
勾选 Sign in with Apple
(3)、工程配置
新建工程,选择项目 TARGETS -> Signing&Capabilities ,单击下图中的 3:Capability:
在弹出框中搜索找到 Sign in with Apple:双击添加
这些完成后,我们就可以在项目中添加代码了。
2、添加代码
(1)、在需要使用 login with Apple 的地方,引入头文件:
#import <AuthenticationServices/AuthenticationServices.h>
首先,我们需要一个登录按钮,系统为我们预设了一个固定样式登录按钮ASAuthorizationAppleIDButton,我们可以直接使用。
if (@available(iOS 13.0, *)) {ASAuthorizationAppleIDButton *appleIDButton = [ASAuthorizationAppleIDButton new];appleIDButton.frame = CGRectMake(.0, .0, CGRectGetWidth(self.view.frame) - 40.0, 100.0);CGPoint origin = CGPointMake(20.0, CGRectGetMidY(self.view.frame));CGRect frame = appleIDButton.frame;frame.origin = origin;appleIDButton.frame = frame;appleIDButton.cornerRadius = CGRectGetHeight(appleIDButton.frame) * 0.25;[self.view addSubview:appleIDButton];[appleIDButton addTarget:self action:@selector(handleAuthrization:) forControlEvents:UIControlEventTouchUpInside];}
通过参数 type、style可以设置为不同样式的按钮;当然,我们也可以自定义,但是要遵循苹果的相关设计规范,详见 Human Interface Guidelines
(2)、我们还需要用到两个协议
// 提供关于授权请求结果信息的接口
ASAuthorizationControllerDelegate,
// 控制器的代理找一个展示授权控制器的上下文的接口
ASAuthorizationControllerPresentationContextProviding>
协议的方法
#pragma mark - ASAuthorizationControllerDelegate// 授权成功地回调
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0));// 授权失败的回调
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0));#pragma mark - ASAuthorizationControllerPresentationContextProviding/*! @brief 返回弹出请求视图的window** @param ASPresentationAnchor 为 UIWindow 的别名* @param controller 管理授权请求的控制器* return 弹出请求视图的window*/
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0));
以及 3个类
//主要作用是用创建相应的请求,查询用户授权状态
ASAuthorizationAppleIDProvider// 授权请求,可以设置具体的请求信息
ASAuthorizationAppleIDRequest// 发送请求控制器,可以设置相应的协议
ASAuthorizationController
首先在程序运行时会执行perfomExistingAccountSetupFlows 来判断如果存在iCloud Keychain 凭证或者AppleID 凭证提示用户
#pragma mark - 如果存在iCloud Keychain 凭证或者AppleID 凭证提示用户- (void)perfomExistingAccountSetupFlows {if (@available(iOS 13.0, *)) {// 基于用户的Apple ID授权用户,生成用户授权请求的一种机制ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];// 授权请求依赖于用于的AppleIDASAuthorizationAppleIDRequest *authAppleIDRequest = [appleIDProvider createRequest];// 为了执行钥匙串凭证分享生成请求的一种机制ASAuthorizationPasswordRequest *passwordRequest = [[ASAuthorizationPasswordProvider new] createRequest];NSMutableArray <ASAuthorizationRequest *>* mArr = [NSMutableArray arrayWithCapacity:2];if (authAppleIDRequest) {[mArr addObject:authAppleIDRequest];}if (passwordRequest) {[mArr addObject:passwordRequest];}// ASAuthorizationRequest:对于不同种类授权请求的基类NSArray <ASAuthorizationRequest *>* requests = [mArr copy];// ASAuthorizationController是由ASAuthorizationAppleIDProvider创建的授权请求 管理授权请求的控制器ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:requests];// 设置授权控制器通知授权请求的成功与失败的代理authorizationController.delegate = self;// 设置提供 展示上下文的代理,在这个上下文中 系统可以展示授权界面给用户authorizationController.presentationContextProvider = self;// 在控制器初始化期间启动授权流[authorizationController performRequests];}
}
通过点击按钮ASAuthorizationAppleIDButton 响应事件添加代理再执行相应的代理方法
#pragma mark - 点击授权按钮- (void)handleAuthrization:(UIButton *)sender {if (@available(iOS 13.0, *)) {// 基于用户的Apple ID授权用户,生成用户授权请求的一种机制ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];// 创建新的AppleID 授权请求ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;// 在用户授权期间请求的联系信息request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];// 由ASAuthorizationAppleIDProvider创建的授权请求 管理授权请求的控制器ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];// 设置授权控制器通知授权请求的成功与失败的代理controller.delegate = self;// 设置提供 展示上下文的代理,在这个上下文中 系统可以展示授权界面给用户controller.presentationContextProvider = self;// 在控制器初始化期间启动授权流[controller performRequests];}
}
#pragma mark - 授权成功地回调- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)) {NSLog(@"%s", __FUNCTION__);NSLog(@"%@", controller);NSLog(@"%@", authorization);NSLog(@"authorization.credential:%@", authorization.credential);NSMutableString *mutableString = [NSMutableString string];mutableString = [self.appleIDInfoTextView.text mutableCopy];if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {// 用户登录使用ASAuthorizationAppleIDCredentialASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;NSString *user = appleIDCredential.user;// 使用钥匙串的方式保存用户的唯一信息NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;[SAMKeychain setPassword:user forService:bundleId account:ShareCurrentIdentifier];[mutableString appendString:user?:@""];NSString *familyName = appleIDCredential.fullName.familyName;[mutableString appendString:familyName?:@""];NSString *givenName = appleIDCredential.fullName.givenName;[mutableString appendString:givenName?:@""];NSString *email = appleIDCredential.email;[mutableString appendString:email?:@""];NSLog(@"mStr:%@", mutableString);[mutableString appendString:@"\n"];self.appleIDInfoTextView.text = mutableString;} else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {// 用户登录使用现有的密码凭证ASPasswordCredential *passwordCredential = authorization.credential;// 密码凭证对象的用户标识 用户的唯一标识NSString *user = passwordCredential.user;// 密码凭证对象的密码NSString *password = passwordCredential.password;[mutableString appendString:user?:@""];[mutableString appendString:password?:@""];[mutableString appendString:@"\n"];NSLog(@"mStr:%@", mutableString);self.appleIDInfoTextView.text = mutableString;} else {NSLog(@"授权信息均不符");mutableString = [@"授权信息均不符" mutableCopy];self.appleIDInfoTextView.text = mutableString;}
}
#pragma mark - 授权失败的回调- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)) {NSLog(@"%s", __FUNCTION__);NSLog(@"错误信息:%@", 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;}NSMutableString *mStr = [self.appleIDInfoTextView.text mutableCopy];[mStr appendString:errorMsg];[mStr appendString:@"\n"];self.appleIDInfoTextView.text = [mStr copy];if (errorMsg) {return;}if (error.localizedDescription) {NSMutableString *mStr = [self.appleIDInfoTextView.text mutableCopy];[mStr appendString:error.localizedDescription];[mStr appendString:@"\n"];self.appleIDInfoTextView.text = [mStr copy];}NSLog(@"controller requests:%@", controller.authorizationRequests);
}
#pragma mark - 告诉代理应该在哪个window 展示内容给用户- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){NSLog(@"调用展示window方法:%s", __FUNCTION__);// 返回windowreturn self.view.window;
}
点击按钮ASAuthorizationAppleIDButton 登录后,如果是未授权会弹出如下弹框:
这里的邮件地址,用户可以选择共享或者隐藏,如果选择了隐藏,开发者将会获得一个苹果自动生成的一个邮箱地址,而不是用户的真实邮箱;成功后返回的信息如下:
user: 001963.27e48e27b0e5853a7c5d744d9a1c5432.0701familyName: XX
givenName: XX
email: 你的邮箱
我们可以将 user 信息保存到钥匙串中,这里我用的是一个开源的第三方库
SAMKeychain
如果我们已经授权登录成功,再次登录的时候,就会显示如下的页面:
我们再次读取时只会返回user的信息
登录成功后,用户是可以随时取消授权的,或者用户将 AppleID退出了当前设备,都需要重新获取。我们可以在应用启动的时候使用下面的方法来检测用户状态
#pragma mark - 使用 user 信息,查询当前用户的状态- (void)checkAuthorizationStateWithUser:(NSString *) usercompleteHandler:(void(^)(BOOL authorized, NSString *msg)) completeHandler {if (user == nil || user.length <= 0) {if (completeHandler) {completeHandler(NO, @"用户标识符错误");}return;}ASAuthorizationAppleIDProvider *provider = [[ASAuthorizationAppleIDProvider alloc]init];[provider getCredentialStateForUserID:user completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {NSString *msg = @"未知";BOOL authorized = NO;switch (credentialState) {case ASAuthorizationAppleIDProviderCredentialRevoked:msg = @"授权被撤销";authorized = NO;break;case ASAuthorizationAppleIDProviderCredentialAuthorized:msg = @"已授权";authorized = YES;break;case ASAuthorizationAppleIDProviderCredentialNotFound:msg = @"未查到授权信息";authorized = NO;break;case ASAuthorizationAppleIDProviderCredentialTransferred:msg = @"授权信息变动";authorized = NO;break;default:authorized = NO;break;}if (completeHandler) {completeHandler(authorized, msg);}}];
}
#pragma mark - 添加苹果登录的状态通知- (void)observeAppleSignInState {if (@available(iOS 13.0, *)) {NSNotificationCenter *center = [NSNotificationCenter defaultCenter];[center addObserver:self selector:@selector(handleSignInWithAppleStateChanged:) name:ASAuthorizationAppleIDProviderCredentialRevokedNotification object:nil];}
}
#pragma mark - 观察SignInWithApple状态改变- (void)handleSignInWithAppleStateChanged:(NSNotification *) noti {NSLog(@"%@", noti.name);NSLog(@"%@", noti.userInfo);
}
3、取消授权
对应用授权登录后,我们可以在设备中取消对某个app的授权,操作方法如下:
设置 -> Apple ID -> 密码与安全性 -> 使用您 Apple ID 的 App
选择需要取消的app,停止使用 Apple ID 即可!
!! 但是这个方法只对 iphone 11 以上的手机才有效,11以下的手机还是展示已授权页面
4、Demo 地址 SignInWithAppleDemo
注意:以上属于原创,若有雷同纯属巧合;如有错误,请多多指正,如有遗漏,欢迎大家在评论区补充
iOS开发:使用 Sign In With Apple(登录)用法以及注意事项相关推荐
- iOS应用接入Sign In With Apple
iOS应用接入Sign In With Apple流程 前言 准备工作 开始编写 总结 参考文献 前言 App Store审核要求: New Guidelines for Sign in with A ...
- iOS开发小知识之正则表达式的简单用法
关于正则表达式,百度百科中是这样说的 正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表 ...
- iOS开发-Please sign in with an app-specific password. You can create one at appleid.apple.com
今天要更新APP,因为是新的账号,所以在Xcode无法登陆. 提示信息:Please sign in with an app-specific password. You can create one ...
- iOS开发最新最全微信第三方登录接入流程
前言: [1] iOS 微信登录注意事项 1.目前移动应用上微信登录只提供原生的登录方式,需要用户安装微信客户端才能配合使用.2.对于Android应用,建议总是显示微信登录按钮,当用户手机没有安装微 ...
- (0013)iOS 开发之集成友盟第三方登录
第三方登录的原理和流程 用户采用第三方登录的时候,用户会发送哪些信息到我的后台,后台会进行哪些比对操作?首次使用第三方登录和再次使用第三方登录时验证有哪些不同,后台如何保存用户的登录信息尼? 对于用户 ...
- iOS 开发,xcode7中用QQ授权登录遇到的一些问题 QQ登录不跳客户端
1.首先导入framework. 2. 调用 _tencentOAuth = [[TencentOAuth alloc] initWithAppId:APPID andDelegate:self];这 ...
- macOS升级至12.1后,iOS开发证书无法安装到钥匙串“登录”目录下,无法导出P12文件问题解决方案
背景: 由于要上传app至app store所以配置对应的开发上架证书,证书配置完成后需要共享给同组开发使用,需要导出P12身份信息文件. 问题描述: 按照常规安装方式,双击证书安装选择安装到&quo ...
- iOS开发 - 微信扫描二维码登录网页的原理
转自: http://daily.zhihu.com/story/3783725 我个人开发过程一般是和产品说,『你们提业务要求.交互方式.性能要求等就好,技术方案我们会综合开发时间.系统架构等因素考 ...
- ios开发之--UITableView中的visibleCells的用法
先上图: 具体代码如下: #import "ViewController.h"@interface ViewController ()<UITableViewDelegate ...
- iOS 苹果授权登录(Sign in with Apple)系列之Apple Developer配置篇
原文 在 iOS13 中,如果 App 提供第三方登录,就必须添加 苹果登录 Sign in with Apple 选项,并要求所有开发者于 2020年4月之前 完成现有应用的更新,否则审核不给通过. ...
最新文章
- 浅谈OpenCL之 应用程序总体步骤思路
- QUIC - 低时延互联网传输层协议
- 新款iPhone SE发布日期曝光:小屏果粉早已按捺不住
- 正版python怎么下载_怎么下载官网python并安装
- 干活的不如写ppt的吗_“干活不如写PPT”为啥扎心?
- javascript之字符串常用方法学习 charAt concat indexOf substring substr toUpperCase
- 11-11 11:11
- FastDFS存储目录迁移方案
- 【pyqt5学习】——添加菜单栏动作action,给动作触发triggered绑定事件
- 根据IP地址求网络号、子网号和主机号
- rust使用vec在遍历时删除元素
- java.sql.SQLException: Incorrect string value: ‘\xE6\xB5\x8B\xE8\xAF\x95...‘ for column ‘xxx‘
- 【Spark】Spark Quick Start(快速入门翻译)
- fragment添加失败错误查找
- 电脑都面的没电了,我是如何通过腾讯云恐怖的一面面试的?
- post请求或get请求通过url传递参数
- Scala之case class
- 疫情期间,大型企业如何保障日常会议的正常进行?
- 微服务链路追踪SkyWalking第八课 OAP的receiver模块详解
- python开发cs软件_开发cs软件 c python
热门文章
- 2022年2月手术机器人行业动态
- android wifi tcpip,Android无线调试:tcpip无线连接 | WiFi apk无线连接
- macOS - pip install scipy Error: No BLAS/LAPACK libraries found
- ofstream和ifstream详细用法
- 因为被骗8000块,他愤而“自学”电信诈骗搞到115万,如今他这样
- 用机器学习打造聊天机器人(四) 代码篇
- JavaScript正则表达式匹配:不包含某字符或字符串
- 论文笔记 | 基于双线性CNN模型的细粒度视觉识别
- 龙之谷单机版(6月17日即将内测)【血量基址+偏移】
- Centos 7安装配置NTP网络时间同步服务器
iOS应用接入Sign In With Apple流程 前言 准备工作 开始编写 总结 参考文献 前言 App Store审核要求: New Guidelines for Sign in with A ...
关于正则表达式,百度百科中是这样说的 正则表达式,又称正规表示法.常规表示法(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表 ...
今天要更新APP,因为是新的账号,所以在Xcode无法登陆. 提示信息:Please sign in with an app-specific password. You can create one ...
前言: [1] iOS 微信登录注意事项 1.目前移动应用上微信登录只提供原生的登录方式,需要用户安装微信客户端才能配合使用.2.对于Android应用,建议总是显示微信登录按钮,当用户手机没有安装微 ...
第三方登录的原理和流程 用户采用第三方登录的时候,用户会发送哪些信息到我的后台,后台会进行哪些比对操作?首次使用第三方登录和再次使用第三方登录时验证有哪些不同,后台如何保存用户的登录信息尼? 对于用户 ...
1.首先导入framework. 2. 调用 _tencentOAuth = [[TencentOAuth alloc] initWithAppId:APPID andDelegate:self];这 ...
背景: 由于要上传app至app store所以配置对应的开发上架证书,证书配置完成后需要共享给同组开发使用,需要导出P12身份信息文件. 问题描述: 按照常规安装方式,双击证书安装选择安装到&quo ...
转自: http://daily.zhihu.com/story/3783725 我个人开发过程一般是和产品说,『你们提业务要求.交互方式.性能要求等就好,技术方案我们会综合开发时间.系统架构等因素考 ...
先上图: 具体代码如下: #import "ViewController.h"@interface ViewController ()<UITableViewDelegate ...
原文 在 iOS13 中,如果 App 提供第三方登录,就必须添加 苹果登录 Sign in with Apple 选项,并要求所有开发者于 2020年4月之前 完成现有应用的更新,否则审核不给通过. ...