Ответ на вызов NT аутентификации WCF

Как я могу заставить свое консольное приложение подключаться к службе WCF, размещенной в IIS, когда включена базовая проверка подлинности и/или проверка подлинности Windows, а анонимная проверка подлинности отключена?

Сайт является внутренним и строгой безопасности не требуется. Нет контроллера домена. Однако мне нужно отключить анонимный доступ.

Я искал несколько дней и перепробовал множество методов, включая использование собственного сертификата и переопределение проверки сертификации, переопределение UserNameValidator и использование client.ClientCredentials.Windows.ClientCredentials.UserName или client.ClientCredentials.UserName.UserName. Ни один из них не сработал.

Я нахожусь в такой ситуации, когда было бы неплохо, если бы кто-нибудь был так любезен, чтобы посмотреть и запустить код и помочь мне запустить образец с аутентификацией.

Я позволил себе загрузить решение для песочницы, содержащее проекты HostWebSite, ClientConsole и API.

Я разместил zip-файл на моем Windows Live SkyDrive: WCF_Authentication.zip

Несколько небольших шагов настройки.

  1. Я добавил в файл hosts 127.0.0.1 hostwebsite.local

  2. Я добавил веб-сайт в IIS
    -- расположение: HostWebSite project root,
    -- привязка: hostwebsite.local
    -- пул приложений: Classic 4.0 app pool.

  3. Прикладная безопасность Everyone доступ для чтения к каталогу проекта HostWebSite.

  4. Убедитесь, что вы видите службу http://hostwebsite.local/services/EchoService.svc

  5. Убедитесь, что консоль возвращает приветствие, мир.

  6. Затем отключите анонимность через IIS/аутентификацию и включите базовую аутентификацию и/или аутентификацию Windows.

спасибо

Для удобства читателей я включил здесь фрагменты кода
Проект: API

namespace API.Contract
{
    [ServiceContract]
    public interface IEcho
    {
        [OperationContract]
        string SendEcho(string message);
    }
}
namespace API.Proxy
{
    public class EchoProxy : IEcho
    {
        public string SendEcho(string message)
        {
            return string.Concat("You said: ", message);
        }
    }
}
namespace API.Service
{
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public class EchoService : System.ServiceModel.ClientBase<IEcho>, IEcho
    {

        public EchoService()
        {
        }

        public EchoService(string endpointConfigurationName) :
            base(endpointConfigurationName)
        {
        }

        public EchoService(string endpointConfigurationName, string remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
        {
        }

        public EchoService(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
        {
        }

        public EchoService(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
        {
        }

        public string SendEcho(string message)
        {
            return base.Channel.SendEcho(message);
        }
    }
}

Проект: ClientConsole

static void Main(string[] args)
{
    EchoService client = new EchoService("WSHttpBinding_IEcho");

    try
    {
        Console.WriteLine(client.SendEcho("Hello World"));
        client.Close(); // i tried putting this in the finally block but the client would close in an errored state it said.
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    finally
    {

    }


    Console.WriteLine("Press any key to exit.");
    Console.ReadKey();
}

Конфигурация клиента

<system.serviceModel>
    <bindings>
        <wsHttpBinding>
            <binding name="WSHttpBinding_IEcho" closeTimeout="00:01:00" openTimeout="00:01:00"
                receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
                transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                allowCookies="false">
                <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                    maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                <reliableSession ordered="true" inactivityTimeout="00:10:00"
                    enabled="false" />
                <security mode="Message">
                    <transport clientCredentialType="Windows" proxyCredentialType="None"
                        realm="" />
                    <message clientCredentialType="Windows" negotiateServiceCredential="true"
                        algorithmSuite="Default" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://hostwebsite.local/Services/EchoService.svc/services/EchoService.svc"
            binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IEcho"
            contract="API.Contract.IEcho" name="WSHttpBinding_IEcho">
            <identity>
                <servicePrincipalName value="host/mikev-ws" />
            </identity>
        </endpoint>
    </client>
</system.serviceModel>

Проект: HostWebSite

<system.serviceModel>
    <!-- SERVER -->
    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServiceTypeBehaviors">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <services>
        <service name="API.Proxy.EchoProxy" behaviorConfiguration="MyServiceTypeBehaviors">
            <endpoint address="/services/EchoService.svc" binding="wsHttpBinding" contract="API.Contract.IEcho" />
            <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
        </service>
    </services>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>

</system.serviceModel>

person Valamas    schedule 29.03.2011    source источник


Ответы (1)


Вы действительно смотрите на безопасность на уровне сообщений? Из вашего описания видно, что вам нужна безопасность на транспортном уровне (от IIS). Для этого вам нужно правильно настроить файл конфигурации клиента. Например,

<binding ...
   ...
   <security mode="TransportCredentialOnly">
       <transport clientCredentialType="windows" proxyCredentialType="None" realm="" />
...

Это обеспечит встроенную аутентификацию Windows — для аутентификации будет использоваться текущий пользователь Windows, запустивший клиент. Для аутентификации NTLM/BASIC вам необходимо указать имя пользователя/пароль из кода — например,

<binding ...
       ...
       <security mode="TransportCredentialOnly">
           <transport clientCredentialType="Ntlm" proxyCredentialType="None" realm="" />

И в коде,

EchoService client = new EchoService("WSHttpBinding_IEcho");
client.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(userName, pwd);

ИЗМЕНИТЬ:

Чтобы базовая аутентификация работала с протоколом http, вы должны выполнить настройку на стороне сервера, а также. Например,

<system.serviceModel>
    <!-- SERVER -->
    <bindings>
        <basicHttpBinding>
            <binding name="NewBinding">
                <security mode="TransportCredentialOnly">
                    <transport clientCredentialType="Basic" />
                </security>
            </binding>
        </basicHttpBinding>
    </bindings>
    ...
    <services>
        <service name="API.Proxy.EchoProxy" ...
           <endpoint binding="basicHttpBinding" bindingConfiguration="NewBinding" contract="API.Contract.IEcho" />
      ...

Дополнительные сведения см. в этой статье. Кстати, вы можете рассмотреть схему HTTPS, потому что базовая аутентификация передает пароль в виде простого текста.

person VinayC    schedule 29.03.2011
comment
@VinayC: Здравствуйте, спасибо за помощь. Я попробовал оба ваших предложения. Мне пришлось изменить привязку на basicHttpBinding; это правильно? Сообщение об ошибке, которое я получаю для 1-го изменения конфигурации, — The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Basic realm="hostwebsite.local"'.. Второе сообщение об ошибке, в котором было изменение конфигурации и кода аутентификации, такое же, как и первое, которое я упомянул, за исключением того, что слово Negotiate заменено на Ntlm. Спасибо - person Valamas; 29.03.2011
comment
@Valamas, чтобы первое изменение конфигурации заработало, вы должны разрешить встроенную / оконную аутентификацию в IIS. Здесь учетные данные пользователя, вошедшего в систему на клиентском компьютере, будут переданы на сервер - это не будет работать, если этот пользователь не распознан на сервере. Для использования базовой схемы аутентификации вам необходимо изменить clientCredentialType на базовый, установить значение области, а в коде вы должны установить ClientCredentials.UserName (задать пользователя и пароль). - person VinayC; 29.03.2011
comment
@VinayC: я следую пути базовой аутентификации. В IIS включена только обычная проверка подлинности. Я следовал вашему последнему заявлению, включая область, которую я установил пустой. В IIS в разделе «Базовая аутентификация» поля «Область» и «Домен» также пусты. При переходе на страницу службы возвращается ошибка (http://hostwebsite.local/Services/EchoService.svc): Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service..... (продолжение) - person Valamas; 29.03.2011
comment
Если вы хотите увидеть текущую конфигурацию и изменения кода. Вот второй почтовый индекс. - person Valamas; 29.03.2011
comment
@Valamas, извиняюсь - обычно базовая аутентификация должна использоваться с https. Поэтому, чтобы использовать с http, я считаю, что вам нужно настроить привязку на стороне сервера, а также я отредактировал ответ, чтобы показать эту часть. - person VinayC; 30.03.2011
comment
спасибо, похоже, я почти там. Теперь я могу использовать браузер для прохождения аутентификации для просмотра файла wsdl. Когда я запускаю клиентскую консоль, я получаю сообщение об ошибке There was no endpoint listening at http://hostwebsite.local/Services/EchoService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. Внутреннее исключение говорит об ошибке 404. Странный! Эхо-код работает до всех настроек безопасности. Просматривая журналы трассировки, я вижу Description Failed to lookup a channel to receive an incoming message. Either the endpoint or the SOAP action was not found. - person Valamas; 30.03.2011
comment
Я загрузил текущее состояние моего проекта WCF_Authentication3.zip, а также сгенерированный Traces.svclog. Спасибо - person Valamas; 30.03.2011
comment
@VinayC: я разместил вопрос об этой проблеме на stackoverflow.com/ вопросы/5507447/ - person Valamas; 01.04.2011
comment
@VinayC: теперь я решил все свои проблемы. большое спасибо за помощь мне. - person Valamas; 01.04.2011