2017-06-30 3 views
3

Die Backend-APIs, mit denen ich arbeite, erfordern ein Token, das mit jeder Anfrage gegen den HTTP-Header-Schlüssel Authorization in diesem Format gesendet wird - Token xxxxxxxxxx.Wie man ein 'Token xxxxxxxxxx' für 'Authorization' im HTTP-Header in URLSession setzt

Im Moment mache ich folgendes.

var getRequest = URLRequest(url: url) 
getRequest.addValue("Token xxxxxxxx", forHTTPHeaderField: "Authorization") 

Das funktioniert manchmal und einige andere Zeiten wird der Header-Feld Authorization abgezogen, wenn die Anforderung aus gesendet wird. Ich habe das mit Charles Proxy überprüft.

Apple's documentation besagt Folgendes.

Ein NSURLSession-Objekt wurde entwickelt, um verschiedene Aspekte des HTTP-Protokolls für Sie zu behandeln. Als Ergebnis sollten Sie die folgenden Header nicht ändern: Berechtigung, Verbindung, Host, WWW-Authenticate

Als Lösung dieses Problems, viele vorschlagen, mit der didReceiveAuthenticationChallenge Delegatmethode für URLSession.

Hier müssen Sie eine URLSession.AuthChallengeDisposition Instanz übergeben, um anzugeben, wie Sie auf die Herausforderung reagieren möchten, und eine URLCredential Instanz, um die Anmeldeinformationen zur Beantwortung der Authentifizierungsanforderung zu übergeben.

Ich weiß nicht, wie und ob ich eine URLCredential Instanz erstellen kann, die für das Header-Feld Authorization hinzufügen wird.

Kann jemand sachkundiger bitte helfen Sie mir, wie man das löst?

PS - Alle in dieser Frage genannten Code ist in Swift 3. This question fragt etwas, was ich ähnlich habe. Aber die Antworten, die dort gegeben werden, funktionieren nicht für mich. Und einige der Fragen, die unter den Fragen gestellt wurden, die Apple nicht erlauben, Header für Authorization hinzuzufügen, sind unbeantwortet geblieben.

Bearbeiten:

Buchung relevanten Code.

var getRequest = URLRequest(url: url) 
getRequest.httpMethod = "GET" 
getRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") 
getRequest.addValue("application/json", forHTTPHeaderField: "Accept") 
let token = DataProvider.sharedInstance.token 
getRequest.addValue("Token \(token)", forHTTPHeaderField: "Authorization") 
let getTask = URLSession.shared.dataTask(with: getRequest) { (data, response, error) in 
     if let data = data { 
      print("--------GET REQUEST RESPONSE START--------") 
      print("CODE: \((response as? HTTPURLResponse)?.statusCode ?? 0)") 
      print("Response Data:") 
      print(String(data: data, encoding: .utf8) ?? "") 
      print("--------GET REQUEST RESPONSE END--------") 
     } 
} 
getTask.resume() 

Hier kann ich bestätigen, dass das Kopfzeilenfeld für 'Authorization' zum Header-Wörterbuch der Anfrage hinzugefügt wird.

Aber wenn ich überprüfe, welche Anfrage den Server trifft, fehlt das Header-Feld für 'Authorization'. Irgendwelche Gedanken?

+1

'request.addValue (Wert, forHTTPHeaderField: key)' funktioniert nach meiner Erfahrung zuverlässig. Ich vermute, dass Ihr Code in "Problemsituationen" nicht für die Anfrage aufgerufen wird. Bitte posten Sie relevanteren Code, um dies herauszufinden. – shallowThought

+0

@ShallowThought Ich habe relevanten Code hinzugefügt. Bitte sehen Sie, ob Sie etwas falsch finden, was ich getan habe. –

Antwort

3

Ich lief genau in dieses Problem und entdeckte, dass mein Fehlen eines Schrägstrichs, /, das Problem war.

Der Server hat eine Antwort 301 Redirect zurückgeschickt. URLSession folgt automatisch der Umleitung, wird aber auch den Header Authorization fallen lassen. Dies ist wahrscheinlich auf den "speziellen Status" Authorization zurückzuführen. Nach URLSessionConfiguration ‚s documentation:

Ein URLSession Objekt für Sie verschiedene Aspekte des HTTP-Protokolls zu handhaben soll.Als Ergebnis sollten Sie die folgenden Header nicht ändern:

  • Authorization
  • Verbindung
  • Host-
  • WWW-Authenticate

Wenn der Authorization Header erforderlich ist, implementieren urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:) von URLSessionTaskDelegate. Dieser Methode wird die neue Anforderung für die Weiterleitung übergeben, sodass Sie die Kopfzeile hinzufügen können.

z.B.

class APIClient: URLSessionTaskDelegate { 
    let session: URLSession! 
    initializeSession() { 
     // Create a new session with APIClient as the delegate 
     session = URLSession(configuration: URLSessionConfiguration.default, 
          delegate: self, 
          delegateQueue: nil) 
    } 

    // Perform the request 
    func fetchRecords(handler:() => void) { 
     var request = URLRequest(url: URL(string: "http://127.0.0.1:8000/api/employee/records")!) 
     request.setValue(retrieveToken(), forHTTPHeaderField: "Authorization") 
     session.dataTask(with: request, completionHandler: handler).resume() 
    } 

    // Implement URLSessionTaskDelegate's HTTP Redirection method 
    func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) { 
     // Create a mutable copy of the new request, add the header, call completionHandler 
     var newRequest = request 
     newRequest.addValue(retrieveToken(), forHTTPHeaderField: "Authorization") 
     completionHandler(newRequest) 
    } 
} 

WICHTIGER HINWEIS!

Es ist eine schlechte Idee, blind auf eine Weiterleitung zu vertrauen. Sie sollten sicherstellen, dass die URL, an die Sie weitergeleitet werden, dieselbe Domain ist wie die ursprüngliche Anfrage. Ich habe das aus meinem Codebeispiel der Kürze halber weggelassen.

Verwandte Themen