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
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容