2012-04-09 11 views
18

Ich versuche, einen HttpClient für einen Dienst eines Drittanbieters zu verwenden, der eine einfache HTTP-Authentifizierung erfordert. Ich benutze die AuthenticationHeaderValue. Hier ist, was ich mit so weit habe kommen:HttpClient-Authentifizierungsheader wird nicht gesendet

HttpRequestMessage<RequestType> request = 
    new HttpRequestMessage<RequestType>(
     new RequestType("third-party-vendor-action"), 
     MediaTypeHeaderValue.Parse("application/xml")); 
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
     string.Format("{0}:{1}", "username", "password")))); 

var task = client.PostAsync(Uri, request.Content); 
ResponseType response = task.ContinueWith(
    t => 
    { 
     return t.Result.Content.ReadAsAsync<ResponseType>(); 
    }).Unwrap().Result; 

Es sieht aus wie die POST-Aktion funktioniert gut, aber ich habe nicht die Daten wieder ich erwarte. Durch einige Versuche und Fehler, und schließlich mit Fiddler, um den rohen Verkehr zu schnüffeln, entdeckte ich, dass der Berechtigungsheader nicht gesendet wurde.

Ich habe this gesehen, aber ich denke, ich habe das Authentifizierungsschema als Teil des AuthenticationHeaderValue Konstruktors angegeben.

Gibt es etwas, das ich vermisst habe?

Antwort

25

Ihr Code sieht aus wie es funktionieren soll - ich erinnere mich, in ein ähnliches Problem bei der Ausführung des Authorization-Header Einstellung und gelöst durch eine Headers.Add tun(), anstatt es zu setzen:

request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", "password")))); 

UPDATE: Es sieht so aus, als wenn Sie eine Anfrage machen. Inhalt, nicht alle Kopfzeilen werden im Inhaltsobjekt wiedergegeben. Sie können dies sehen, indem Sie request.Headers vs request.Content.Headers überprüfen. Eine Sache, die Sie vielleicht ausprobieren möchten, ist, SendAsync anstelle von PostAsync zu verwenden. Zum Beispiel:

HttpRequestMessage<RequestType> request = 
    new HttpRequestMessage<RequestType>(
     new RequestType("third-party-vendor-action"), 
     MediaTypeHeaderValue.Parse("application/xml")); 

request.Headers.Authorization = 
    new AuthenticationHeaderValue(
     "Basic", 
     Convert.ToBase64String(
      System.Text.ASCIIEncoding.ASCII.GetBytes(
       string.Format("{0}:{1}", "username", "password")))); 

request.Method = HttpMethod.Post; 
request.RequestUri = Uri; 
var task = client.SendAsync(request); 

ResponseType response = task.ContinueWith(
    t => 
     { return t.Result.Content.ReadAsAsync<ResponseType>(); }) 
     .Unwrap().Result; 
+0

ich versuchte, und etwas ähnliches mit 'request.Headers.Authorization' mit den gleichen Ergebnissen. Es hat mich mit ein bisschen Kopf-Scratcher verlassen, da ich nicht ganz sicher bin, was ich als nächstes versuchen soll. Ich weiß, dass die MVC4-Beta und die 4.5-Vorschau für einige Dinge direkt inkompatibel sind - ich frage mich, ob das etwas damit zu tun hat? – Ross

+0

Ihr Update scheint zumindest den Berechtigungsheader zu senden. Ich bin noch nicht in der Lage, Daten vom Third-Party-Service noch zu erhalten (wahrscheinlich etwas anderes falsch in der Anfrage Körper, die ich verpasst habe), aber zumindest die richtigen Header gehen über die Leitung. Es ist ein Anfang. Vielen Dank! – Ross

+0

ASCII oder UTF-8? Siehe http://stackoverflow.com/questions/11743160/how-doi-i-decode-and-decode-a-base64-string. – Philippe

17

Versuchen Sie, den Header auf dem Client:

DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password)))); 

Dies funktioniert für mich.

+1

Das würde wahrscheinlich funktionieren, aber es würde die Autorisierungsheader für alle Anfragen setzen, nicht wahr? Das ist nicht wünschenswert. – Ross

+2

Für alle Anfragen, die mit dieser Instanz eines Clients gemacht werden, ja. Verwenden Sie denselben Client für den Zugriff auf Endpunkte mit unterschiedlichen Authentifizierungsschemas? D. h., Setzen Sie die BaseAddress auf der Client-Instanz oder nicht? –

15

Dies würde auch funktionieren, und Sie würden nicht mit den base64 String-Konvertierungen zu tun haben:

var handler = new HttpClientHandler(); 
handler.Credentials = new System.Net.NetworkCredential("username", "password"); 
var client = new HttpClient(handler); 
... 
+0

viel sauberere Lösung als die UID: PWD-Kombination zu kodieren. –

2

Eigentlich ist Ihr Problem mit PostAsync - Sie sollten SendAsync verwenden. In Ihrem Code - client.PostAsync(Uri, request.Content); sendet nur den Inhalt der Anfrage Nachricht Header sind nicht enthalten. Der richtige Weg ist:

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url) 
{ 
    Content = content 
}; 
message.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials); 
httpClient.SendAsync(message); 
+0

Tausend Mal danke. Ich habe Stunden damit verbracht, Header an den HttpClient anzuhängen und GetAsync und PostAsync usw. zu verwenden, und im Allgemeinen finde ich WebAPI ein Problem (gib mir ServiceStack !!) –