iT邦幫忙

0

ios app 實作登入/登出功能(API驗證)

各位大哥先進好!
小弟目前是IOS APP 新手,目前後台功能都寫得差不多了(單純抓API資料庫顯示一些資料),目前遇到一大難題不知道從何下手
就是登入介面,想要實作一個登入介面的功能
View底下只有兩個Text Field (帳號密碼),還有一個Button(LOGIN按鈕),要驗證的方式是透過web api抓MSSQL相關人員的帳號密碼
如下圖
https://ithelp.ithome.com.tw/upload/images/20190323/20115582fuhxYq3xpc.png
很簡單的api,我只要驗證兩個字串,然後到下一頁的功能
IOS抓JSON的code如下圖
https://ithelp.ithome.com.tw/upload/images/20190323/20115582mrCb7pn5Lh.png
IOS這邊目前把api欄位的數據都已經抓出來了,但是不知道要怎麼利用抓到的字串去做登入驗證的功能,登出就是回到登入頁
目前粗略的想法是,單純驗證使用者輸入的值去判斷等不等於json的字串,但是因為是初學IOS
所以不知道怎麼下手,不知道JSON回傳回來值要怎麼運用
感謝大哥先進的解答!!

0
海綿寶寶
iT邦超人 1 級 ‧ 2019-03-24 10:03:11
最佳解答
1.改API,不必回傳所有人的帳號密碼(既麻煩又違反所有資安規則),API的回覆只要以下兩種即可 
{RESULT:"OK"}(登入成功}
{RESULT:"FAILED"}(登入失敗}
2.依據結果做對應動作
3.登入成功 - 記錄「登入狀態」為「已登入」(Y),頁面轉轉去
4.登入失敗 - 顯示失敗訊息,停留在原頁面
5.登出 - 「登入狀態」改為「未登入」(N),頁面轉去登入頁
看更多先前的回應...收起先前的回應...

謝謝你的解答,但因為我們只是大學的專題(app功能僅是查看MSSQL的資料),所以當初並沒有設想到資安的問題,只想到從app裡面抓取到的json字串做比對即可(但是連這個功能都不太會做),所以api設計上也相對簡陋,只有單純把人員的資料給一一顯示出來(json)
程式碼如下圖(C#寫的api)
https://ithelp.ithome.com.tw/upload/images/20190324/20115582KJH6G2IXbD.png
所以毫無頭緒不知道從何改起,不知道能不能提點我一些改進的方向,感謝你!

目的是「拿一組帳密和一堆帳密做比對並決定是否登入成功」
大致上有兩個寫法:
1.API 回傳所有帳密,在 app 端做比對
程式設計:字串和 json物件(陣列?)比對
2.API 拿帳密和資料庫裡帳密做比對,只回覆 app 登入成功和失敗
程式設計:SQL指令,以帳密去SELECT ID/Password,有資料就算成功

我是推薦第2種寫法
但是你覺得那個好寫就用那個寫法囉

謝謝你的回復,受益良多,目前的想法與之前的做法偏向於第一種設計,但是目前膠著於api傳回所有帳密後,不知道app端如何去做比對,我把json資料解析完回傳users,但之後就不知道如何著手,無法把users裡面的兩組帳密字串給抓出來做比對
例如
let userID = users[indexPath.row].ID這種形式
以上這種形式我可以把它放到cell中做顯示,卻無法抓出來做比對,麻煩你再給我一些指導了,感謝你!

「但是目前膠著於api傳回所有帳密後,不知道app端如何去做比對」
你這是在用寫web的思維寫app嗎?
看你跟海綿寶寶討論的如此熱烈……我寫的回答怎麼你一點反應都沒有?
是我寫的太艱深難懂嗎?
既然討論線是在這邊,我就把我的回答刪掉直接移過來這邊討論好了。

基本上來說。
你傳送給server驗證。
驗證成功就取回二個東西。
一個叫做驗證token(authorization token,簡稱auth token)另一個叫做更新token(refresh token)
比較常用的就是jwt規範的token。
之後要跟server溝通就全丟這個token來處理。
jwt的token是有時效性的(可能一個小時就過期)
所以過期的token要用refresh token去重新要新的auth token跟新的refresh token
登出的話,就是把token全部清除掉然後回到登入頁面如此而已。
只不過,你說ios,是用swift?objective c?xamarin?還是像是cordova?
不過不管是用那個,驗證後取token都是一般常用的方式。就算不是app而是網頁現在也幾乎都會
使用這樣的登入驗證token方式了。

@可樂快跑
因為目前功力尚淺,大哥所解析的方法好像在我這個app中還應用不到,並不是沒有回應你,真的不好意思!
因為目前的專案的需求沒有要到很高深驗證方式,只有很單純的字串比對,但目前就連字串比對做起來就有點困難了,想說先至少先簡單的做起來再來規劃困難的部分
/images/emoticon/emoticon02.gif

ru822929991
其實這只是個你願意,花上幾個小時就能夠理解的東西。
並不是要花個好幾天才能懂。
再來,你還是沒有告訴我你ios那邊是用什麼語言在寫。

試試看(我沒測過)

//txtID.text 是帳號 textView
//txtPassword.text 是密碼 textView
//users 是 API 回覆回來的 USER 陣列
//判斷是否登入成功
if users.contains(where: {$0.ID == txtID.text && $0.Password == txtPassword.text }) {
   // Login OK
} else {
   // Login Failed
}

Samと可樂快跑
感謝你的回復,目前使用swift撰寫

海綿寶寶
謝謝你的回復,目前使用了你的語法,感覺有一點摸到邊了,但是還是不行,不管打正確或錯誤的帳號密碼都是錯誤的,我是不是有遺漏了什麼

import UIKit

class testloginViewController: UIViewController {
    private let kivaLoanURl = "http://localhost/API/api/USER" //api之url
    //private let kivaLoanURl = 
    private var users = [USER]() //將api 回傳json格式的陣列宣告成變數
    @IBOutlet weak var txtcount: UITextField!
    @IBOutlet weak var txtpaswoerd: UITextField!
    @IBOutlet weak var loginbtn: UIButton!
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func viewWillAppear(_ animated: Bool) {
        navigationController?.isNavigationBarHidden = true
    }
    override func viewDidDisappear(_ animated: Bool) {
        navigationController?.isNavigationBarHidden = false
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    @IBAction func onclickLogin(_ sender: Any) {
       // if users == txtcount.text! && password == txtpaswoerd.text!{
        if users.contains( where: {$0.ID == txtcount.text! && $0.Password == txtpaswoerd.text!})
        {
          print("333333")
        }else{
            let alert = UIAlertController(title: "Alert", message: "ID or Password error", preferredStyle: .alert)
            let ok = UIAlertAction(title: "OK", style: .default, handler: nil)
            
            alert.addAction(ok)
             present(alert, animated: true, completion: nil)
        }
    }
   
    @objc func getlatestUSER(){
        guard let userUrl = URL(string: kivaLoanURl) else{
            return
        }
        
        let request = URLRequest(url: userUrl)
        let task = URLSession.shared.dataTask(with: request, completionHandler: {(data,response,error) -> Void in
            if let error = error {
                print(error)
                return
            }
            if let data = data {
                self.users = self.pardrJsonData(data: data)//轉換給定的JSON格式資料 作為USER物件的陣列
            }
        })
        task.resume()
    }
    func pardrJsonData(data: Data) -> [USER]{
        var users = [USER]()
        do {
            let jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
            //JSONSerialization 類別轉JSON data 結果存 jsonResult
            //解析 json data
            let jsonUSERs = jsonResult?["USER"] as! [AnyObject]  // 驗證此陣列是否有值
            for jsonUSER in jsonUSERs{
                var user = USER()
                user.ID = jsonUSER["ID"] as! String
                user.Password = jsonUSER["Password"] as! String
                users.append(user)
            }        }catch{
                print(error)
        }
        return users
    }
}

以上是我完整的程式碼

你在 viewDidLoad 時就該呼叫 getlatestUSER 了
否則 users 是空值
比對到明年也是失敗

海綿寶寶
真的是太謝謝了,原來忙了一大圈是在那邊遺漏了呼叫!

ru822929991
問題解決就好
另外提醒你一件小事
你之前還有兩個問題
有空時去選個最佳解答
才是對熱心回答的iT邦友的禮貎嘿...

ru822929991
既然你是用swift的話。
我倒是建議可以試試Alamofire跟SwiftyJSON這二個套件。
可以很方便快速的完你要的網路以及處理json的功能。
只是我很好奇你的xcode是用那個版本的?
為什麼還有didReceiveMemoryWarning這個東西?
在xcode10不管是objc還是swift這個函式都已經非必要了。

Samと可樂快跑
好的,我會參考,謝謝你的回覆!

0

小弟只有學android所以我不知道ios是否也是可以這樣做:
利用登入按鈕的觸發去取得textfield的值進行驗證並跳到下一頁

0
Samと可樂快跑
iT邦研究生 2 級 ‧ 2019-03-24 01:07:06

因為沒有刪除回答的功能。
本篇內容轉移至海綿寶寶回答的討論中。

我要發表回答

立即登入回答