ios - 在 iOS 应用程序中使用 GitHub 的 OAuth 身份验证 - 它是如何工作的

标签 ios swift github oauth

我正在尝试了解在 IOS 应用程序的情况下如何使用 GITHUB 进行 oauth 身份验证。

我正在开发一个IOS App,想使用GITHUB进行登录认证。

这是我的应用程序的流程。

  1. 用户注册 - 这是一个离线过程,发生在我的应用之外。当我为用户创建帐户时,我要求他们提供他们的 GITHUB 电子邮件地址。我将此电子邮件地址作为该用户的用户 ID 存储在我们的数据库中。

  2. 从 GITHUB 获取访问 token - 当用户打开我们的应用程序时,我们将他们定向到 https://github.com/login/oauth/authorize使用 WebView 。一旦用户成功登录到 GITHUB 帐户,我使用 https://github.com/login/oauth/access_token获取访问 token 。

  3. 使用访问 token 获取电子邮件地址 - 我正在使用 https://api.github.com/user/emails使用我在第 2 步中获得的访问 token 获取登录帐户的电子邮件地址。

  4. 验证电子邮件地址:我根据我的数据库验证我在第 3 步中获得的电子邮件地址。如果 userid 存在,那么用户将能够在我们的应用程序上进行交易。

现在在 GITHUB 验证控制返回到具有 GITHUB 的 webview 的 viewcontroller 之后,出现空白屏幕。如何将流程移动到下一个 View Controller ?

这是我的 ViewController 代码:

import UIKit
import WebKit

class Login: UIViewController, UIWebViewDelegate {

    @IBOutlet weak var webview: UIWebView!
    override func viewDidLoad() {
        super.viewDidLoad()

        let authURL = String(format: "%@?client_id=%@&redirect_uri=%@&scope=%@", arguments: [GITHUB.GITHUB_AUTHURL,GITHUB.GITHUB_CLIENT_ID,GITHUB.GITHUB_REDIRECT_URI,GITHUB.GITHUB_SCOPE])

        let urlRequest = URLRequest.init(url: URL.init(string: authURL)!)
        webview.loadRequest(urlRequest)
        webview.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func webView(_ webview: UIWebView, shouldStartLoadWith request:URLRequest, navigationType: UIWebViewNavigationType) -> Bool{
        return checkRequestForCallbackURL(request: request)
    }

    func checkRequestForCallbackURL(request: URLRequest) -> Bool {
        //print("3. IN FUNCTION checkRequestForCallbackURL")

        let requestURLString = (request.url?.absoluteString)! as String
        //print("3. requestURLString=\(requestURLString)")

        if requestURLString.hasPrefix(GITHUB.GITHUB_REDIRECT_URI) {

            let range: Range<String.Index> = requestURLString.range(of: "?code=")!

            handleGithubCode(code: requestURLString.substring(from: range.upperBound))

            return false;
        }

        return true
    }

    func handleGithubCode(code: String) {

            let urlString = "https://github.com/login/oauth/access_token"
            if let tokenUrl = URL(string: urlString) {

                let req = NSMutableURLRequest(url: tokenUrl)
                req.httpMethod = "POST"
                req.addValue("application/json", forHTTPHeaderField: "Content-Type")
                req.addValue("application/json", forHTTPHeaderField: "Accept")

                let params = [
                    "client_id" : GITHUB.GITHUB_CLIENT_ID,
                    "client_secret" : GITHUB.GITHUB_CLIENTSECRET,
                    "code" : code
                ]

                req.httpBody = try? JSONSerialization.data(withJSONObject: params, options: [])
                let task = URLSession.shared.dataTask(with: req as URLRequest) { data, response, error in

                    if let data = data {
                        do {
                            if let content = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] {
                                if let accessToken = content["access_token"] as? String {
                                    self.getComposerToken(accessToken: accessToken)

                                }
                            }
                        } catch {}
                    }
                }
                task.resume()
            }
    }

    func getComposerToken(accessToken: String) {
        print("5. accessToken=\(accessToken)")

        let def = "NO_DATA"

        let composerUrl = "http://192.168.100.112/kubher/getAccessToken.php?token=\(accessToken)"
        guard let url = URL(string: composerUrl) else { return }

        URLSession.shared.dataTask(with: url) { (data, response, error) in
            if let response = response {
                //print(response)
            }

            if let data = data {
                do {
                    let json = try? JSONSerialization.jsonObject(with: data, options: [])

                    if let dict = json as? [String: Any],
                        let token = dict["accessToken"] {
                        print("Blockchain Token:\(token)")
                    }
                } catch {
                    print(error)
                }
            }
        }.resume()
  }
}

最佳答案

移动到下一个 View Controller 取决于代码的架构。根据您的设计尝试以下代码。 选择 1:如果您需要返回到之前的 ViewController,只需修改您的 getComposerToken 函数:

if let dict = json as? [String: Any], {
    let token = dict["accessToken"] {
    print("Blockchain Token:\(token)")
    dispatch_async(dispatch_get_main_queue()) {
        self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
    }
    }
}

选项 2:另一方面,如果您正在使用 Segue 作为 stoaryboard 中的下一个 viewController,请为您的 segue 命名(标识符),然后遵循以下代码:

if let dict = json as? [String: Any], {
        let token = dict["accessToken"] {
        print("Blockchain Token:\(token)")
        dispatch_async(dispatch_get_main_queue()) {
            self.performSegue(withIdentifier: "YourSegueName", sender: token)
        }
      }
    }

另外,你必须重写prepare方法来传递数据

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "segueName" {
            let viewController = segue.destination as? YourViewController
            if let token = sender as? String {
                viewController?.token = token
            }
        }
    }
}

选项 3:如果您在从 Storyboard 中创建后使用推送 View Controller ,则必须在 Storyboard 中为 View Controller 提供一个标识符,然后您可以使用实例化它并使用以下方式推送它:

if let dict = json as? [String: Any], {
    let token = dict["accessToken"] {
    let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
    let abcViewController = storyboard.instantiateViewControllerWithIdentifier("YourControlleridentifier") as! YourViewController
YourViewController.token = token
navigationController?.pushViewController(YourViewController, animated: true)
}
}

关于ios - 在 iOS 应用程序中使用 GitHub 的 OAuth 身份验证 - 它是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52446904/

相关文章:

java - Travis CI 不使用 pom.xml 中提供的额外 Maven 存储库

github - 如何在 github 上的私有(private)仓库上禁用 fork

ios - ConvertRect 没有按预期工作

iphone - 如果设备上没有互联网连接,则 ios 应用程序会出错

swift - 计算平均配速

ios - 将照片库中的图像加载到我的 UIImageView 中,但重新启动应用程序时图像不会更改

ios - 无法在索引 0 处插入 CAGradientLayer(在 tableView 后面)

ios - NSUTF8StringEncoding 结果编码字符串为 'Optional' 字符串

ios - 将自己从 Bonjour 搜索结果中排除的方法

github - Git 拉取 : EGit with GitHub