WCF 身份验证 NT 质询响应

发布于 2024-10-28 05:48:07 字数 6118 浏览 2 评论 0原文

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

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

我已经搜索了几天并尝试了许多方法,包括使用自托管证书并覆盖认证验证、覆盖 UserNameValidator 和使用 client.ClientCredentials.Windows.ClientCredentials.UserName或client.ClientCredentials.UserName.UserName。这些都不起作用。

我现在的处境是,如果有人愿意查看并运行代码并帮助我通过身份验证运行示例,那就太好了。

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

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

一些小的设置步骤。

  1. 我添加到主机文件 127.0.0.1 hostwebsite.local

  2. 我添加IIS 网站
    -- 位置:HostWebSite 项目根目录,
    -- 绑定:hostwebsite.local
    -- 应用程序池:经典 4.0 应用程序池

  3. 应用安全性Everyone对 HostWebSite 项目目录的读取权限。

  4. 验证可以看到服务http://hostwebsite.local/services/EchoService.svc

  5. 验证控制台回显 hello world。

  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>

How can I get my console app to connect with an IIS hosted WCF service when basic and/or windows authentication is switched on and anonymous authentication turned off?

The site is internal and stringent security is not required. There is no domain controller. However, I need to turn off anonymous access.

I have searched for days and have tried many methods including using a self hosted certificate and overriding the certification validation, overriding the UserNameValidator and using client.ClientCredentials.Windows.ClientCredentials.UserName or client.ClientCredentials.UserName.UserName. None of these have worked.

I am at a point where it would be nice if someone would be so kind as to look and run the code and help me get the sample running with authentication.

I have taken the liberty of uploading a sandbox solution containing, HostWebSite, ClientConsole and API projects.

I have hosted the zip file on my Windows Live SkyDrive: WCF_Authentication.zip

Some small setup steps.

  1. I added to the hosts file 127.0.0.1 hostwebsite.local

  2. I added a website to IIS
    -- location: HostWebSite project root,
    -- binding: hostwebsite.local
    -- app pool: Classic 4.0 app pool.

  3. Applied security Everyone read access to the HostWebSite project directory.

  4. Verify can see service http://hostwebsite.local/services/EchoService.svc

  5. Verify the console echoes back hello world.

  6. Then turn off anonymous via IIS / Authentication and turn on either basic and/or windows authentication.

thank you

For the benefit of readers, I have included code snippets here
Project: 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);
        }
    }
}

Project: 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();
}

Client Config

<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>

Project: 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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不疑不惑不回忆 2024-11-04 05:48:07

您真的在关注消息级安全性吗?从您的描述来看,您似乎需要传输级安全性(来自 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 方案,因为基本身份验证以纯文本形式传输密码。

Are you really looking at message level security? From your description, it appears that you want a transport level security (from IIS). For that you have to get your client configuration file correct. For example,

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

This will ensure integrated windows authentication - will use current windows user running the client for authentication. For NTLM/BASIC authentication, you need to provide user name/password from code - for example,

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

And in code,

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

EDIT:

For basic authentication to work with http protocol, you have to do configuration on server side as well as. For example,

<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" />
      ...

See this article for more info. BTW, you may want to consider HTTPS scheme because basic auth transmits password in plain text.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文