【发布时间】:2015-03-05 21:12:50
【问题描述】:
我正在尝试从客户端应用程序(Windows 窗体)到在 IIS 下运行的一个 Windows 2008 R2 服务器上的 WCF Web 服务执行 Kerberos 身份验证,这反过来又调用在另一个也在运行的 Windows 2008 R2 服务器上运行的另一个 WCF 服务在 IIS 下。我已经看到这被称为 Kerberos 双跳身份验证。
当我在同一个 Windows 2008 R2 服务器上找到这两个 Web 服务时,我们的双跳身份验证工作正常。但是,当我们将第二个 WCF 服务移动到不同的服务器时,两个 Web 服务之间的身份验证失败。我不知道是什么导致了这个问题,这可能是配置问题,或者是我们的服务器/网络设置中的问题。客户端和服务器都存在于同一个域中。
这里是我迄今为止所做的更多细节。我已经尝试了有关此问题的其他相关主题/问题中的许多建议,但到目前为止没有任何乐趣。
- 我创建了一个 Windows 窗体客户端应用程序,该应用程序连接到 WCF Web 服务(我将其称为中间服务),以及 将登录用户的用户名从 服务。
- 在客户端 app.config(见下文)中,我们指定了“Windows” 身份验证(请参阅下面的配置)。
- 中间服务在我们的服务器“SERVER1”上运行。
- 中间服务将用户名返回给客户端应用程序, 因此,中间服务身份验证必须正常工作。
- 我在中间服务中有另一个方法调用另一个 WCF Web 服务(我将这第二个服务称为 End 服务), 并再次在绑定中指定 Windows 身份验证 中间服务到终端服务。如果我在 与中间服务相同的服务器,然后再次进行身份验证 预期,登录用户的用户名(即:我)是 从 End 服务返回到客户端应用程序,通过 Middle 服务。但是,如果我在不同的服务器上找到 End 服务 (SERVER2)身份验证(双跳)失败,'内部异常: 无法满足对安全令牌的请求,因为 身份验证失败。'
- Client 应用程序、Middle 服务和 End 服务都存在于同一个 域 (MYDOMAIN)。
- 我正在使用服务帐户 (MYDOMAIN\MY-HOST_ACCOUNT) 来运行两者 中间和终端服务,并创建了服务主体名称 (SPN) 为此称为“HTTP/SERVER1.int.mydomain.com”。我也信任过 此服务帐户,以及 Kerberos 的计算机/机器“SERVER1” Active Directory 中的委派(信任此用户/计算机 委托给任何服务)。绑定使用“消息”安全模式 这在 Web 服务绑定中指定。
- 我已经包含了客户端 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>
中间服务网络配置
<?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. ---&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. ---&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)
【问题讨论】:
标签: c# web-services wcf authentication kerberos