ログインアプリケーションに取り組んでいます。ログインに成功すると、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)'
Cookieの使用を理解している場合、サーバーはクライアント要求への応答としてヘッダーSet-Cookie
を送信する必要があります。応答のヘッダーを調べるだけで、Cookieが含まれるSet-Cookie
ヘッダーフィールドが表示されます。
https://en.wikipedia.org/wiki/HTTP_cookie#Setting_a_cookie
デフォルトまたはバックグラウンドURLSessionConfiguration
でURLSessionを使用する場合、Cookieを保存するために変更を加える必要はありません。このように説明するデフォルトのURLSessionConfiguration
のドキュメントを見ると、
デフォルトのセッション構成では、永続的なディスクベースのキャッシュが使用され(結果がファイルにダウンロードされる場合を除く)、ユーザーのキーチェーンに資格情報が保存されます。また、NSURLConnectionクラスおよびNSURLDownloadクラスと同じ共有CookieストアにCookie(デフォルト)を保存します。
また、これについては、プロパティ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: []
HttpCookieStoragePolicyに.neverを使用すると、システムは共有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ストアに保存します。
class func cookiesWithResponseHeaderFields(_ headerFields:[String:String]、forURL URL:NSURL)-> [NSHTTPCookie]
HeaderFieldsは[String:String]辞書であり、コンパイラは[NSObject:AnyObject]を渡していると文句を言うことに注意してください。
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)