2012-04-18 19 views
7

Ich muss eine vorhandene REST-API mit .NET (ursprünglich mit Ruby geschrieben) neu schreiben. Aus der Sicht des Clients muss es genauso funktionieren wie die alte API - d. H. Der Client-Code muss nicht geändert werden. Die aktuelle API erfordert die Standardauthentifizierung. Also die alte API aufrufen, funktioniert die folgende perfekt: -ASP.Net Web API - Autorisierungsheader leer

 var wc = new System.Net.WebClient(); 
     var myCache = new CredentialCache(); 
     myCache.Add(new Uri(url), "Basic", new NetworkCredential("XXX", "XXX")); 
     wc.Credentials = myCache; 
     var returnBytes = wc.DownloadData("http://xxxx"); 

(Ich habe die reale URL/Benutzername/Passwort etc aus Sicherheitsgründen ommit).

Jetzt schreibe ich die neue API mit ASP.Net Web API mit MVC4. Ich habe ein seltsames Problem und kann niemanden mit genau dem gleichen Problem finden. Um die Standardauthentifizierung zu unterstützen, habe ich die Richtlinien hier gefolgt:

http://sixgun.wordpress.com/2012/02/29/asp-net-web-api-basic-authentication/

Eine Sache, habe ich den Code „Haken im Handler“ in der Datei Global.asax.cs im Application_Start() Ereignis (das wurde nicht erklärt, so vermutete ich).

Wie auch immer, wenn ich meine API (die ich in IIS bereitgestellt habe) mit dem obigen Code aufrufen, ist die Autorisierung Header immer Null, und das obige schlägt mit 401 Unauthorized. Wenn ich jedoch den Header mit diesem Code manuell setze, funktioniert es einwandfrei - d. H. Der Berechtigungsheader existiert jetzt und ich kann den Benutzer authentifizieren.

private void SetBasicAuthHeader(WebClient request, String userName, String userPassword) 
    { 
     string authInfo = userName + ":" + userPassword; 
     authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo)); 
     request.Headers["Authorization"] = "Basic " + authInfo; 
    } 
    ....... 
    var wc = new System.Net.WebClient(); 
    SetBasicAuthHeader(request, "XXXX", "XXXX"); 
    var returnBytes = wc.DownloadData("http://xxxx"); 

Obwohl das funktioniert, dann ist es nicht gut für mich, weil vorhandene Benutzer der bestehenden API nicht manuell den Header Einstellung gehen werden.

Lesen Sie, wie die Standardauthentifizierung funktioniert, die ursprüngliche Anfrage soll anonym sein, dann wird der Client zurückgegeben 401, dann soll der Client es erneut versuchen. Wenn ich jedoch einen Unterbrechungspunkt in meinen Code einfüge, wird der Code in Antonys Beispiel nie wieder angezeigt. Ich habe erwartet, dass mein Haltepunkt zweimal getroffen wird.

Irgendwelche Ideen, wie ich das zur Arbeit bringen kann?

Antwort

9

Sie erwarten das richtige Verhalten. System.Net.WebClient enthält die Autorisierungsheader nicht automatisch bei der ersten Anfrage. Es sendet sie nur, wenn es durch eine Antwort, die meines Wissens ein 401-Statuscode und ein richtiger WWW-Authenticate-Header ist, richtig herausgefordert wird. Weitere Informationen finden Sie unter here und here.

Ich gehe davon aus, dass Ihr Standardauthentifizierungs-Handler den WWW-Authenticate-Header nicht zurückgibt, und WebClient versucht daher nicht einmal, die Anmeldeinformationen bei einer zweiten Anforderung zu senden. Sie sollten dies in Fiddler oder einem ähnlichen Tool sehen können.

Wenn Ihr Handler so etwas wie dies getan hat, sollten Sie den WebClient Ansatz Arbeits Zeuge:

//if is not authenticated or Authorization header is null 
return base.SendAsync(request, cancellationToken).ContinueWith(task => 
    { 
     var response = task.Result; 
     response.StatusCode = HttpStatusCode.Unauthorized; 
     response.Headers.Add("WWW-Authenticate", "Basic realm=\"www.whatever.com\""); 
     return response; 
    }); 

//else (is authenticated) 
return base.SendAsync(request, cancellationToken); 

Wie Sie bemerkt haben, wenn Sie schließen die Authorization Header bei jeder Anfrage (wie Sie in Ihrem alternativen Ansatz haben), dann Dein Handler arbeitet bereits wie er ist. Es kann also ausreichen - es ist einfach nicht für WebClient und andere Clients, die auf die gleiche Weise arbeiten.

+0

Perfekt - es hat funktioniert! Vielen Dank. – nickthompson