2009-08-05 38 views
3

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

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

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

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

这里是我的客户端的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> 

回答

6

手动创建代理并不妨碍您将配置放置在配置文件中;你只需要在你的ClientBase派生的代理类中公开正确的构造函数重载,该代理类委托给ClientBase中的right constructor,它使用在配置中查找的端点名称。这就是说,你当然可以通过代码填充端点标识,只需要创建一个正确的EndpointIdentity派生类并将其附加到实例化代理类时使用的EndpointAddress对象上。类似这样的:

EndpointIdentity epid = EndpointIdentity.CreateUpnIdentity("[email protected]"); 
EndpointAddress epaddr = new EndpointAddress(uri, epid); 

MyClient client = new MyClient(epaddr); 
+0

Ash的第一条评论让我开始了一条在托马斯的帮助下完成的路径,现在一切正常。 作为一个方面说明,要创建一个新的EndpointAddress,您必须指定一个Uri,EndpointIdentity和一个AddressHeader对象以使其正常工作。他们的API设置有点混乱(尤其是如果你没有正确使用base.New,会出现一些模糊的错误),但是都告诉它它的功能。 感谢您的帮助! – RubyHaus 2009-08-06 18:14:00

+2

对于其他人在看这个答案,仍然有问题,我需要使用“DOMAIN \用户”,仍然没有工作。我发现我必须使用“[email protected]”(或您的完全合格的Active Directory域名。 – Jim 2012-10-02 16:39:02

1

虽然我可能不会直接回答你的问题,使用相同的数据成员的围栏上的两侧,你不”您需要手动创建代理。你要做的就是您在使用SvcUtil工具生成你的代理,你在

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

这样,数据成员类型不是在你的ServiceProxy.cs反复有你的数据成员作为该dll/R通过文件。您可以通过传递wsdl/xsd(真正的合同第一种方法),使用/ ct等自定义收集类型等来广泛定制此功能。

这将为您节省许多手工制作代理的时间,同时避免类似问题以上你可能会遇到,因为一切都成为股票标准。