c# - faultcontract - wcf fault exception sample
NetTCP vinculante Soap Security Negotiation falló (2)
Los servicios de Windows se registran con un Nombre principal de usuario o un Nombre principal de servicio ( documentation ). Para citar desde ese enlace: " Si el servicio se ejecuta con las cuentas LocalSystem, LocalService o NetworkService, se genera un nombre principal del servicio (SPN) de forma predeterminada en forma de host / host porque esas cuentas tienen acceso a los datos SPN de la computadora. Si el servicio se ejecuta bajo una cuenta diferente, Windows Communication Foundation (WCF) genera un UPN en forma de @. "De hecho, esta cita es bastante similar a lo que indica su mensaje de error. Entonces parece que ...
a) si el servicio se está ejecutando bajo la cuenta del Servicio Local o una cuenta estándar similar, entonces necesita ajustar su archivo de configuración del cliente para tener esto, donde el nombre real del servidor es "dirección" y el punto final se está ejecutando en el puerto 4503:
<identity>
<servicePrincipalName value="host/address:4503" />
</identity>
b) alternativamente, si está ejecutando una cuenta de servicio dedicada (llamémosla "Cuenta de servicio" en el dominio "MiDominio"), entonces desea
<identity>
<userPrincipalName value="ServiceAccount@MyDomain" />
</identity>
Tenga en cuenta que es posible que deba usar el nombre de dominio completo en ambos casos, incluidos los niveles de Bosque y Árbol. Para un dominio simple dentro de su LAN / WAN privada, eso significará address.MyDomain.local y [email protected]. Si su dominio está en un árbol llamado MyTree, entonces será [email protected]; si eso está en un bosque llamado MyForest, entonces será [email protected] (y similar para ServicePrincipalName). El nombre completo es necesario cuando está utilizando Kerberos para la autenticación.
Estoy escribiendo que un servicio WCF requiere personificación y sesión.
Está bien cuando intenté llamarlo a mi máquina local, pero en la máquina remota siempre falló con tal error:
La autenticación de la Interfaz del proveedor de soporte de seguridad (SSPI) falló. Es posible que el servidor no se esté ejecutando en una cuenta con la identidad ''host / hostname''. Si el servidor se está ejecutando en una cuenta de servicio (Servicio de red, por ejemplo), especifique ServicePrincipalName de la cuenta como la identidad en la EndpointAddress para el servidor. Si el servidor se está ejecutando en una cuenta de usuario, especifique UserPrincipalName de la cuenta como la identidad en la EndpointAddress para el servidor.
Si proporcioné una actualización, se produce una excepción de identidad fallida.
Aquí está mi configuración:
Configuración del servidor (APP):
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="default">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization impersonateCallerForAllOperations="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="DataService.netTcpBinding">
<readerQuotas maxArrayLength="65535" maxBytesPerRead="2147483647" maxStringContentLength="2147483647"/>
<reliableSession enabled="true" inactivityTimeout="24:00:00" ordered="true"/>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Windows" />
<transport clientCredentialType="Windows"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<services>
<service behaviorConfiguration="default" name="DataService.DataService">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="DataService.netTcpBinding"
name="DataService.DataService" contract="DataService.IDataService"/>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://address:4504/"/>
<add baseAddress="net.tcp://address:4503/"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
Configuración del cliente:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="DataService.DataService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="24.00:00:00"
enabled="true" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" algorithmSuite="Default" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://address:4503/" binding="netTcpBinding"
bindingConfiguration="DataService.DataService"
contract="ataService.IDataService" name="DataService.DataService">
<identity>
<dns value="DOMAIN"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Cualquier ayuda sería muy apreciada.
También hay un truco sucio, publicado here , here y here , y analizado here .
Puede proporcionar un Nombre principal de servicio (SPN) ficticio. En ese caso, WCF no fallará, pero recurrirá a NTLM para la autenticación que no verifica el principal.
Entonces, la configuración:
<identity>
<servicePrincipalName value="dummy" >
</identity>
y programáticamente
EndpointIdentity identity = EndpointIdentity.CreateSpnIdentity("dummy");
utilizando ChannelFactory:
Uri uri = new Uri("net.tcp://<myServer>:<myPort>/myServiceAddress");
ChannelFactory channelFactory = new ChannelFactory<IMyContract>(new NetTcpBinding());
channelFactory.CreateChannel(new EndpointAddress(uri, identity)
También funcionará.