在 iOS 应用程序中使用 GitHub 进行 OAuth 身份验证 - 它是如何工作的
问题:在 iOS 应用程序中使用 GitHub 进行 OAuth 身份验证 - 它是如何工作的
我正在尝试了解在 IOS 应用程序中使用 GITHUB 的 oauth 身份验证如何工作。
我正在开发一个 IOS 应用程序并想使用 GITHUB 进行登录验证。
这是我的应用程序的流程。
-
用户注册 - 这是一个离线过程,发生在我的应用程序之外。当我为用户创建帐户时,我要求他们提供他们的 GITHUB 电子邮件地址。我将此电子邮件地址作为该用户的用户 ID 存储在我们的数据库中。
-
从 GITHUB 获取访问令牌 - 当用户打开我们的应用程序时,我们使用 webview 将他们定向到https://github.com/login/oauth/authorize。用户成功登录 GITHUB 帐户后,我使用https://github.com/login/oauth/access_token获取访问令牌。
-
使用访问令牌获取电子邮件地址 - 我正在使用https://api.github.com/user/emails使用我在步骤 2 中获得的访问令牌获取登录帐户的电子邮件地址。
4.验证电子邮件地址:我根据我的数据库验证我在步骤3中获得的电子邮件地址。如果 userid 存在,那么用户将能够在我们的应用程序上进行交易。
现在,在 GITHUB 验证控制返回到具有 GITHUB 的 webview 的视图控制器之后,出现了一个空白屏幕。如何将流程移动到下一个视图控制器?
这是我的视图控制器代码:
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()
}
}
解答
移至下一个视图控制器取决于代码的体系结构。根据您的设计尝试以下代码。 opt 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 用于下一个 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
}
}
}
}
OPT 3:如果您在从情节提要创建后使用推送视图控制器,则必须在情节提要中为您的视图控制器提供一个标识符,然后您可以使用实例化它并使用以下方式推送它:
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)
}
}
更多推荐
所有评论(0)