Sign in with Apple

Sign in with Apple 从登陆到服务器验证 看我这个链接。

WWDC2019大会上,苹果将支持使用AppleID进行登录。这篇文件记录并介绍下Sing in with Apple这篇视频中所介绍的内容,即使用AppleID登录。

AppleID登录的一些特性

  1. 简化账号的创建和登录流程,无缝跨设备使用
  2. 开发者可以获取到已验证过的邮箱作为登录账号或者与用户进行通信(注:用户可以选择隐藏真实邮箱,并使用苹果提供的虚拟邮箱进行授权)
  3. 尊重用户隐私,开发者只可获取邮箱及姓名
  4. 反欺诈,使用机器学习等技术和其他信息,帮助开发者判断一个账号是否真实
  5. 跨平台
image.png

登录流程图:


image.png

代码操作

  • 在项目中找到如图所示位置,点击并添加Sign in with Apple

这里需要注意的是,你的对应证书里面也要添加对应的权限

image.png

image.png
  • 导入框架 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是一个枚举,可以获取到用户的nameemail

extension ASAuthorization.Scope {
    @available(iOS 13.0, *)
    public static let fullName: ASAuthorization.Scope

    @available(iOS 13.0, *)
    public static let email: ASAuthorization.Scope
}

登录方法中我们需要遵循两个协议:ASAuthorizationControllerDelegateASAuthorizationControllerPresentationContextProviding

@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!
}

这时候你点击按钮应该可以看到如下界面:


image.png
  • 登录回调
    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
}

你可能感兴趣的:(Sign in with Apple)