web-dev-qa-db-ja.com

Swift:さらなるHTTPリクエストのためにCookieを記憶する方法

ログインアプリケーションに取り組んでいます。ログインに成功すると、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)'
17
Himanshu Yadav

Cookieの使用を理解している場合、サーバーはクライアント要求への応答としてヘッダーSet-Cookieを送信する必要があります。応答のヘッダーを調べるだけで、Cookieが含まれるSet-Cookieヘッダーフィールドが表示されます。

https://en.wikipedia.org/wiki/HTTP_cookie#Setting_a_cookie

デフォルトまたはバックグラウンドURLSessionConfigurationでURLSessionを使用する場合、Cookieを保存するために変更を加える必要はありません。このように説明するデフォルトのURLSessionConfigurationのドキュメントを見ると、

デフォルトのセッション構成では、永続的なディスクベースのキャッシュが使用され(結果がファイルにダウンロードされる場合を除く)、ユーザーのキーチェーンに資格情報が保存されます。また、NSURLConnectionクラスおよびNSURLDownloadクラスと同じ共有CookieストアにCookie(デフォルト)を保存します。

また、これについては、プロパティURLSessionConfigurationherehttpCookieStorageドキュメントでさらに読むことができます。

これは、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を操作する場合は、httpCookieAcceptPolicyneverに設定できます。

次のコードが示すように、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ストアに保存します。

25
Sandeep

class func cookiesWithResponseHeaderFields(_ headerFields:[String:String]、forURL URL:NSURL)-> [NSHTTPCookie]

HeaderFieldsは[String:String]辞書であり、コンパイラは[NSObject:AnyObject]を渡していると文句を言うことに注意してください。

1
Edward Ashak

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)
0
iman kazemayni