【问题标题】:WCF Transport Windows Authentication with NET.TCP only works locally使用 NET.TCP 的 WCF 传输 Windows 身份验证仅在本地工作
【发布时间】:2012-05-23 10:51:30
【问题描述】:

我有一个本地运行的 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() 的这种简单实例化似乎可以工作(至少在本地)。

【问题讨论】:

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


    【解决方案1】:

    我通常在代码中配置我的 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) 格式的地址。

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

    【讨论】:

    • 我使用代码来创建客户端,但配置来创建服务器。不要问我为什么,就这样发生了.. 大声笑.. 仍然没有得到任何快乐,这是我在客户端上使用的代码。你是使用渠道还是代理,还是像我上面那样打开客户端?
    • 我会挖掘一些我为另一个项目所做的代码,看看我可能遗漏了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多