三方登录- iOS Twitter登录

背景

在现代移动应用中,集成第三方登录已经成为一种常见的需求,它不仅能提高用户体验,还能减少用户注册的阻力。我们选择了 Twitter 作为示例,但类似的步骤和逻辑也适用于其他第三方登录服务。希望这篇博客能为你提供清晰的指导,并帮助你在应用中成功实现第三方登录。

Twitter登录与其它三方登录不同,比如Facebook官方提供了完整的SDK可以直接使用,业务场景中有遇到的话难免会有点不知所措,下面就介绍一下Twitter登录的实现方案。

实现方案一

虽然Twitter没有提供官方的SDK但是也在开发者网站上也推荐了两个github的库。

https://developer.x.com/en/docs/twitter-api/tools-and-libraries/v2

我们以TwitterAPIKit为例:

1.点击连接下载TwitterAPIKit到本地。
2.打开自己的项目点击file->Add Package Dependenceis将刚刚下载的Package添加到项目。

添加后项目结构如下:

3.Info.plist文件增加scheme

允许回调到你的APP

允许打开其它APP

4.代码实现

声明一些必要属性

class ViewController: UIViewController, ASWebAuthenticationPresentationContextProviding {
   
    /// 替换成你自己的consumerKey
    let consumerKey = "consumerKey"
    /// 替换成你自己的consumerSecret
    let consumerSecret = "consumerSecret"
    /// callbackURL
    var callbackURL:String!
    /// scheme
    var scheme:String!
    
    var client:TwitterAPIClient!

    override func viewDidLoad() {
            .....
    }
}

consumerKey和consumerSecret是在开发平台创建自己应用后可以获取到的两个数据。

callbackURL和scheme需要自己进行拼接

        callbackURL = "twitterkit-\(consumerKey)://"
        scheme = "twitterkit-\(consumerKey)"

点击登录按钮后创建TwitterAPIClient的实例client,并发起post请求获取用户token和secret

@objc func loginAction() {
        callbackURL = "twitterkit-\(consumerKey)://"
        scheme = "twitterkit-\(consumerKey)"
        client = TwitterAPIClient(.oauth10a(.init(consumerKey: consumerKey, consumerSecret: consumerSecret, oauthToken: nil, oauthTokenSecret: nil)))
        client.auth.oauth10a.postOAuthRequestToken(.init(oauthCallback: callbackURL)).responseObject {[weak self] response in
            guard let self = self else { return }
            do {
                let success = try response.result.get()
                let url = self.client.auth.oauth10a.makeOAuthAuthorizeURL(.init(oauthToken: success.oauthToken))!
                let session = ASWebAuthenticationSession(url: url, callbackURLScheme: scheme) { url, error in
                    // url is "twitter-api-kit-ios-sample://?oauth_token=<string>&oauth_verifier=<string>"
                    guard let url = url else {
                        if let error = error {
                            print(error)
                        }
                        return
                    }
                    print("URL:", url)

                    let component = URLComponents(url: url, resolvingAgainstBaseURL: false)
                    guard let oauthToken = component?.queryItems?.first(where: { $0.name == "oauth_token"} )?.value,
                          let oauthVerifier = component?.queryItems?.first(where: { $0.name == "oauth_verifier"})?.value else {
                        print("Invalid URL")
                        return
                    }
                    self.client.auth.oauth10a.postOAuthAccessToken(.init(oauthToken: oauthToken, oauthVerifier: oauthVerifier))
                        .responseObject { response in
                            do {
                                let token = try response.result.get()
                                let oauthToken = token.oauthToken
                                let oauthTokenSecret = token.oauthTokenSecret
                                print("result : \(oauthToken), \(oauthTokenSecret)")
                            } catch {
                               print(error)
                            }
                        }
                }
                session.presentationContextProvider = self
                session.prefersEphemeralWebBrowserSession = true
                session.start()

            } catch {
                print(error)
            }
        }
    }
    
    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return view.window!
    }

将获取到的token和screte传递给服务端,完成Twitter登录。

但是这里面有个问题,由于我们使用ASWebAuthenticationSession,它主要用于处理 OAuth 和 OpenID Connect 等 web 基于身份验证的流程。ASWebAuthenticationSession 让应用程序可以安全地打开一个浏览器界面(使用 Safari 浏览器)来完成认证过程,并在认证完成后将结果返回给应用程序。

所以即使安装了TwitterAPP也不能调起TwitterAPP,整个认证过程都是在自己的APP内进行。

实现方案二

再介绍一种更简单的实现方式,不需要借助任何三方代码,直接使用ASWebAuthenticationSession或者UIApplication.shared.open的方式打开认证页面。

为了可以调起Twitter我们这里使用UIApplication.shared.open的方式。

info.plist文件的设置与上面相同,这里就不过多介绍了。

代码实现

我们为它单独创建了一个单利

class CSTwitterHelper: NSObject {
    
    static let shared = CSTwitterHelper()
    ....
}

同样需要使用Consumer_Key和Consumer_Secret。

  let Twitter_Consumer_Key = "pxvBpjJMk4OwxA1rB7R3OnSEN"
    let Twitter_Consumer_Secret = "EQzLWzeIBqZzOr1WN6g4V6aH0WUNiDwFx6aQkGtG20E2xLwCaD"
    
    var successCompletion: ((_ accessToken:String,_ accessTokenSecret:String) -> Void)?
    var failure: ((_ error:Error) -> Void)?

点击登录时,直接使用UIApplication.shared.open方式打开拼接的url

    /// twitter登录
    /// - Parameters:
    ///  - successCompletion: 成功回调
    ///  - fairlure: 失败回调
    func twitterLogin(successCompletion: @escaping (_ accessToken:String,_ accessTokenSecret:String) -> Void,fairlure: @escaping (_ error:Error) -> Void) {
        let url = "twitterauth://authorize?consumer_key=\(Twitter_Consumer_Key)&consumer_secret=\(Twitter_Consumer_Secret)&oauth_callback=twitterkit-\(Twitter_Consumer_Key)"
        UIApplication.shared.open(URL(string: url)!, options: [:]) { success in
            if !success {
                let error = NSError(domain: "twitter", code: 101, userInfo: [NSLocalizedDescriptionKey:"Cannot open twitter app"])
                fairlure(error)
            }
        }
        self.successCompletion = successCompletion
        self.failure = fairlure
    }

在AppDelegate中设置回调,如果你保留了SceneDelegate也需要设置回调。

 func application(
        _ app: UIApplication,
        open url: URL,
        options: [UIApplication.OpenURLOptionsKey : Any] = [:]
    ) -> Bool {
        // twitter
        if url.scheme == "twitterkit-\(CSTwitterHelper.shared.Twitter_Consumer_Key)" {
            return CSTwitterHelper.shared.twitterApplication(app, open: url, options: options)
        }
    }

在回调中获取我们需要的token和secret传递给服务端。

    /// twitter登录回调
    /// - Parameters:
    /// - app: UIApplication
    /// - url: URL
    /// - options: [UIApplication.OpenURLOptionsKey : Any]
    /// - Returns: Bool
    func twitterApplication(_ app: UIApplication,open url: URL,options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        let isCanceled = (url.host == nil)
        if isCanceled {
            // 用户取消
            let error = NSError(domain: "twitter", code: 100, userInfo: [NSLocalizedDescriptionKey:"User canceled"])
            self.failure?(error)
            return false
        }
        let params = url.queryParams
        let secret = params["secret"]
        let token = params["token"]
        let userName = params["username"]
        if let token = token,let secret = secret {
            self.successCompletion?(token,secret)
        } else {
            let error = NSError(domain: "twitter", code: 102, userInfo: [NSLocalizedDescriptionKey:"params error"])
            self.failure?(error)
        }
        return true
    }

其中url.queryParams是为URL添加了一个扩展方法,用来获取参数。

extension URL {
    
    /// 获取参数
    var queryParams: [String : String] {
        guard let host = self.host else { return [:] }
        return host.split(separator: "&").reduce(into: [:]) { (result, parameter) in
            let keyValue = parameter.split(separator: "=")
            result[String(keyValue[0])] = String(keyValue[1])
        }
    }
}

结语

对客户端来说Twitter登录,只需要获取到token和secret就算完成了,任何一种方法只要能从Twitter获取到这两个数据就算登录成功了。

感谢你的阅读,如果你有任何问题或需要进一步的帮助,请随时留言交流。祝你开发顺利,项目成功!

  • 22
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值