Аутентификация WCF NT Challenge ответ

Как я могу заставить мое консольное приложение подключаться к службе 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 / Authentication и включите базовую аутентификацию и / или проверку подлинности 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>

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, потому что базовая аутентификация передает пароль в виде простого текста.

Другие вопросы по тегам