2

我有一个本地运行的 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>

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

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

下一个是什么?获取 mode="Transport" 工作?使用 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() 的这种简单实例化似乎有效(至少在本地)。

4

1 回答 1

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) 格式作为地址。

同样,我不确定这如何转换为配置文件。我希望这可以帮助您走上正确的道路。

于 2012-05-23T12:13:34.010 回答