WCF Authentication NT Challenge отговор

Как мога да накарам моето конзолно приложение да се свърже с IIS хоствана WCF услуга, когато основното и/или 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; вярно ли е? Съобщението за грешка, което получавам за първата промяна на конфигурацията, е 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, за да работи първата промяна на конфигурацията, трябва да разрешите интегрирано/windows удостоверяване в IIS. Тук идентификационните данни на потребител, влязъл в клиентската машина, ще бъдат предоставени на сървъра - това няма да работи, ако този потребител не е разпознат на сървъра. За да използвате основна схема за удостоверяване, трябва да промените clientCredentialType на основен, да зададете стойност на областта и в кода трябва да зададете ClientCredentials.UserName (задайте потребител и парола). - person VinayC; 29.03.2011
comment
@VinayC: Следвам пътя за основно удостоверяване. В IIS е активирано само основното удостоверяване. Проследих последното ви изявление, включително царство, което зададох да е празно. В IIS под Basic Authentication полетата Realm и Domain също са празни. Преглеждането на страницата на услугата връща грешка (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