Sign in with Apple

Sign in with Apple 從登陸到服務(wù)器驗(yàn)證 看我這個(gè)鏈接。

WWDC2019大會(huì)上,蘋(píng)果將支持使用AppleID進(jìn)行登錄。這篇文件記錄并介紹下Sing in with Apple這篇視頻中所介紹的內(nèi)容,即使用AppleID登錄。

AppleID登錄的一些特性

  1. 簡(jiǎn)化賬號(hào)的創(chuàng)建和登錄流程,無(wú)縫跨設(shè)備使用
  2. 開(kāi)發(fā)者可以獲取到已驗(yàn)證過(guò)的郵箱作為登錄賬號(hào)或者與用戶進(jìn)行通信(注:用戶可以選擇隱藏真實(shí)郵箱,并使用蘋(píng)果提供的虛擬郵箱進(jìn)行授權(quán))
  3. 尊重用戶隱私,開(kāi)發(fā)者只可獲取郵箱及姓名
  4. 反欺詐,使用機(jī)器學(xué)習(xí)等技術(shù)和其他信息,幫助開(kāi)發(fā)者判斷一個(gè)賬號(hào)是否真實(shí)
  5. 跨平臺(tái)
image.png

登錄流程圖:


image.png

代碼操作

  • 在項(xiàng)目中找到如圖所示位置,點(diǎn)擊并添加Sign in with Apple

這里需要注意的是,你的對(duì)應(yīng)證書(shū)里面也要添加對(duì)應(yīng)的權(quán)限

image.png

image.png
  • 導(dǎo)入框架 import AuthenticationServices

創(chuàng)建登錄按鈕(蘋(píng)果框架中提供了一個(gè)現(xiàn)成的)

// 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是一個(gè)枚舉,可以獲取到用戶的nameemail

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

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

登錄方法中我們需要遵循兩個(gè)協(xié)議: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方法我們需要返回一個(gè)window

注: public typealias ASPresentationAnchor = UIWindow

func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
    return self.view.window!
}

這時(shí)候你點(diǎn)擊按鈕應(yīng)該可以看到如下界面:


image.png
  • 登錄回調(diào)
    ASAuthorizationControllerDelegate這個(gè)協(xié)議中的兩個(gè)方法即為登錄成功及失敗的回調(diào)
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
}

如果用戶之前已經(jīng)登陸過(guò),那么我們可以提醒用戶輸入密碼直接登錄之前的賬號(hào),代碼如下

func performExistingAccountSetupFlows() {
    let requests = [ASAuthorizationAppleIDProvider().createRequest(),
                        ASAuthorizationPasswordProvider().createRequest()]
        
    let controller = ASAuthorizationController(authorizationRequests: requests)
    controller.delegate = self
    controller.presentationContextProvider = self
    controller.performRequests()
}

然后修改回調(diào)方法,在上面的switch-case語(yǔ)句中添加一個(gè)case

case let passwordCredential as ASPasswordCredential:
        // Sign in using an existing iCloud Keychain credential.
        break
  • 檢查用戶登錄狀態(tài)
    這個(gè)操作我們可以放到AppDelegate中的app did finish launching中,因?yàn)樘O(píng)果告訴我們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
    }
}
  • 監(jiān)聽(tīng)用戶是否取消對(duì)app的登錄授權(quán)
// 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
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容