Swift 不接受 NSURLSession NSURLRequest Cookie

Swift NSURLSession NSURLRequest Cookies are not accepted

我是 swift 和 OS X 编程的新手。对于我的第一步,我想创建一个命令行工具,它将我登录到我的移动运营商的网络界面,然后显示我剩余的数据量。我开始围绕 NSURLSession 编写一个包装器,以使事情对我来说更容易。

问题:我的程序不接受 cookie。

我尝试了很多方法,还在会话对象上设置了 cookie 策略,但没有任何改变。如何让我的程序接受 cookie 以及如何在后续请求中使用它们?

HttpClient.swift:

import Foundation

class HttpClient {

    private var url: NSURL!
    private var session: NSURLSession

    internal init(url: String) {
        self.url = NSURL(string: url)
        self.session = NSURLSession.sharedSession()
        session.configuration.HTTPShouldSetCookies = true
        session.configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicy.OnlyFromMainDocumentDomain
        session.configuration.HTTPCookieStorage?.cookieAcceptPolicy = NSHTTPCookieAcceptPolicy.OnlyFromMainDocumentDomain
    }

    internal func sendGet() -> String {
        var ready = false
        var content: String!
        var request = NSMutableURLRequest(URL: self.url)

        var task = session.dataTaskWithRequest(request) {
            (data, response, error) -> Void in
            content = NSString(data: data, encoding: NSASCIIStringEncoding) as! String
            ready = true
        }
        task.resume()
        while !ready {
            usleep(10)
        }
        if content != nil {
            return content
        } else {
            return ""
        }
    }

    internal func sendPost(params: String) -> String {
        var ready = false
        var content: String!
        var request = NSMutableURLRequest(URL: self.url)

        request.HTTPMethod = "POST"
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.HTTPBody = params.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)
        request.HTTPShouldHandleCookies = true

        var task = session.dataTaskWithRequest(request) {
            (data, response, error) -> Void in
            content = NSString(data: data, encoding: NSASCIIStringEncoding) as! String
            ready = true
        }
        task.resume()
        while !ready {
            usleep(10)
        }
        if content != nil {
            return content
        } else {
            return ""
        }
    }

    internal func setUrl(url: String) {
        self.url = NSURL(string: url)
    }
}

main.swift

import Foundation

let loginPage = "https://service.winsim.de/"
let dataPage = "https://service.winsim.de/mytariff/invoice/showGprsDataUsage"

var hc = HttpClient(url: loginPage)
println(hc.sendPost("usernameField=username&passwordfield=password"))
hc.setUrl(dataPage)
println(hc.sendGet())

问题已解决

事实上,上面的代码接受了cookies。我尝试登录到另一个站点并且它有效。登录也持续存在。那么,为什么它不适用于我的运营商的网站?

愚蠢的我,我的运营商有 CSRF 保护和其他我没有注意的隐藏表单字段。因此,登录不起作用。现在我知道怎么解决了。

对于任何感兴趣的人,我会 post 我更新的 HttpClient.swift 文件,我希望它更整洁一些。

请随时评论我的代码并给我改进的提示。

import Foundation

public class HttpClient {

    private var session: NSURLSession
    private var request: NSMutableURLRequest

    public init(url: String) {
        self.session = NSURLSession.sharedSession()
        session.configuration.HTTPShouldSetCookies = true
        session.configuration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicy.OnlyFromMainDocumentDomain
        session.configuration.HTTPCookieStorage?.cookieAcceptPolicy = NSHTTPCookieAcceptPolicy.OnlyFromMainDocumentDomain
        self.request = NSMutableURLRequest(URL: NSURL(string: url)!)
    }

    public func send() -> String {
        var ready = false
        var content: String!

        var task = session.dataTaskWithRequest(self.request) {
            (data, response, error) -> Void in
            content = NSString(data: data, encoding: NSASCIIStringEncoding) as! String
            ready = true
        }
        task.resume()
        while !ready {
            usleep(10)
        }
        if content != nil {
            return content
        } else {
            return ""
        }
    }

    public func setUrl(url: String) -> HttpClient {
        self.request.URL = NSURL(string: url)
        return self
    }

    public func getMethod() -> String {
        return self.request.HTTPMethod
    }

    public func setMethod(method: String) -> HttpClient {
        self.request.HTTPMethod = method
        return self
    }

    public func addFormData(data: Dictionary<String, String>) -> HttpClient {
        var params: String = ""
        var ctHeader: String? = self.request.valueForHTTPHeaderField("Content-Type")
        let ctForm: String = "application/x-www-form-urlencoded"

        if(data.count > 0) {
            for(name, value) in data {
                params += name + "=" + value + "&"
            }

            params = params.substringToIndex(params.endIndex.predecessor())
            self.request.HTTPBody = params.dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)

            if ctHeader != nil {
                self.request.setValue(ctForm, forHTTPHeaderField: "Content-Type")
            }
        }

        return self
    }

    public func removeFormData() -> HttpClient {
        self.request.setValue("text/html", forHTTPHeaderField: "Content-Type")
        self.request.HTTPBody = "".dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: false)

        return self
    }
}