swift Apple sign 苹果登录

  1. AppDelegate中判断apple sign状态是否有效

当用户使用苹果登录认证成功之后,用户可以在iPhone上更改状态:

  • 设置->Apple ID->密码与安全性->使用您AppleID的App 中删除你的APP
  • 在设置里注销了 Apple ID

这些情况下,App需要获取到这些状态,然后做退出登录操作,或者重新登录。

我们可以在 App 启动的时候,通过 getCredentialState:completion: 来获取当前用户的授权状态:
.authorized:验证通过
.notFound:注销了 Apple ID
.revoked, .transferred:暂无测试

//
// MARK: - apple login
//
@available(iOS 13.0, *)
extension AppDelegate {
    
    /*
     判断登录的类型 是手机号、微信号、appleid
     注意:当第一次认证成功之后,将不会再返回email,fullName等信息
     */
    func appleLoginStateCheck() {
        
        ///1.钥匙串是否保存了apple login id
        guard let userIdentifier = KeychainExt.extKeyChainReadData(identifier: kAppBundleID+kAppleLogin888Identify) as? String else {
            DebugLog("没有读到apple login Identify")
            return
        }

        ///2.获取状态 回调是子线程
        let appleIDProvider = ASAuthorizationAppleIDProvider()
        appleIDProvider.getCredentialState(forUserID: userIdentifier) { (credentialState, error) in
            switch credentialState {
                
            /// The Apple ID credential is valid.
            case .authorized:
                break
                
            ///如果上次是apple登录 需要重新登录
            case .revoked, .notFound, .transferred:
                fallthrough
            default:
                break
            }
        }
    }
}
  1. vc中布局UI,调用登录方法
//
// MARK: - 苹果登录 
//
@available(iOS 13.0, *)
extension LoginVC {
    
    func setupProviderLoginView() {
        let btnAuth = ASAuthorizationAppleIDButton(type: .signIn, style: .whiteOutline)
        btnAuth.addTarget(self, action: #selector(signInWithApple), for: .touchUpInside)
        view.addSubview(btnAuth)
        btnAuth.snp.makeConstraints { (make) in
            make.left.right.height.equalTo(self.btnWechat)
            make.bottom.equalTo(self.btnWechat.snp.top).offset(-15)
        }
    }
    
    @objc func signInWithApple() {
        let appleIDProvider = ASAuthorizationAppleIDProvider()
        let request = appleIDProvider.createRequest()
        request.requestedScopes = [.fullName, .email]
        
        let authVC = ASAuthorizationController(authorizationRequests: [request])
        authVC.delegate = self
        authVC.presentationContextProvider = self
        authVC.performRequests()
    }
}
  1. 代理方法
//
// MARK: - 苹果登录 
//
@available(iOS 13.0, *)
extension LoginViewModel : ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
    
    ///告诉 ASAuthorizationController 展示在哪个 window 上
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return view.window!
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        var errorMsg = ""
        
        switch error {
        case ASAuthorizationError.canceled:
            errorMsg = "用户取消了授权请求";
            break;
        case ASAuthorizationError.failed:
            errorMsg = "授权请求失败";
            break;
        case ASAuthorizationError.invalidResponse:
            errorMsg = "授权请求响应无效";
            break;
        case ASAuthorizationError.notHandled:
            errorMsg = "未能处理授权请求";
            break;
        case ASAuthorizationError.unknown:
            errorMsg = "授权请求失败未知原因";
            break;
        default:
            break;
        }
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        switch authorization.credential {
        case let appleIDCredential as ASAuthorizationAppleIDCredential:
            
            // 用户唯一ID,在一个开发者账号下的APP获取到的是一样的,类似微信开发API中的openid
            // 注意:第二次登录的时候不会返回所有数据,只返回了user,所以需要根据这个user查询存储在服务器的完整用户信息
            let userIdentifier = appleIDCredential.user///"000332.908a521751dd432eb8b35d48f0a98eae.0141"
            DebugLog(userIdentifier)
            
            
            //后端需要的token
            if let identityTokenData = appleIDCredential.identityToken, let idTokenStr = String(data: identityTokenData, encoding: .utf8) {
                /**
                 "eyJraWQiOiI4NkQ4OEtmIiwiYWxnIjoiUlMyNTYifQ.eyJpc3MiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiYXVkIjoiY29tLnRhZ0V4cC5xaWFucWlhbiIsImV4cCI6MTYwMjg5OTkyNSwiaWF0IjoxNjAyODEzNTI1LCJzdWIiOiIwMDE1OTQuODMxNjllYjA2YzE4NDUzMTk4NWVmNDY4NTUxNGUyNGYuMDE0OCIsImNfaGFzaCI6IjdDUWVkUUNqSmluQXl2ODgzN1RlZEEiLCJlbWFpbCI6IjU3ZjllbTVnZXBAcHJpdmF0ZXJlbGF5LmFwcGxlaWQuY29tIiwiZW1haWxfdmVyaWZpZWQiOiJ0cnVlIiwiaXNfcHJpdmF0ZV9lbWFpbCI6InRydWUiLCJhdXRoX3RpbWUiOjE2MDI4MTM1MjUsIm5vbmNlX3N1cHBvcnRlZCI6dHJ1ZX0.Rv7DZ8gMqE_5t16Q_sjIAhDc5R0HN7vzDYUHeQI-6KJZVRKyA6UrI3hSK9Z-gPLrHaegyvVdMhut4k_VBsw69c9gcLmo6s8WbV-aw7tU8UHNksinQF153PAlGuKJgRs1fnC-WPywmL7-u8Y0depCy0HJGsfwxpiV4kctxypt3CAEGtt7PC2GrkWYQMjEvFf1ZLYD42MDzw-0im9Eh6GUC_WbW31EXfF92KQpNdwmDqoyJ8fAyXxga1xgRZLYCbqSU1iN7K-9kJqLRZlvcJLFikyQdICr91gRmLHeRzS43q50SyVyhcBa_AELrkYZDkcdPD18gT4d3rGTGh2Os7WAfA"
                 */
                DebugLog(idTokenStr)
            }
            
            // realUserStatus:是否是“真实用户”,可用于反作弊,对抗黑灰产
            if .likelyReal == appleIDCredential.realUserStatus {
                DebugLog("用户 likelyReal")
            } else {
                DebugLog("用户 不是真实用户")
            }
            
            // store the `userIdentifier` in the keychain.
            let saveRst = KeychainExt.extKeyChainSaveData(data: userIdentifier, withIdentifier: kAppBundleID+kAppleLogin888Identify)
            DebugLog(saveRst ? "保存OK" : "保存失败")
        
        case let passwordCredential as ASPasswordCredential:
        
            // Sign in using an existing iCloud Keychain credential.
            let username = passwordCredential.user
            let password = passwordCredential.password
            DebugLog(username)
            DebugLog(password)
            
            DispatchQueue.main.async {
                self.appleBlock(username + "opo" + password)
            }
            
        default:
            break
        }

你可能感兴趣的:(swift Apple sign 苹果登录)