Этот вопрос, который уже обсуждался несколько раз на SO, но я не мог найти подходящего решения моей проблемы. У меня есть служба WCF, размещенная на внешнем сервере (другой домен), и я пытаюсь ее использовать из приложения командной строки. Я получаю следующую ошибку:
The request for security token could not be satisfied because authentication failed.
Служба настроена внутри файла web.config:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBinding_IRun">
<security mode="None">
<message clientCredentialType="None" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix="http://www.domain.net"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior name="calculadora.SOA.RunBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="calculadora.SOA.RunBehavior" name="calculadora.SOA.Run">
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc" binding="wsHttpBinding" contract="calculadora.SOA.IRun">
<identity>
<dns value="domain.net"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
На стороне клиента я создаю пользовательскую привязку для подключения к службе. Вот конфигурация безопасности:
standardBinding.Security.Mode = SecurityMode.None;
standardBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
standardBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
standardBinding.Security.Transport.Realm = "";
standardBinding.Security.Message.ClientCredentialType = MessageCredentialType.None;
standardBinding.Security.Message.NegotiateServiceCredential = false;
standardBinding.Security.Message.EstablishSecurityContext = false;
standardBinding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;
Я не использую какой-либо механизм безопасности для аутентификации, но, тем не менее, служба, похоже, ожидает его. При работе в разных доменах необходимо ли использовать базовую аутентификацию?
EDIT: Я не ссылался на какую-либо привязку к моей конечной точке. После того, как ссылка была установлена, я получил еще одну ошибку сообщения:
{"The message with Action 'http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue' cannot be processed at the
receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract
mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the
receiver. Check that sender and receiver have the same contract and the same binding (including security
requirements, e.g. Message, Transport, None)."}
Проблема была вызвана привязкой моего клиента. Пока я создавал свое обязательное связывание с использованием стандартного WSHttpBinding, для свойства "SecurityMode" вместо "Нет" было установлено "Сообщение". Теперь код выглядит следующим образом, и сервис наконец работает:
WSHttpBinding standardBinding = new WSHttpBinding(SecurityMode.None, false);
CustomBinding myCustomBinding = new CustomBinding(standardBinding);
Большое спасибо marc_s!
Я думаю, что проблема заключается в определении конечной точки вашего сервиса:
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc"
binding="wsHttpBinding" contract="calculadora.SOA.IRun">
Вы используете стандартную wsHttpBinding, которая по умолчанию использует встроенную защиту Windows как безопасность сообщений.
Пока вы определяете конфигурацию привязки (называемую wsHttpBinding_IRun
), вы не ссылаетесь на определение своей конечной точки - таким образом, она не вступает в игру. Вам необходимо расширить определение конечной точки службы с помощью атрибута bindingConfiguration
, например:
<endpoint address="http://www.domain.net/calculadora/SOA/run.svc"
binding="wsHttpBinding"
bindingConfiguration="wsHttpBinding_IRun"
contract="calculadora.SOA.IRun">
чтобы фактически использовать определенную конфигурацию привязки (включая настройки безопасности).
Я столкнулся с одной и той же проблемой, и после целого дня инвестировал, наконец, выяснил, как исправить. Ключ помещается в тег сообщения installedSecurityContext = "false".
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" establishSecurityContext="false" />
</security>
establishSecurityContext
переменную false
.