如何在WCF中解决SecurityNegotiationException和InvalidCredentialException

问题描述 投票:1回答:2

所以我写了一个小游戏,希望游戏可以在互联网上播放。

我一直在使用这些配置通过localhost测试游戏:

客户Winapp应用:

App.Config文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <system.serviceModel>
    <client>
        <endpoint name ="CommandBoard"
                  address="net.tcp://localhost:9000/commandboard"
                  binding = "netTcpBinding"
                  contract="CommandBoardServiceLibrary.ICommandBoardService"/>
    </client>
  </system.serviceModel>
</configuration>

在客户端Winform代码中,我将它连接起来

ChannelFactory<ICommandBoardService> remoteFactory= new ChannelFactory<ICommandBoardService>("CommandBoard");
ICommandBoardService proxy = remoteFactory.CreateChannel();

接下来,为了托管服务,我创建了一个控制台应用程序

App.config是基本的。我没有改变任何东西,仅在实际代码中。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>

控制台应用代码:

static void Main(string[] args)
{
    using (ServiceHost host = new ServiceHost(typeof(CommandBoardServiceLibrary.CommandBoardService)))
    {
        host.AddServiceEndpoint(typeof(
            CommandBoardServiceLibrary.ICommandBoardService),
            new NetTcpBinding(),
            "net.tcp://localhost:9000/commandboard");
        host.Open();

        Console.ReadLine();
     }
}

同时运行客户端和主机在我的计算机上完美运行。

现在,当我将客户端的App.Config更改为

<client>
    <endpoint name ="CommandBoard"
              address="net.tcp://23.122.59.211:9000/commandboard"
              binding = "netTcpBinding"
              contract="CommandBoardServiceLibrary.ICommandBoardService"/>
</client>

并在另一个网络上的另一台计算机上运行它我得到以下错误:System.ServiceModel.Security.SecurityNegotiationException: The server has rejected the client credentials. ---> System.Security.Authentication.InvalidCredentialException: The server has rejected the client credentials. ---> System.ComponentModel.Win32Exception: The logon attempt failed

这个错误的来源在哪里?配置不正确吗?或者我错过了什么?

编辑:WCF服务的Web.config

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>
c# wcf exception networking network-programming
2个回答
0
投票

WCF的所有配置都在<system.serviceModel>标记内完成。这适用于主机和客户端。由于您的主机服务没有serviceModel标记,因此WCF将应用netTcpBinding的默认值,即传输安全性。

客户端有一个服务模型标记,但没有安全设置,因此它也将尝试netTcpBinding的默认值。

您可以使用Visual Studio附带的“WCF服务配置编辑器”工具为客户端和主机设置绑定和安全性,但基本上,您需要覆盖默认值。

在客户端和服务器上为端点创建配置,并将绑定配置等于“”,如下所示:

 <endpoint address=""
           binding="netTcpBinding"
           bindingConfiguration=""
           name="NetTcpBindingEndpoint"
           contract="WCFHostService.IMyService">

Here你可以找到netTcpBinding的完整指南。


0
投票

根据您的配置以及它确实在本地工作的事实,意味着您已正确配置了一部分。但是,您应该为您的主机部分执行此操作。

<endpoint address= ""
     binding="netTcpBinding"
     bindingConfiguration= ""
     name= "NetTcpBindingEndpoint"
     contract="Reference.To.Your.Interface.IMyService">

     <identity>
         <dns value="localhost" />
     </identity>
</endpoint>

现在,重要的部分之一是,您需要物理地公开元数据。如果没有配置该端点,您将遇到严重问题。

<endpoint address="mex"
     binding="mexTcpBinding"
     bindingConfiguration= ""
     name="MexTcpBindingEndpoint"
     contract="IMetadataExchange" />

<host>
    <baseAddress>
         <add baseAddress="net.tcp://localhost:8523/WcfTestService" />
    </baseAddress>
</host>

现在您已配置主机的该部分,您需要物理安装该服务。您只需发布,构建,安装可执行文件,然后通过服务验证服务确实在您的计算机上运行

这是我相信你有问题的另一部分,通过svc utility。您无法为您的服务生成有效的URI。如果您已正确配置主机,这将起作用:

  1. 右键单击您的客户端应用程序
  2. 添加服务参考
  3. URI设置为:net.tcp://localhost:8523/ServiceName然后单击Go。它应该解决,或者您可以尝试自动解决。可能需要更改端口号。

获得参考后,它应该像以下一样简单:

  WCFTestService.MyServiceClient myService =
     new WCFTestService.MyServiceClient();
  MessageBox.Show(myService.DoWork("Hello World!"));
  myService.Close();

您创建Client对象,然后从界面公开该方法。这种方法还应该减轻这些安全问题。我有一种感觉,因为正在使用无效的URI。

您可能还需要以管理员身份运行Visual Studio。

我希望有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.