WCF 代理和 userPrincipalName
我和我的团队正在开发一个相当大的应用程序,其中包含许多基于 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>
We have a rather large application my team and I are developing that contains a number of WCF NetTCP-based services. The Windows service this system will be running under won't be a local account, but instead a standard domain user (with admin privileges on the servers hosting the service). In the middle of testing connectivity I ran into an issue where SSPI calls fail. Based on a few hours of research this has led me down the path of me missing the following line from my client config:
<identity>
<userPrincipalName value="MACHINE\user" />
</identity>
The problem with using this is I don't use VS or svcutil to generate a client/proxy for this service - the proxies being used are completely written in code and they inherit System.ServiceModel.ClientBase. I believe the original reason this option was chosen was so we could use the exact same DataMember objects that pass through the services on either side of the fence - third party groups won't need to connect to our services so this wasn't a problem.
Does anyone know a way for me to set userPrincipalName in the client (code or through a config) when I don't have endpoints specified in the standard system.serviceModel configuration section?
Here's what my client-side web.config looks like for reference:
<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>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
手动创建代理并不妨碍您将配置放入配置文件中; 您只需要在 ClientBase 派生的代理类中公开正确的构造函数重载,该类委托给
也就是说,您当然可以通过代码填写端点标识,您只需创建正确类型的 EndpointIdentity 派生类并将其附加到实例化代理类时使用的 EndpointAddress 对象即可。 像这样的事情:
Creating your proxies manually does not impede you from putting the configuration in the config file; you just need to expose the right constructor overload in your ClientBase-derived proxy class that delegates to the right constructor in ClientBase that takes the name of an endpoint to look up in the configuration.
That said, you can of course fill in the endpoint identity through code, you just need to create the right kind of EndpointIdentity-derived class and attach it to the EndpointAddress object you use when you instantiate the proxy class. Something like this:
尽管我可能不会直接回答您的问题,但要在栅栏两侧使用相同的数据成员,您不需要手动创建代理。 您要做的就是使用 svcutil 生成代理,并传入将数据成员作为 /r 的 dll,
例如,
这样,数据成员类型就不会在 ServiceProxy.cs 文件中重复。 您可以通过传递 wsdl/xsd (真正的契约优先方法)来广泛自定义它,使用 /ct 等自定义集合类型。
这将为您节省大量手动制作代理的时间,同时避免您可能遇到的上述问题相遇,因为一切都变成了库存标准。
Although I am probably not answering your question directly, to use the same datamember on both side of the fence, you don't need to create the proxies manually. What you do is that you generate your proxies using svcutil and you pass in the dll that has your datamember as /r
e.g
With this, the datamember types are not repeated in your ServiceProxy.cs file. You can customize this extensively by passing wsdl/xsd (true contract first approach), customise the collectiontypes with /ct, etc etc.
This will save you many hours manually crafting your proxies, and at the same time avoid issues like above that you may encounter because everything then becomes stock standard.