我正在处理登录应用程序。成功登录后,响应cookie数据
如何为将来的请求使用/保存此数据?
对于初学者,我试图将其保存在NSHTTPCookieStorage
中。但这也行不通。
登录方式(部分):
let task = session.dataTaskWithRequest(request) { (data, responseData, error) -> Void in
if let response = responseData as? NSHTTPURLResponse {
statusCode = response.statusCode
print("Response code: \(statusCode)")
}
var json: NSDictionary?
do {
json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
} catch {
print(error)
err = error
}
if(statusCode != 200) {
let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Error could not parse JSON: '\(jsonStr)'")
}
else {
print("Everything Looks good: \(responseData)")
self.setCookies(responseData!)
self.shouldPerformSegueWithIdentifier("showHomeController", sender: self)
}
}
task?.resume()
保存Cookie方法
private func setCookies(response: NSURLResponse) {
if let httpResponse = response as? NSHTTPURLResponse {
let cookies = NSHTTPCookie.cookiesWithResponseHeaderFields(httpResponse.allHeaderFields, forURL: response.URL!) as! [NSHTTPCookie]
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookies(cookies, forURL: response.URL!, mainDocumentURL: nil)
for cookie in cookies {
var cookieProperties = [String: AnyObject]()
cookieProperties[NSHTTPCookieName] = cookie.name
cookieProperties[NSHTTPCookieValue] = cookie.value()
cookieProperties[NSHTTPCookieDomain] = cookie.domain
cookieProperties[NSHTTPCookiePath] = cookie.path
cookieProperties[NSHTTPCookieVersion] = NSNumber(integer: cookie.version)
cookieProperties[NSHTTPCookieExpires] = NSDate().dateByAddingTimeInterval(31536000)
let newCookie = NSHTTPCookie(properties: cookieProperties)
NSHTTPCookieStorage.sharedHTTPCookieStorage().setCookie(newCookie!)
println("name: \(cookie.name) value: \(cookie.value())")
}
}
}
错误:
Cannot invoke 'cookiesWithResponseHeaderFields' with an argument list of type '([NSObject : AnyObject], forURL: NSURL)'
答案 0 :(得分:24)
如果您意识到cookie的使用,服务器必须发送标头Set-Cookie
以响应客户端请求。只需检查标题作为响应,您将看到Set-Cookie
标题字段,其中包含Cookie。
https://en.wikipedia.org/wiki/HTTP_cookie#Setting_a_cookie
如果您使用默认或背景URLSessionConfiguration
的URLSession,则无需进行任何更改以保存Cookie。如果您查看默认URLSessionConfiguration
的文档,其描述如下,
默认会话配置使用基于磁盘的持久缓存 (除非将结果下载到文件中)并存储 用户钥匙串中的凭据。它还存储cookie(通过 默认情况下)与NSURLConnection和。相同的共享cookie存储区 NSURLDownload类。
此外,您可以在财产URLSessionConfiguration
here的httpCookieStorage
文档中进一步了解相关内容。
这是一小段代码,我将进一步用它来测试cookie存储。
let sessionConfiguration = URLSessionConfiguration.ephemeral
sessionConfiguration.httpCookieAcceptPolicy = .never
let customSession = URLSession(configuration: sessionConfiguration)
enum Result {
case success(HTTPURLResponse, Data)
case failure(Error)
}
func readCookie(forURL url: URL) -> [HTTPCookie] {
let cookieStorage = HTTPCookieStorage.shared
let cookies = cookieStorage.cookies(for: url) ?? []
return cookies
}
func deleteCookies(forURL url: URL) {
let cookieStorage = HTTPCookieStorage.shared
for cookie in readCookie(forURL: url) {
cookieStorage.deleteCookie(cookie)
}
}
func storeCookies(_ cookies: [HTTPCookie], forURL url: URL) {
let cookieStorage = HTTPCookieStorage.shared
cookieStorage.setCookies(cookies,
for: url,
mainDocumentURL: nil)
}
func executeURLRequest(url: URL, inSession session: URLSession = .shared, completion: @escaping (Result) -> Void) {
let task = session.dataTask(with: url) { data, response, error in
if let response = response as? HTTPURLResponse,
let data = data {
completion(.success(response, data))
return
}
if let error = error {
completion(.failure(error))
return
}
let error = NSError(domain: "com.cookiesetting.test", code: 101, userInfo: [NSLocalizedDescriptionKey: "Unknown error occurred"])
completion(.failure(error))
}
task.resume()
}
使用上面的代码段,我们首先测试默认会话是否保存了Cookie。
var cookies = readCookie(forURL: googleURL)
print("Cookies before request: ", cookies)
executeURLRequest(url: googleURL) { result in
if case .success (let data) = result {
cookies = readCookie(forURL: googleURL)
print("Cookies after request: ", cookies)
deleteCookies(forURL: googleURL)
cookies = readCookie(forURL: googleURL)
print("Cookies after deletion: ", cookies)
}
}
而且,这就是我们得到的,
Cookies before request: []
Cookies after request: [<NSHTTPCookie
version:0
name:1P_JAR
value:2018-09-26-15
expiresDate:'2018-10-26 15:39:46 +0000'
created:'2018-09-26 15:39:46 +0000'
sessionOnly:FALSE
domain:.google.com
partition:none
sameSite:none
path:/
isSecure:FALSE
path:"/" isSecure:FALSE>, <NSHTTPCookie
version:0
name:NID
value:139=E3g4bKNRGcYoeFuaECpfsx_Efp64xONmVwcJS7f7PuZe8LayS5ZkGuz3f7z6eq7zoBm2z-opTvzX8YPzn8v1ebjH6iyt5-6yDYm9RE6XhXwHCZWs98_j7nb11u2EPnHI
expiresDate:'2019-03-28 15:39:46 +0000'
created:'2018-09-26 15:39:46 +0000'
sessionOnly:FALSE
domain:.google.com
partition:none
sameSite:none
path:/
isSecure:FALSE
isHTTPOnly: YES
path:"/" isSecure:FALSE isHTTPOnly: YES>]
Cookies after deletion: []
URLSessionConfiguration
还有一个属性httpCookieAcceptPolicy
,引用以下内容:
此属性确定其中所有任务的cookie接受策略 基于此配置的会话。
默认值为 HTTPCookie.AcceptPolicy.onlyFromMainDocumentDomain。你可以改变它 到HTTPCookie.AcceptPolicy中定义的任何常量 枚举类型。
如果您想更直接地控制接受哪些Cookie,请设置 这个值为HTTPCookie.AcceptPolicy.never然后使用 allHeaderFields和cookies(withResponseHeaderFields:for :)方法 自己从URL响应对象中提取cookie。
因此,如果您希望自己操纵Cookie,可以将httpCookieAcceptPolicy
设置为never
。
以下代码显示,从未使用httpCookieAcceptPolicy时未存储Cookie
var cookies = readCookie(forURL: googleURL)
print("Cookies before request: ", cookies)
executeURLRequest(url: googleURL, inSession: customSession) { result in
if case .success (let data) = result {
cookies = readCookie(forURL: googleURL)
print("Cookies after request: ", cookies)
}
}
记录以下内容;
Cookies before request: []
Cookies after request: []
您可以看到使用.never for httpCookieStoragePolicy,系统不会将cookie存储到共享cookie存储。
你也可以自己存储cookie,看起来像这样,
自行存储Cookie
deleteCookies(forURL: googleURL)
var cookies = readCookie(forURL: googleURL)
print("Cookies before request: ", cookies)
executeURLRequest(url: googleURL, inSession: customSession) { result in
if case let .success (response, data) = result {
guard let cookiesResponseHeader = response.allHeaderFields["Set-Cookie"] else {
return
}
cookies = readCookie(forURL: googleURL)
print("Cookies after request: ", cookies)
let responseCookies = HTTPCookie.cookies(withResponseHeaderFields: response.allHeaderFields as! [String: String], for: googleURL)
storeCookies(responseCookies, forURL: googleURL)
cookies = readCookie(forURL: googleURL)
print("Cookies after storing: ", cookies)
}
}
以下是上面代码打印到控制台的内容,
Cookies before request: []
Cookies after request: []
Cookies after storing: [<NSHTTPCookie
version:0
name:1P_JAR
value:2018-09-26-18
expiresDate:'2018-10-26 18:35:23 +0000'
created:'2018-09-26 18:35:23 +0000'
sessionOnly:FALSE
domain:.google.com
partition:none
sameSite:none
path:/
isSecure:FALSE
path:"/" isSecure:FALSE>, <NSHTTPCookie
version:0
name:NID
value:139=D7GTUazWfeaB5Bcu1wN5I_Il2k6xALNiRZDX_DN9totQbnrP31gE0GzlsjCHDISUv8ulPq9G8Yu1p-GsZcVRw2fnrBROih-vtAVBic5UXFKUkG_ZbFQYKFprr4MPHDGS
expiresDate:'2019-03-28 18:35:23 +0000'
created:'2018-09-26 18:35:23 +0000'
sessionOnly:FALSE
domain:.google.com
partition:none
sameSite:none
path:/
isSecure:FALSE
isHTTPOnly: YES
path:"/" isSecure:FALSE isHTTPOnly: YES>]
上面的代码使用.never
HTTPCookieAcceptPolicy到URLSessionConfiguration,但我们从响应中创建cookie并自己将它存储到cookie存储区。
答案 1 :(得分:1)
class func cookiesWithResponseHeaderFields(_ headerFields:[String: 字符串],forURL网址:NSURL) - &gt; [NSHTTPCookie]
请注意,headerFields是[String:String] Dictionary,编译器抱怨你正在传递[NSObject:AnyObject]
答案 2 :(得分:-1)
对于URLSession连接,您可以使用此功能(在收到第一个回复后):
var cookies = URLSession.shared.configuration.httpCookieStorage?.cookies
你可以像这样使用这些cookie:
var session = URLSession.self
session.shared.configuration.httpCookieStorage?.setCookies(cookies, for: baseurl, mainDocumentURL: baseurl)
let task = session.shared.dataTask(with: url)