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
}
}
我是 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
}
}