2010-05-06 1 views
16

У меня здесь странная ситуация. У меня это работает, но я не понимаю, почему. Ситуация такова:Конечная точка клиента WCF: SecurityNegotiationException без <dns>

Служба WCF, на которую мне нужно позвонить (веб-сайт). Служба WCF предоставляет netTcpBinding и требует безопасности транспорта (Windows). Клиент и сервер находятся в одном домене, но на разных серверах.
Таким образом генерируя клиента результаты в следующей конфигурации (в основном по умолчанию)

<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
     <binding name="MyTcpEndpoint" ...>   
       <reliableSession ordered="true" inactivityTimeout="00:10:00" 
           enabled="false" /> 
      <security mode="Transport"> 
       <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/> 
       <message clientCredentialType="Windows" /> 
      </security> 
     </binding> 
     </netTcpBinding> 
    </bindings> 
    <client> 
     <endpoint address="net.tcp://localhost:xxxxx/xxxx/xxx/1.0" 
        binding="netTcpBinding" bindingConfiguration="MyTcpEndpoint" 
        contract="Service.IMyService" name="TcpEndpoint"/> 
    </client> 
</system.serviceModel> 

Когда я запускаю веб-сайт и сделать звонок на службу, я получаю следующее сообщение об ошибке:

System.ServiceModel.Security.SecurityNegotiationException: Either the target name is incorrect or the server has rejected the client credentials. ---> System.Security.Authentication.InvalidCredentialException: Either the target name is incorrect or the server has rejected the client credentials. ---> System.ComponentModel.Win32Exception: The logon attempt failed 
    --- End of inner exception stack trace --- 
    at System.Net.Security.NegoState.EndProcessAuthentication(IAsyncResult result) 
    at System.Net.Security.NegotiateStream.EndAuthenticateAsClient(IAsyncResult asyncResult) 
    at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.InitiateUpgradeAsyncResult.OnCompleteAuthenticateAsClient(IAsyncResult result) 
    at System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorAsyncResult.CompleteAuthenticateAsClient(IAsyncResult result) 
    --- End of inner exception stack trace --- 

Server stack trace: 
    at System.ServiceModel.AsyncResult.End[TAsyncResult](IAsyncResult result) 
    at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result) 
    at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result) 
.... 

Теперь, если я просто изменить конфигурацию клиента следующим образом:

<endpoint address="net.tcp://localhost:xxxxx/xxxx/xxx/1.0" 
       binding="netTcpBinding" bindingConfiguration="MyTcpEndpoint" 
       contract="Service.IMyService" name="TcpEndpoint"> 
     <identity> 
      <dns /> 
     </identity> 
    </endpoint> 

все работает и мой сервер с радостью сообщает, что он получил колл от го e, который содержит AppPool для моего веб-сайта. Все хорошо.

Мой вопрос сейчас: почему это работает? Что это делает? Я добрался до этого решения простой пробной ошибкой. Мне кажется, что все теги <dns /> говорят клиенту использовать DNS по умолчанию для аутентификации, но разве это не так?

UPDATE
Таким образом, после некоторых больше исследований и проб и ошибок, я до сих пор не нашел ответ на эту проблему. В некоторых случаях, если я не предоставляю <dns />, я получаю ошибку Credentials rejected, но если я предоставляю конфигурацию <dns value="whatever"/>, она работает. Зачем?

+0

Имея проблемы с SSPI с нашим клиентом/службой WCF в течение некоторого времени, но никогда не смог правильно его решить, и это произошло только с некоторыми пользователями на некоторых машинах. Идентификатор «DNS» - даже пустой - кажется, делает тик ... просто вау. –

ответ

12

<dns/> тег позволяет клиенту проверять идентификатор сервера. Например, если вы сказали <dns value="google.com"/>, он будет проверять, что сервер WCF предоставляет идентификатор google.com. Поскольку вы говорите <dns/>, это, вероятно, просто позволяет всем служить вам.

Более подробная информация на Service Identity and Authentication

+0

Ну, после прочтения этой страницы и повторения некоторых разных конфигураций она по-прежнему не решена. Даже если я поставлю 'my-crappy-unexisting-dummy-domain.com', он все равно работает.Я решил, что он должен попытаться сделать запрос, а затем вернуться к умолчанию, но я не могу найти что-либо в протоколе, который предполагает, что DNS-сервер или сервер приложений даже попытались пройти проверку подлинности в отношении этого домена ... Поэтому мой вопрос: еще не решен. Спасибо, что помогли мне! – RoelF

+0

Я думаю, вам нужно будет иметь сертификат с доменным именем, чтобы клиент мог аутентифицироваться. – Vitalik

+0

+1 Привет, не могли бы вы объяснить это мне, Итак, что это значит, если у dns есть значение = "localhost"? – Lamps

5

MSDN-х "Service Identity and Authentication" объясняет, что раздел идентичности конечных точек позволяет предосторожность безопасности на стороне клиента от фишинга.

Из MSDN:

After the client initiates a communication to an endpoint and the service authenticates itself to the client, the client compares the endpoint identity value with the actual value the endpoint authentication process returned. If they match, the client is assured it has contacted the expected service endpoint. This functions as a protection against phishing by preventing a client from being redirected to an endpoint hosted by a malicious service.

Также см MSDN-х "Service Identity Sample".

0

Не ответ, но тот же «трюк» работает, если вы создаете EndpointAddress с помощью кода:

// does fail on some machines for some users 
// (I have no explanation here - just crazy) 
var address = new EndpointAddress(new Uri(url)); 

// will work and the dns entry doesn't matter 
address = new EndpointAddress(new Uri(url), UpnEndpointIdentity.CreateDnsIdentity("")); 

Это странно, и я не знаю, почему это работает, но это, кажется, помогает.