使用NET.TCP的WCF传输Windows身份验证仅在本地运行

时间:2012-05-23 10:51:31

标签: c# wcf wcf-binding windows-authentication net.tcp

我有一个在本地运行的WCF服务,以及一个远程运行的客户端。我已将双方的绑定匹配到:

<binding name="TcpBindingConfiguration_2">
  <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
  <security mode="Transport">
    <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign"/>
    <message clientCredentialType="Windows"/>
  </security>
</binding>

我有一个虚拟方法设置,它只返回Thread.CurrentPrincipal.Identity.Name,ServiceSecurityContext.Current.WindowsIdentity.Name和OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name(如果可用)。

在与服务器相同的计算机上运行客户端时,传输模式工作正常,并且所有三个身份名称都可用。但是,当从远程主机(在相同和不同域上的主机上测试)连接到我的本地计算机时,我得到了可怕的“服务器已拒绝客户端凭据”消息。

如果我将绑定更改为:

<binding name="TcpBindingConfiguration_1">
  <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
  <security mode="None"/>
</binding>

建立连接并且dummy方法不返回任何名称(正如我想象的那样)。

有人可以使用net.tcp绑定在不同主机(有时是不同的可信域)之间共享其启用Windows身份验证的配置吗?我已经看到很多例子只是说将安全模式设置为None,这一切都很好,但我仍然想确定谁在拨打电话。

接下来是什么?获取模式=“运输”工作?使用mode =“None”并实施其他类型的授权?更改为成功使用Windows身份验证的其他绑定?

如果在别处得到回答,请道歉;我只是找不到它的确切答案。

更新:这是我现在用来创建客户端的代码:

var endPointAddress = "net.tcp://" + remoteHost + ":8092/Marc/WcfService";
EndpointAddress address = new EndpointAddress(new Uri(endPointAddress), EndpointIdentity.CreateSpnIdentity("AppName/" + remoteHost), new AddressHeaderCollection());
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;

using (var remoteService = new RemoteService.GuestServiceClient(binding, address))
{
    try
    {
        MessageBox.Show(remoteService.Hello("Marc"));
        remoteService.Close();
    }
    catch (Exception ex)
    {
        remoteService.Abort();
        MessageBox.Show("Error occurred:\n\n" + ex.Source + "\n\n" + ex.Message, "Could not connect to " + remoteHost, MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

remoteHost被设置为远程计算机的IP地址。

我应该使用频道和代理吗?我已经在其他地方看到了其他代码,但是这个GuestServiceClient()的简单实例似乎可以工作(至少在本地)。

1 个答案:

答案 0 :(得分:0)

我通常在代码中配置我的WCF服务,所以我不确定这会如何转换为配置文件。

根据我多年前的研究,您需要添加服务主体名称(SPN)作为客户端点的一部分。服务器端不需要更改。

在代码中它看起来像这样:

string endPointAddress = String.Format("net.tcp://{0}:1111/ServiceName", ServerAddress);
EndpointAddress address = new EndpointAddress(new Uri(endPointAddress), EndpointIdentity.CreateSpnIdentity("AppName/" + ServerAddress), new AddressHeaderCollection());
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.Transport;

第二行是将SPN添加到连接信息的内容。在EndpointIdentity.CreateSpnIdentity中,字符串的格式为AppName / ServerAddress。 “AppName”部分可以是任何内容,但我建议您的应用程序使用独特的内容。我通常使用FQDN(host.domain.com)格式作为地址。

同样,我不确定这是如何转换为配置文件的。我希望这有助于您开始走正确的道路。