C# 具有Kerberos身份验证的WCF:无法满足对安全令牌的请求,因为身份验证失败

C# 具有Kerberos身份验证的WCF:无法满足对安全令牌的请求,因为身份验证失败,c#,web-services,wcf,authentication,kerberos,C#,Web Services,Wcf,Authentication,Kerberos,我正在尝试从客户端应用程序(Windows窗体)到运行在IIS下的一台Windows 2008 R2服务器上的WCF Web服务执行Kerberos身份验证,该服务器反过来调用运行在同样运行在IIS下的另一台Windows 2008 R2服务器上的另一个WCF服务。我看到过,这称为Kerberos双跳身份验证 当我在同一台Windows2008R2服务器上找到这两个web服务时,我们的双跳身份验证工作正常。但是,当我们将第二个WCF服务移动到另一个服务器时,两个web服务之间的身份验证将失败。我

我正在尝试从客户端应用程序(Windows窗体)到运行在IIS下的一台Windows 2008 R2服务器上的WCF Web服务执行Kerberos身份验证,该服务器反过来调用运行在同样运行在IIS下的另一台Windows 2008 R2服务器上的另一个WCF服务。我看到过,这称为Kerberos双跳身份验证

当我在同一台Windows2008R2服务器上找到这两个web服务时,我们的双跳身份验证工作正常。但是,当我们将第二个WCF服务移动到另一个服务器时,两个web服务之间的身份验证将失败。我不知道是什么原因导致了这个问题,可能是配置问题,或者是服务器/网络设置中的问题。客户端和服务器都存在于同一个域中

以下是我到目前为止所做工作的更多细节。我在其他相关主题/问题中尝试了许多关于这个问题的建议,但到目前为止没有任何乐趣

  • 我创建了一个Windows窗体客户端应用程序,该应用程序连接到 WCF web服务(我将其称为中间服务),以及 将登录用户的用户名从返回到客户端应用程序 服务
  • 在client app.config(见下文)中,我们指定了“Windows” 认证(请参见下面的配置)
  • 中间服务在我们的服务器“SERVER1”上运行
  • 中间服务将用户名返回给客户端应用程序, 因此,中间服务身份验证必须正常工作
  • 在中间服务中有另一个方法调用另一个WCF。 web服务(我将第二个服务称为终端服务), 并且再次在来自的绑定上指定Windows身份验证 中间服务到终端服务。如果我在 与中间服务相同的服务器,然后身份验证再次作为 应为,并且登录用户(即:me)的用户名为 从终端服务通过中间层返回到客户端应用程序 服务但是,如果我在另一台服务器上找到最终服务 (SERVER2)身份验证(双跳)失败,“内部异常: 无法满足对安全令牌的请求,因为 身份验证失败。'
  • 客户端应用程序、中间服务和终端服务都存在于同一个应用程序中 域(MYDOMAIN)
  • 我正在使用一个服务帐户(MYDOMAIN\MY-HOST\u帐户)来运行这两个帐户 中间和终端服务,并创建服务主体名称(SPN) 对于这个名为“HTTP/SERVER1.int.mydomain.com”的文件。我也相信 此服务帐户和Kerberos的计算机/计算机“SERVER1” Active Directory中的委派(信任此用户/计算机 任何服务的授权)。绑定使用“消息”安全模式 这是在Web服务绑定中指定的
  • 我已经包括了Client app.config和两个Web服务 web.configs(请参见下文)
  • 我尝试了各种不同的配置设置,这些 当服务位于同一位置时,当前设置工作正常 但当服务位于不同的服务器上时会发生错误 服务器。我已经试过“真”和“假”两种说法 “negotiateServiceCredential”,但请相信这需要是“真实的”。我 当设置为false时,获取不同的错误消息( 使用Kerberos的身份验证模式不支持模拟 级别“委派”。指定标识或模拟)
希望以前处理过“双跳”WCF Kerberos身份验证的人能够认识到这个问题并能够帮助我

非常感谢

客户端应用程序配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IMiddleService">
                    <security mode="Message">
                        <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" algorithmSuite="Default" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <behaviors>
          <endpointBehaviors>
            <behavior name="DelegationBehavior">
              <clientCredentials>
                <windows allowedImpersonationLevel="Delegation" />
              </clientCredentials>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <client>
          <endpoint address="http://SERVER1/KerberosMiddleService/MiddleService.svc"
              behaviorConfiguration="DelegationBehavior" binding="wsHttpBinding"
              bindingConfiguration="WSHttpBinding_IMiddleService" contract="KerberosMiddleService.IMiddleService"
              name="WSHttpBinding_IMiddleService">
            <identity>
              <servicePrincipalName value="HTTP/SERVER1.int.mydomain.com"/>
              <userPrincipalName value="MYDOMAIN\MY-HOST_ACCOUNT@int.mydomain.com"/>
            </identity>
          </endpoint>
        </client>
    </system.serviceModel>
</configuration>

中间服务WEB配置

<?xml version="1.0"?>
<configuration>
  <appSettings/>
  <system.web>
    <compilation targetFramework="4.0"/>
    <httpRuntime/>
    <customErrors mode="Off"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IEndService">
          <security mode="Message">
            <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" algorithmSuite="Default"/>
          </security>
         </binding>
          <binding name="WSHttpBinding_IEndService1">
          <security mode="Message">
            <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" algorithmSuite="Default" />
          </security>
         </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
          <!-- 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="true"/>
          <serviceAuthorization impersonateCallerForAllOperations="true"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="DelegationBehavior">
         <clientCredentials>
           <windows allowedImpersonationLevel="Delegation" />
         </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <client>
      <endpoint address="http://SERVER2/endservice/endservice.svc" 
                behaviorConfiguration="DelegationBehavior" binding="wsHttpBinding" 
                bindingConfiguration="WSHttpBinding_IEndService" contract="KerberosEndService.IEndService"
                name="WSHttpBinding_IEndService">
      </endpoint>
      <endpoint address="http://SERVER1/kerberosendservice/endservice.svc" 
                behaviorConfiguration="DelegationBehavior" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_IEndService1" contract="BT01_KerberosEndService.IEndService"
                name="WSHttpBinding_IEndService1">
      </endpoint>
    </client>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme="http"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>
<?xml version="1.0"?>
<configuration>
  <appSettings/>
<system.web>
    <customErrors mode="Off"/>
    <compilation targetFramework="4.0"/>
    <httpRuntime/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceAuthorization impersonateCallerForAllOperations="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme="http"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

终端服务WEB配置

<?xml version="1.0"?>
<configuration>
  <appSettings/>
  <system.web>
    <compilation targetFramework="4.0"/>
    <httpRuntime/>
    <customErrors mode="Off"/>
  </system.web>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IEndService">
          <security mode="Message">
            <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" algorithmSuite="Default"/>
          </security>
         </binding>
          <binding name="WSHttpBinding_IEndService1">
          <security mode="Message">
            <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true" algorithmSuite="Default" />
          </security>
         </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
          <!-- 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="true"/>
          <serviceAuthorization impersonateCallerForAllOperations="true"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="DelegationBehavior">
         <clientCredentials>
           <windows allowedImpersonationLevel="Delegation" />
         </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <client>
      <endpoint address="http://SERVER2/endservice/endservice.svc" 
                behaviorConfiguration="DelegationBehavior" binding="wsHttpBinding" 
                bindingConfiguration="WSHttpBinding_IEndService" contract="KerberosEndService.IEndService"
                name="WSHttpBinding_IEndService">
      </endpoint>
      <endpoint address="http://SERVER1/kerberosendservice/endservice.svc" 
                behaviorConfiguration="DelegationBehavior" binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_IEndService1" contract="BT01_KerberosEndService.IEndService"
                name="WSHttpBinding_IEndService1">
      </endpoint>
    </client>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme="http"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>
<?xml version="1.0"?>
<configuration>
  <appSettings/>
<system.web>
    <customErrors mode="Off"/>
    <compilation targetFramework="4.0"/>
    <httpRuntime/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceAuthorization impersonateCallerForAllOperations="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme="http"/>
    </protocolMapping>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

WCF堆栈跟踪的一部分

<ExceptionString>System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service. ---&amp;gt; System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
   at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
   at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)
   --- End of inner exception stack trace ---</ExceptionString><InnerException><ExceptionType>System.ServiceModel.FaultException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The request for security token could not be satisfied because authentication failed.</Message><StackTrace>   at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
   at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)</StackTrace><ExceptionString>System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
   at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
   at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)</ExceptionString></InnerException></Exception></TraceRecord></DataItem></TraceData></ApplicationData></E2ETraceEvent><E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent"><System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system"><EventID>131075</EventID><Type>3</Type><SubType Name="Error">0</SubType><Level>2</Level><TimeCreated SystemTime="2015-03-02T21:04:14.4059347Z" /><Source Name="System.ServiceModel" /><Correlation ActivityID="{acfc80d6-b119-4f57-aaf2-65f1319b9fca}" /><Execution ProcessName="w3wp" ProcessID="1432" ThreadID="43" /><Channel/><Computer>SERVER1</Computer></System><ApplicationData><TraceData><DataItem><TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"><TraceIdentifier>http://msdn.microsoft.com/en-NZ/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier><Description>Throwing an exception.</Description><AppDomain>/LM/W3SVC/1/ROOT/KerberosMiddleService-6-130698038017642990</AppDomain><Exception><ExceptionType>System.ServiceModel.Security.SecurityNegotiationException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>The caller was not authenticated by the service.</Message><StackTrace>   at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)
   at System.ServiceModel.Security.IssuanceTokenProviderBase`1.GetNextOutgoingMessage(Message incomingMessage, T negotiationState)
   at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)</StackTrace><ExceptionString>System.ServiceModel.Security.SecurityNegotiationException: The caller was not authenticated by the service. ---&amp;gt; System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
   at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
System.ServiceModel.Security.SecurityNegotiationException:服务未对调用方进行身份验证---&;燃气轮机;System.ServiceModel.FaultException:无法满足安全令牌的请求,因为身份验证失败。
位于System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(消息消息,端点地址目标)
位于System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextToutGoingMessageBody(消息输入消息,SspiNegotiationTokenProviderState sspiState)
---内部异常堆栈跟踪结束----System.ServiceModel.FaultException,System.ServiceModel,版本=4.0.0.0,区域性=neutral,PublicKeyToken=B77A5C561934E089由于身份验证失败,无法满足对安全令牌的请求。位于System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(消息消息,端点地址目标)
在System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextToutGoingMessageBody(Message incomingMessage,SspiNegotiationTokenProviderState sspiState)System.ServiceModel.FaultException:由于身份验证失败,无法满足对安全令牌的请求。
位于System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(消息消息,端点地址目标)
在System.ServiceModel.Sec