2010-09-09 15 views
8

Necesito llamar a un servicio de WCF programmatically. El servicio puede hospedarse con ya sea autenticación NTLM o Kerberos y debe funcionar bajo cualquiera de ellos. Es decir, si falla la conexión al servicio a través de Kerberos, debe recurrir a NTLM.¿Cómo escribir código que llame a un servicio WCF y que retroceda desde Kerberos a NTLM si es necesario?

Aquí está el código que estoy usando para Kerberos de autenticación (si es relevante, el servicio está alojado en SharePoint 2010 y se está llamando desde una pieza de la tela):

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; 
} 

llamar a un método en el proxy cuando es ejecutado en un entorno NTLM da el error:

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

Nota: la dirección URL puede estar en otra aplicación web en otro servidor. No puedo verificar en qué autenticación se ejecuta la aplicación web de la parte web y asumir que es igual a donde se aloja el servicio WCF.

¿Cómo puedo (automática o manualmente) garantizar que la autenticación vuelva desde Kerberos a NTLM cuando falla?

Actualización:

Como se mencionó, el error de autenticación se produce cuando se llama a un método web. Sin embargo, no quiero esperar tanto, ya que hay varios métodos web en el servicio llamados desde varios lugares. Me gustaría probar la autenticación en el punto donde está configurado el proxy (en el fragmento de código anterior).

He intentado usar proxy.Open() pero eso no parece causar la falla.

Respuesta

0

no he sido capaz de encontrar una manera de hacer esto de forma automática. En su lugar, agregué UI a la aplicación donde se debe elegir el tipo de autenticación.

1

Esto es un poco fuera de balance, pero ¿por qué está retrocediendo a NTLM. He tenido dificultades significativas con la seguridad en Active Directory y WCF, todos relacionados con los nombres principales del servicio (SPN).

Kerberos fallará si está ejecutando el servicio como algo más que el Servicio de red a menos que tenga un SPN declarado en el dominio para su servicio. Para configurar el SPN necesita el kit administrativo del servidor de Windows, que tiene el comando setspn.

setspn -A HTTP\machinename domain\service_account 

Esto permitirá que Kerberos comparta las credenciales del cliente a su servicio dentro del dominio.

Lea atentamente, ya que podría romper kerberos para cualquier otro servicio que se ejecute en la misma caja, dependiendo de su configuración.

+0

Bueno, es más que quiero que pruebe Kerberos primero y si eso falla, entonces use NTLM. Esperaba usar Kerberos auth automáticamente haría esto pero parece que no. –

+0

Mi primera suposición también. La forma de pensarlo es si se confió en algún servicio de la empresa, entonces podrías tener un rogue de servicio robando credenciales, suplantando y haciendo cosas malas. El SPN obliga al administrador de la empresa a decir que se confía en que este servicio tenga su credencial de kerberos; de lo contrario, no lo solicite. – Spence

+0

Eso es bueno saber. He reformulado la pregunta un poco, ya que no creo que haya sido clara. Necesito el elemento web para 'seleccionar automáticamente' la autenticación correcta dependiendo de si el servicio está alojado en Kerberos o autenticación de Windows. –

0

que tenían el mismo error msg, que he publicado sobre here y lo resolvió mediante la creación de un extremo dinámico de este 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; 
} 

estaba corriendo el servicio WCF como un usuario de Active Directory específico en lugar del NETWORK_SERVICE por defecto .

+0

Eso es genial, pero necesito pasar las credenciales del usuario actual al servicio web. –

0

entorno Probar:

proxy.ClientCredentials.Windows.AllowNTLM = true;

Según this, AllowNTLM está obsoleta - no estoy seguro de cuál es la alternativa correcta es.

+0

Afortunadamente estoy usando .NET 3.5 donde no está marcado como obsoleto. Lo intentaré, ¡gracias! –

+0

Comprobé esto y descubrí que AllowNTLM está configurado como verdadero, por lo que lamentablemente esto no funcionó. He actualizado la pregunta. –

0

Supongo que está utilizando el nombre completo dns del servidor como la dirección del servicio. Intente usar el nombre NETBIOS o la dirección IP. Eso debería obligarlo a usar NTLM.

Si sabe qué protocolo está usando el servidor, puede configurar su aplicación para usar el nombre completo o la ip.

la esperanza de que funcione para usted.

+0

Tienes razón, estoy usando el nombre DNS. Esa es mi única opción porque el sistema está equilibrado de carga y olvidé mencionar que el servicio WCF está alojado en SharePoint; solo responderá a las solicitudes de ese nombre DNS. –

0
+0

Este no es el caso. Si especifico 'HttpClientCredentialType.Windows' obtengo el error escrito en la pregunta. –

1

(I reconocen el post original es muy antigua.)

¿Se puede usar algo distinto BasicHttpBinding (como wsHttpBinding)? De acuerdo con el artículo this, BasicHttpBinding es la única excepción a los objetos vinculantes, ya que no negocia automáticamente. Esta es la razón por la cual allowNTLM no tiene ningún efecto.

+0

No sabía eso y parece que WsHttpBinding hubiera estado bien para usar en SharePoint. ¡Gracias por el consejo! –

Cuestiones relacionadas