Sign in with Apple 从登陆到服务器验证 看我这个链接。
WWDC2019大会上,苹果将支持使用AppleID
进行登录。这篇文件记录并介绍下Sing in with Apple这篇视频中所介绍的内容,即使用AppleID
登录。
AppleID
登录的一些特性
- 简化账号的创建和登录流程,无缝跨设备使用
- 开发者可以获取到已验证过的邮箱作为登录账号或者与用户进行通信(注:用户可以选择隐藏真实邮箱,并使用苹果提供的虚拟邮箱进行授权)
- 尊重用户隐私,开发者只可获取邮箱及姓名
- 反欺诈,使用机器学习等技术和其他信息,帮助开发者判断一个账号是否真实
- 跨平台
登录流程图:
代码操作
- 在项目中找到如图所示位置,点击并添加
Sign in with Apple
这里需要注意的是,你的对应证书里面也要添加对应的权限
- 导入框架
import AuthenticationServices
创建登录按钮(苹果框架中提供了一个现成的)
// Add “Sign In with Apple” button to your login view
func setUpProviderLoginView() {
let button = ASAuthorizationAppleIDButton()
button.addTarget(self, action:#selector(handleAuthorizationAppleIDButtonPress),
for: .touchUpInside)
self.loginProviderStackView.addArrangedSubview(button)
}
// Configure request, setup delegates and perform authorization request
@objc func handleAuthorizationButtonPress() {
let request = ASAuthorizationAppleIDProvider().createRequest()
request.requestedScopes = [.fullName, .email]
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()
}
ASAuthorization.Scope
是一个枚举,可以获取到用户的name
及email
extension ASAuthorization.Scope {
@available(iOS 13.0, *)
public static let fullName: ASAuthorization.Scope
@available(iOS 13.0, *)
public static let email: ASAuthorization.Scope
}
登录方法中我们需要遵循两个协议:ASAuthorizationControllerDelegate
和ASAuthorizationControllerPresentationContextProviding
@available(iOS 13.0, *)
public protocol ASAuthorizationControllerDelegate : NSObjectProtocol {
optional func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization)
optional func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error)
}
@available(iOS 13.0, *)
public protocol ASAuthorizationControllerPresentationContextProviding : NSObjectProtocol {
/** @abstract Return a view anchor that is most appropriate for athorization UI to be presented over. This view will be used as a hint if a credential provider requires user interaction.
*/
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor
}
其中presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor
方法我们需要返回一个window
注: public typealias ASPresentationAnchor = UIWindow
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
这时候你点击按钮应该可以看到如下界面:
- 登录回调
ASAuthorizationControllerDelegate
这个协议中的两个方法即为登录成功及失败的回调
func authorizationController(controller _: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
switch authorization.credential {
case let appleIdCredential as ASAuthorizationAppleIDCredential:
let userIdentifier = appleIdCredential.user
let identityToken = appleIdCredential.identityToken
let authCode = appleIdCredential.authorizationCode
let realUserStatus = appleIdCredential.realUserStatus
default:
break
}
}
func authorizationController(_: ASAuthorizationController, didCompleteWithError error: Error) {
// Handle error
}
如果用户之前已经登陆过,那么我们可以提醒用户输入密码直接登录之前的账号,代码如下
func performExistingAccountSetupFlows() {
let requests = [ASAuthorizationAppleIDProvider().createRequest(),
ASAuthorizationPasswordProvider().createRequest()]
let controller = ASAuthorizationController(authorizationRequests: requests)
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()
}
然后修改回调方法,在上面的switch-case
语句中添加一个case
case let passwordCredential as ASPasswordCredential:
// Sign in using an existing iCloud Keychain credential.
break
- 检查用户登录状态
这个操作我们可以放到AppDelegate
中的app did finish launching
中,因为苹果告诉我们the api is very fast
let provider = ASAuthorizationAppleIDProvider()
provider.getCredentialState(forUserID: "currentUserIdentifier") { (credentialState, error) in
switch(credentialState){
case .authorized:
// Apple ID Credential is valid
case .revoked:
// Apple ID Credential revoked, handle unlink
fallthrough
case .notFound:
// Credential not found, show login UI
default: break
}
}
- 监听用户是否取消对app的登录授权
// Register for revocation notification
let center = NotificationCenter.default
let name = ASAuthorizationAppleIDProvider.credentialRevokedNotification
let observer = center.addObserver(forName: name, object: nil, queue: nil) { (Notification) in
// Sign the user out, optionally guide them to sign in again
}