簡體   English   中英

如何使用 NSURLSession 復制 POST 登錄

[英]How to replicate POST login with NSURLSession

我正在嘗試編寫一個 iOS 應用程序作為我的城市圖書館網站的個人前端。 實際上,我希望我的應用程序可以隱形訪問圖書館的網頁,輸入我的用戶名和密碼,然后發送 HTTP 請求以隱形瀏覽圖書館的 Web 界面以獲取我的已借出項目列表,在到期日附近更新項目,等等。

第一步是能夠發送我的用戶名和密碼。 我已將圖書館的登錄頁面精簡為以下內容:

<html>
<body>
    <form action="http://brown.ent.sirsi.net/client/en_US/home/search/patronlogin.loginpageform/TRAINING" method="post">
        <input name="t:ac" type="hidden" value="http:$002f$002fbrown.ent.sirsi.net"></input>
        <input name="t:formdata" type="hidden" value="gFJQUIXDSUXVXoGv49wm3q8cIUQ=:H4sIAAAAAAAAAFvzloG1XJ5Btjg1sSg5Qz8gsaQoP88nPz0zzyorvrQ4tSgvMTe1uIjBNL8oXS+xIDE5I1WvJLEgtbikqNJULzm/KDUnM0kvKbE4Vc8xCSiYmFzilpmak6ISnFpSWqAaepj7oejxP0wMjD4M3Mn5eUDTc/yAJpYwCPlkJZYl6uck5qXrB5cUZealW1cUlDBwIWwlxlmOpDoroCg/ObW4OLg0KTezuDgzP+/wuhSTtG/zzjExMFQU4LSyILG4uDy/KKW4kKGOgQHsTJgQQT0gLazl0gySWFRlZKakpOYBPeKA1yPJ+bkF+XmpeSXFeh5gHZj+iGpXEK6Q3sGGEdQg6xlBQcsGsQyHS4pBJpWQ4hKw3SWYLpkZ/Ely65YWZyYGJh8GjuScTKBqT3AogFyWmpOaCxRAcRkHxPJ4AyQmABiJtLaZAgAA"></input>
        Library Card #: <input name="j_username" value = "29878001234567" type="text"></input><br/>
        PIN: <input name="j_password" value="1234" type="text"></input><br/>
        <input name="hidden" value="SYMWS" type="hidden"></input>
        <input type="submit"></input>
    </form>
</body>
</html>

當我從硬盤打開這個 HTML 文件,輸入我的真實借書證號碼和密碼並提交表格時,我成功登錄了圖書館系統。 當我只用上面代碼中的虛擬號碼點擊“提交”時,我會收到“登錄失敗”屏幕,就像我應該的那樣。

我試圖在我的 Swift 代碼中模仿這一點,如下所示:

func loginToLibrary() {
    let request = NSMutableURLRequest(URL: NSURL(string: "http://brown.ent.sirsi.net/client/en_US/home/search/patronlogin.loginpageform/TRAINING")!)
    request.HTTPMethod = "POST"
    var postString = "t:ac=http:$002f$002fbrown.ent.sirsi.net"
    postString += "&t:formdata=gFJQUIXDSUXVXoGv49wm3q8cIUQ=:H4sIAAAAAAAAAFvzloG1XJ5Btjg1sSg5Qz8gsaQoP88nPz0zzyorvrQ4tSgvMTe1uIjBNL8oXS+xIDE5I1WvJLEgtbikqNJULzm/KDUnM0kvKbE4Vc8xCSiYmFzilpmak6ISnFpSWqAaepj7oejxP0wMjD4M3Mn5eUDTc/yAJpYwCPlkJZYl6uck5qXrB5cUZealW1cUlDBwIWwlxlmOpDoroCg/ObW4OLg0KTezuDgzP+/wuhSTtG/zzjExMFQU4LSyILG4uDy/KKW4kKGOgQHsTJgQQT0gLazl0gySWFRlZKakpOYBPeKA1yPJ+bkF+XmpeSXFeh5gHZj+iGpXEK6Q3sGGEdQg6xlBQcsGsQyHS4pBJpWQ4hKw3SWYLpkZ/Ely65YWZyYGJh8GjuScTKBqT3AogFyWmpOaCxRAcRkHxPJ4AyQmABiJtLaZAgAA"
    postString += "&j_username=29878001234567"
    postString += "&j_password=1234"
    postString += "&hidden=SYMWS"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
        guard error == nil && data != nil else {
            print("error=\(error)")
            return
        }

        if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }

        let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
        print("response to login attempt = \(responseString)")
    }
    task.resume()
}

但是,當我運行 Swift 代碼時,控制台會打印以下內容:

response to login attempt = Optional(<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml"><head><link rel="shortcut icon" href="/client/assets/4.5.03/ctx/favicon.ico" type="image/vnd.mircrosoft.icon" id="favicon"/><title>Unexpected Error</title><link type="text/css" rel="stylesheet" href="/client/assets/4.5.03/core/default.css"/><meta content="Apache Tapestry Framework (version 5.3.7)" name="generator"/></head><body><div id="exception"><h1>Unexpected Error</h1><div class="pageheading">The system encountered an error while processing the following request:</div><div class="url">/en_US/home/search/patronlogin.loginpageform/TRAINING</div><h2>Error Summary</h2><div class="cause">java.io.IOException: Client data associated with the current request appears to have been tampered with (the HMAC signature does not match).</div><div class="timestamp">Wed May 25 22:51:42 CDT 2016</div></div></body></html>)

在瀏覽器中解釋為:


意外的錯誤

意外的錯誤

系統在處理以下請求時遇到錯誤:/en_US/home/search/patronlogin.loginpageform/TRAINING

錯誤摘要

java.io.IOException:與當前請求關聯的客戶端數據似乎已被篡改(HMAC 簽名不匹配)。2016 年 5 月 25 日星期三 22:51:42 CDT)


誰能幫我弄清楚我的 Swift 代碼發送的 POST 請求與我的瀏覽器從上面的精簡網頁發送的 POST 請求有何不同?

對於它的價值,如果我更改t:formdata輸入的值,我可以從我的精簡網頁在瀏覽器中獲得相同的錯誤(HMAC 簽名不匹配)。 我已經嘗試將= (大約 30 個字符到t:formdata值中)百分比編碼為%3D ,甚至將/編碼為%2F ,但這沒有幫助。

您嘗試發布的站點正在使用 HMAC 進行身份驗證。

簡短回答:你無法完成你正在嘗試的事情。 您需要做一些研究來解決 HMAC。

長答案: HMAC(基於散列的消息驗證碼)是散列函數與密鑰一起應用於消息正文的產物。 因此,不是隨 Web 服務請求發送用戶名和密碼,而是發送私鑰的一些標識符和 HMAC。 當服務器收到請求時,它會查找用戶的私鑰並使用它為傳入的請求創建 HMAC。 如果隨請求提交的 HMAC 與服務器計算的 HMAC 匹配,則該請求通過身份驗證。

有兩大優勢。 第一個是 HMAC 允許您驗證密碼(或私鑰),而無需用戶將其嵌入到請求中,第二個是 HMAC 還驗證請求的基本完整性。 如果攻擊者在傳輸過程中以任何方式操縱請求,簽名將不匹配並且請求將無法通過身份驗證。 這是一個巨大的勝利,特別是如果 Web 服務請求不是通過安全的 HTTP 連接發出的。

查看此鏈接以獲取有關 HMAC 的更多信息。

您發布到 Symphony 的數據缺少 URL 編碼,我遇到了您遇到的相同問題。 這就是 Symphony 錯誤 t:formdata 的原因

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM