WCF身份验证NT Challenge响应

时间:2011-03-29 05:36:47

标签: c# wcf wcf-binding wcf-security wcf-client

如果打开基本和/或Windows身份验证并关闭匿名身份验证,如何让我的控制台应用程序连接到IIS托管的WCF服务?

该网站是内部的,不需要严格的安全性。没有域控制器。但是,我需要关闭匿名访问。

我已经搜索了几天,并尝试了很多方法,包括使用自托管证书和覆盖认证验证,覆盖UserNameValidator并使用client.ClientCredentials.Windows.ClientCredentials.UserNameclient.ClientCredentials.UserName.UserName。这些都没有奏效。

如果有人能够查看并运行代码并帮助我通过身份验证运行示例,那么我将会很高兴。

我冒昧地上传了包含HostWebSite,ClientConsole和API项目的沙箱解决方案。

我在我的Windows Live SkyDrive上托管了zip文件:WCF_Authentication.zip

一些小的设置步骤。

  1. 我已添加到主机文件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身份验证。

  7. 谢谢

    为了读者的利益,我在此处添加了代码段
    项目: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 个答案:

答案 0 :(得分: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" />
      ...

有关详细信息,请参阅this article。顺便说一句,您可能需要考虑HTTPS方案,因为基本身份验证以纯文本形式传输密码。