webentwicklung-frage-antwort-db.com.de

Swift: Wie Sie sich Cookies für weitere HTTP-Anfragen merken können

Ich arbeite an einer Login-Anwendung. Nach erfolgreichem Login kommt die Antwort mit den Cookie-Daten zurück.
Wie kann ich diese Daten für meine zukünftigen Anfragen verwenden/speichern?
Für Anfänger versuche ich, es in NSHTTPCookieStorage zu speichern. Das funktioniert aber auch nicht .
Login-Methode (teilweise):

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-Methode speichern

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())")
            }
        }
    }

Error:

Cannot invoke 'cookiesWithResponseHeaderFields' with an argument list of type '([NSObject : AnyObject], forURL: NSURL)'
16
Himanshu Yadav

Wenn Sie die Verwendung eines Cookies erkennen, muss der Server den Header Set-Cookie als Antwort auf die Clientanfrage senden. Überprüfen Sie einfach die Kopfzeile als Antwort, und Sie sehen das Set-Cookie-Kopffeld mit einem Cookie darin.

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

Wenn Sie URLSession mit Standard oder Hintergrund URLSessionConfiguration verwenden, müssen Sie keine Änderungen vornehmen, um das Cookie zu speichern. Wenn Sie sich die Dokumentation für default URLSessionConfiguration ansehen, die es so beschreibt,

Die Standardsitzungskonfiguration verwendet einen permanenten festplattenbasierten Cache (außer wenn das Ergebnis in eine Datei heruntergeladen wird) und speichert Anmeldeinformationen im Schlüsselbund des Benutzers. Es speichert auch Cookies (mit der Standardeinstellung ) In demselben gemeinsam genutzten Cookie-Speicher wie NSURLConnection und NSURLDownload-Klassen.

Darüber hinaus können Sie dies in der URLSessionConfiguration-Dokumentation für die Eigenschaft httpCookieStoragehier nachlesen.

Hier ist ein kleiner Code-Ausschnitt, den ich zum Testen des Cookie-Speichers weiter verwenden werde.

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()
}

Mit dem obigen Snippet testen wir zunächst, dass die Standardsitzung den Cookie speichert.

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)
    }
}

Und hier bekommen wir,

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 hat auch eine Eigenschaft httpCookieAcceptPolicy, die Folgendes zitiert:

Diese Eigenschaft bestimmt die Cookie-Akzeptierungsrichtlinie für alle Aufgaben innerhalb von Sitzungen basierend auf dieser Konfiguration.

Der Standardwert ist HTTPCookie.AcceptPolicy.onlyFromMainDocumentDomain. Du kannst es ändern auf eine der Konstanten, die in HTTPCookie.AcceptPolicy definiert sind Aufzählungstyp.

Wenn Sie mehr Kontrolle darüber haben möchten, welche Cookies akzeptiert werden, setzen Sie diesen Wert auf HTTPCookie.AcceptPolicy.never und verwenden Sie dann die allHeaderFields und Cookies (withResponseHeaderFields: for :) -Methoden für Extrahieren Sie Cookies aus dem URL-Antwortobjekt.

Wenn Sie also das Cookie selbst bearbeiten möchten, können Sie die Variable httpCookieAcceptPolicy auf never setzen.

Der folgende Code zeigt, dass das Cookie nicht gespeichert wird, wenn httpCookieAcceptPolicy verwendet wird, um nie,

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)

    }
}

Welche protokolliert Folgendes:

Cookies before request:  []
Cookies after request:  []

Wenn Sie .never für httpCookieStoragePolicy verwenden, speichert das System das Cookie nicht für die gemeinsame Speicherung von Cookies. 

Sie können den Cookie auch selbst speichern, was so aussehen würde.

Den Cookie selbst aufbewahren

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)

    }
}

Und hier ist, was der Code oben auf die Konsole druckt,

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>]

Der obige Code verwendet .never HTTPCookieAcceptPolicy für URLSessionConfiguration. Wir erstellen jedoch ein Cookie aus der Antwort und speichern es selbst im Cookie-Store. 

23
Sandeep

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

Beachten Sie, dass headerFields [String: String] Dictionary ist und der Compiler sich darüber beschwert, dass Sie [NSObject: AnyObject] übergeben.

1
Edward Ashak

für die URLSession-Verbindung können Sie dies verwenden (nachdem Sie Ihre erste Antwort erhalten haben):

var cookies =  URLSession.shared.configuration.httpCookieStorage?.cookies

und Sie können diese Cookies wie folgt verwenden:

var session = URLSession.self
session.shared.configuration.httpCookieStorage?.setCookies(cookies, for: baseurl, mainDocumentURL: baseurl)
    let task = session.shared.dataTask(with: url)
0
iman kazemayni