2015-05-13 9 views
12

Sto provando a comunicare con un client WebAPI self-hosted utilizzando HttpClient. Il cliente è stato creato con il seguente codice:HTTPClient che ottiene due 401 prima del successo (invio di token errati)

HttpClientHandler clientHandler = new HttpClientHandler() 
{ 
    UseDefaultCredentials = true, 
    PreAuthenticate = true 
}; 
var client = new HttpClient(clientHandler); 

sul lato server abbiamo impostato:

HttpListener listener = (HttpListener)app.Properties[typeof(HttpListener).FullName]; 
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication; 

nel file Startup.

Il problema è che ottengo due errori (o uno dopo la preautenticazione) 401 prima che la richiesta venga elaborata.

Nel violinista sequenza si presenta così:

First request: 
Authorization: Negotiate TlRMTVNTUAABAAAAl7II4gcABwAxAAAACQAJACgAAAAGAbEdAAAAD1dTMTEzLTEyMFNXVC0xMTM= 
Answer: 
WWW-Authenticate: Negotiate TlRMTVNTUAACAAAADgAOADgAAAAVwonisrQOBMTKHhKwCkgCAAAAAJoAmgBGAAAABgGxHQAAAA9TAFcAVAAtADEAMQAzAAIADgBTAFcAVAAtADEAMQAzAAEAEgBXAFMAMQAxADMALQAxADIAMAAEABYAcwB3AHQALQAxADEAMwAuAGwAbwBjAAMAKgBXAFMAMQAxADMALQAxADIAMAAuAHMAdwB0AC0AMQAxADMALgBsAG8AYwAFABYAQQBMAEQASQA5ADkAOQAuAGwAbwBjAAcACACkGh0XVY3QAQAAAAA= 

Second request (succeeds): 
Authorization: Negotiate TlRMTVNTUAADAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAAAAAAFgAAAAAAAAAWAAAAAAAAABYAAAAFcKI4gYBsR0AAAAPfJafWSuLL0sAXYtWCynOqg== 

Allora, perché non è il mio client che invia la corretta autorizzazione gettone la prima volta, ma sempre ha bisogno di questo approccio in due tempi?

+0

si prega di condividere l'autenticazione Handler –

+0

Eventuali duplicati di http://stackoverflow.com/questions/24021413/can-i -make-httpwebrequest-include-windows-credentials-without-waiting-for-a-401 – Mike

+0

Hai parlato di due 401, ma hai mostrato solo una richiesta non riuscita. Potresti mostrare un esempio completo di richiesta/risposta (fail), richiesta/risposta (fail), richiesta/risposta (successo)? –

risposta

10

Quello che stiamo vivendo è normale, questo è come funziona lo schema di autenticazione NTLM.

1: C --> S GET ... 

2: C <-- S 401 Unauthorized 
       WWW-Authenticate: NTLM 

3: C --> S GET ... 
       Authorization: NTLM <base64-encoded type-1-message> 

4: C <-- S 401 Unauthorized 
       WWW-Authenticate: NTLM <base64-encoded type-2-message> 

5: C --> S GET ... 
       Authorization: NTLM <base64-encoded type-3-message> 

6: C <-- S 200 Ok 
  1. il client invia una richiesta GET al server.
  2. Poiché è necessario essere autenticati per accedere alla risorsa richiesta, il server restituisce una risposta 401 Unathorized e notifica il client nell'intestazione WWW-Authenticate che supporta l'autenticazione NTLM. Quindi questo è dove si ottiene il primo codice di risposta 401.
  3. Il client invia il nome di dominio e il nome utente al server nell'intestazione Authorization. Si noti che basandosi esclusivamente su queste informazioni il client non può ancora essere autenticato.
  4. Il server invia una richiesta al client. Si tratta di un numero generato in modo casuale chiamato nonce. Qui è dove ottieni il tuo secondo codice di risposta 401.
  5. Il client restituisce una risposta alla sfida del server, utilizzando l'hash della sua password per crittografare il numero casuale.
  6. Il server invia il nome utente del client, la richiesta inviata al client e la risposta ricevuta dal client al controller di dominio. Usando il nome utente il controller di dominio recupera l'hash della password dell'utente e crittografa la sfida con esso. Se il risultato corrisponde alla risposta inviata dal client, il client viene autenticato e il server restituisce un codice di risposta 200 e la risorsa richiesta al client.
0

il comportamento predefinito in cui invia solo le credenziali dopo aver ricevuto una risposta HTTP 401 non autorizzata.

Aggiungere manualmente l'intestazione delle credenziali sembra essere la migliore soluzione disponibile.

More details in this post

+0

Lo so, ma non dovrebbe comunque risultare * due * 401 prima del 200. E non è possibile aggiungere credenziali da soli quando si utilizza l'autenticazione di Windows, vero? – Voo

+0

Penso che puoi, vedi in fondo al post. req.Credentials = new NetworkCredential (utente, pwd, dominio); – silver

+0

Sicuro che l'utente possa ottenere, anche il dominio, ma ovviamente non ho modo di ottenere la password (grande difetto di sicurezza che sarebbe) - che funziona solo tramite 'DefaultCredentials'. E in ogni caso tutto mi sembra un'autenticazione di base lì, non NTLM – Voo

1

Di fronte a un problema simile e dopo aver ricevuto molte risposte, nessuna di queste ha funzionato.Di seguito ha lavorato, e non venire con due 401:

var credential = new NetworkCredential("username", "password", "domainname"); 
var myCache = new CredentialCache(); 

// Add the target Uri to the CredentialCache with credential object 
myCache.Add(new Uri("http://targeturi/"), "NTLM", credential); 

// Create an HttpClientHandler to add some settings 
var handler = new HttpClientHandler(); 
handler.AllowAutoRedirect = true; 
handler.Credentials = myCache; 

// Create an HttpClient with the handler object 
httpClient = new HttpClient(handler); 

// Wait to get the reponse, and you can use the reponse in your code 
HttpResponseMessage response = await httpClient.GetAsync(resourceUri); 

Source

+0

Ricevo un'eccezione con la soluzione su "handler.Credentials = myCache;": il valore 'System.Net.CredentialCache' non è supportato per le credenziali di proprietà ' '. Qualche idea? –

+0

@ Gold.strike puoi semplicemente impostare handler.Credentials = credential; La cache delle credenziali non è necessaria. –

Problemi correlati