【问题标题】:WCF Proxy and userPrincipalNameWCF 代理和 userPrincipalName
【发布时间】:2009-08-05 22:55:47
【问题描述】:

我和我的团队正在开发一个相当大的应用程序,其中包含许多基于 WCF NetTCP 的服务。此系统将在其下运行的 Windows 服务不是本地帐户,而是标准域用户(在托管服务的服务器上具有管理员权限)。在测试连接性的过程中,我遇到了 SSPI 调用失败的问题。根据几个小时的研究,这导致我在客户端配置中丢失了以下行:

<identity>
     <userPrincipalName value="MACHINE\user" />
</identity>

使用它的问题是我不使用 VS 或 svcutil 为该服务生成客户端/代理 - 正在使用的代理完全用代码编写,它们继承 System.ServiceModel.ClientBase。我相信选择此选项的最初原因是我们可以使用完全相同的 DataMember 对象,这些对象通过围栏两侧的服务 - 第三方组不需要连接到我们的服务,所以这不是问题.

当我没有在标准 system.serviceModel 配置部分中指定端点时,是否有人知道我在客户端(代码或通过配置)中设置 userPrincipalName 的方法?

这是我的客户端 web.config 的外观供参考:

    <system.serviceModel>
    <diagnostics>
        <messageLogging logEntireMessage="true" logMalformedMessages="true"
         logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
    </diagnostics>
    <behaviors>
        <serviceBehaviors>
            <behavior name="includeExceptions">
                <serviceDebug includeExceptionDetailInFaults="true"/>
                <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <bindings>
        <netTcpBinding>
            <binding name="NetTcpBinding_Default" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="Infinite" sendTimeout="01:00:00" portSharingEnabled="true" transferMode="Buffered" maxReceivedMessageSize="2147483647">
                <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
                <security mode="Transport">
                    <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
                </security>
            </binding>
        </netTcpBinding>
    </bindings>

</system.serviceModel>

【问题讨论】:

    标签: wcf identity wcf-security


    【解决方案1】:

    手动创建代理不会妨碍您将配置放入配置文件;您只需要在 ClientBase 派生的代理类中公开正确的构造函数重载,该代理类委托给 ClientBase 中的 right constructor,它采用端点名称以在配置中查找。

    也就是说,您当然可以通过代码填写端点身份,您只需创建正确类型的 EndpointIdentity 派生类并将其附加到您在实例化代理类时使用的 EndpointAddress 对象。像这样的:

    EndpointIdentity epid = EndpointIdentity.CreateUpnIdentity("user@domain.fqdn");
    EndpointAddress epaddr = new EndpointAddress(uri, epid);
    
    MyClient client = new MyClient(epaddr);
    

    【讨论】:

    • Ash 的第一条评论让我开始了一条在 tomasr 的帮助下完成的道路,现在一切正常。附带说明一下,要创建新的 EndpointAddress,您必须指定 Uri、EndpointIdentity 和 AddressHeader 对象才能使其正常工作。他们的 API 设置有点混乱(特别是如果你没有正确使用 base.New 会出现一些模糊的错误),但都告诉它可以正常工作。感谢您的帮助!
    • 对于其他查看此答案但仍有问题的人,我需要使用“DOMAIN\user”,但仍然无法正常工作。我发现我必须使用“user@DOMAIN.local”(或者您的完全限定 Active Directory 域名。
    【解决方案2】:

    虽然我可能不会直接回答您的问题,但要在栅栏的两侧使用相同的数据成员,您无需手动创建代理。您所做的是使用 svcutil 生成代理,然后传入将数据成员作为 /r 的 dll

    例如

    svcutil http://localhost/service/service.svc /r:AssemblyThatHasDataMembers.dll /out:ServiceProxy.cs
    

    这样,数据成员类型不会在您的 ServiceProxy.cs 文件中重复。您可以通过传递 wsdl/xsd(真正的合约优先方法)来广泛地自定义它,使用 /ct 等自定义集合类型。

    这将为您节省大量手动制作代理的时间,同时避免您可能遇到的上述问题,因为一切都将成为库存标准。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-15
      • 1970-01-01
      • 2018-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多