2010-09-09 6 views
8

Devo chiamare un servizio WCF a livello di programmazione. Il servizio può essere ospitato con l'autenticazione o NTLM o Kerberos e deve funzionare in entrambi. Cioè, se la connessione al servizio via Kerberos fallisce, allora dovrebbe tornare a NTLM.Come scrivere codice che chiama un servizio WCF e se necessario torna da Kerberos a NTLM?

Ecco il codice che sto utilizzando per Kerberos autenticazione (se del caso, il servizio è ospitato in SharePoint 2010 e viene chiamato da una parte web):

public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url) 
{ 
    var binding = new BasicHttpBinding(); 
    binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly; 
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows; 
    url = url.EndsWith("/") ? url + SiteMembershipAddress : url + "/" + SiteMembershipAddress; 
    var endpoint = new EndpointAddress(url); 
    var proxy = new SiteMembershipSvc.SiteMembershipServiceClient(binding, endpoint); 
    proxy.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation; 
    return proxy; 
} 

Chiamare un metodo sul proxy quando corsa in un ambiente NTLM dà l'errore:

The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'NTLM'.

Nota: l'URL può essere in un'altra applicazione web su un altro server. Non riesco a verificare quale autenticazione esegue l'app web della web part e ritengo che sia la stessa di dove è ospitato il servizio WCF.

Come è possibile (automaticamente o manualmente) garantire che l'autenticazione ricada indietro da Kerberos a NTLM in caso di errore?

Aggiornamento:

Come detto, l'errore di autenticazione si verifica quando un metodo Web viene chiamato. Tuttavia, non voglio aspettare così a lungo che ci sono diversi metodi web nel servizio chiamato da più posti. Mi piacerebbe testare l'autenticazione nel punto in cui è configurato il proxy (nello snippet di codice sopra).

Ho provato a utilizzare proxy.Open() ma ciò non sembra causare l'errore.

risposta

0

non sono stato in grado di trovare un modo per farlo automaticamente. Invece ho aggiunto l'interfaccia utente all'applicazione in cui deve essere scelto il tipo di autenticazione.

1

Questo è un po 'fuori curva, ma perché ricade su NTLM. Ho avuto grosse difficoltà con la sicurezza nella directory attiva e WCF tutte correlate ai nomi principali dei servizi (SPN).

Kerberos avrà esito negativo se si sta eseguendo il servizio come servizio diverso da Servizio di rete a meno che non sia stato dichiarato un SPN nel dominio per il servizio. Per impostare l'SPN è necessario il kit di amministrazione del server Windows, che ha il comando setspn.

setspn -A HTTP\machinename domain\service_account 

Ciò consentirà quindi a Kerberos di condividere le credenziali del client per il servizio all'interno del dominio.

Si prega di fare qualche lettura, in quanto si potrebbe rompere kerberos per tutti gli altri servizi in esecuzione sulla stessa scatola a seconda della configurazione.

+0

Beh, è ​​più che voglio provare prima Kerberos e se fallisce, usa NTLM. Speravo che l'utilizzo dell'autent Kerberos lo avrebbe fatto automaticamente ma non sembra. –

+0

Anche la mia prima ipotesi. Il modo di pensarci è se ogni servizio in azienda fosse affidabile, quindi si potrebbe avere un servizio non autorizzato per rubare credenziali, impersonare e fare cose cattive. L'SPN obbliga l'amministratore aziendale a dire che questo servizio è affidabile per avere le credenziali Kerberos, altrimenti non chiederglielo. – Spence

+0

Buono a sapersi. Ho riformulato la domanda un po 'perché non penso fosse abbastanza chiaro. Ho bisogno che la web part "selezioni automaticamente" l'autenticazione corretta a seconda che il servizio sia ospitato in Kerberos o Windows auth. –

0

Ho avuto lo stesso msg di errore che ho postato su here e risolto con la creazione di un endpoint dinamico in questo modo:

public static SiteMembershipSvc.SiteMembershipServiceClient InitialiseSiteMembershipService(string url) 
{ 
    //create endpoint 
    EndpointAddress ep = new EndpointAddress(new Uri(string), EndpointIdentity.CreateUpnIdentity("MyDomain\WCFRunAsUser")); 
    //create proxy with new endpoint 
    SiteMembershipSvc.SiteMembershipServiceClient service = new SiteMembershipSvc.SiteMembershipServiceClient("wsHttp", ep); 
    //allow client to impersonate user 
    service.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation; 
    //return our shiny new service 
    return service; 
} 

stavo correndo il servizio WCF come un utente di Active Directory specifico piuttosto che il NETWORK_SERVICE predefinita .

+0

È bello, ma ho bisogno di passare le credenziali dell'utente corrente al servizio web. –

0

impostazione Prova:

proxy.ClientCredentials.Windows.AllowNTLM = true;

Secondo this, AllowNTLM è ormai obsoleto - io non sono sicuro di quello che l'alternativa corretta è.

+0

Fortunatamente sto usando .NET 3.5 dove non è contrassegnato come obsoleto. Ci proverò - grazie! –

+0

Ho verificato che AllowNTLM è impostato su true, quindi sfortunatamente non ha funzionato. Ho aggiornato la domanda. –

0

Suppongo che si stia utilizzando il nome DNS completo del server come indirizzo del servizio. Prova a utilizzare il nome NETBIOS o l'indirizzo IP. Questo dovrebbe costringerlo a usare NTLM.

Se si conosce il protocollo utilizzato dal server, è possibile configurare l'app in modo che utilizzi il nome completo o l'ip.

Spero che funzioni per voi.

+0

Hai ragione, sto usando il nome DNS. Questa è la mia unica opzione perché il sistema è bilanciato dal carico e ho dimenticato di menzionare che il servizio WCF è ospitato in SharePoint, risponderà solo alle richieste su quel nome DNS. –

0
+0

Questo non è il caso. Se specifico 'HttpClientCredentialType.Windows' ottengo l'errore scritto nella domanda. –

1

(riconosco il post originale è molto vecchio.)

è possibile utilizzare qualcosa di diverso BasicHttpBinding (come WsHttpBinding)? Secondo l'articolo this, BasicHttpBinding è l'unica eccezione agli oggetti vincolanti, in quanto non negozia automaticamente. Questo è il motivo per cui allowNTLM non ha alcun effetto.

+0

Non lo sapeva e sembra che WsHttpBinding sarebbe stato OK da usare in SharePoint. Grazie per il consiglio! –