使用 kerberos 的 WCF 配置在某些域上失败
WCF configuration using kerberos fails on certain domains
我不太确定,这个问题就在 Whosebug 上...也许它属于 serverfault...无论如何,它是这样的:
我们有 server/client 实施 WCF 服务的设置。客户端和服务都在域用户下 运行。托管服务器端服务的域用户也是服务器上的本地管理员。此设置适用于大多数客户。某些客户抱怨说,他们无法使用服务器的主机名进行单点登录 (SSO)。我们跟进了那个问题并发现,如果我们指定服务器的 IP 地址,一切正常。对我来说,这表明我们的配置工作正常,但某些域配置会干扰我们的设置。
WCF 配置:
<configuration>
<system.serviceModel>
<client>
<!-- minimal needed config, address will be ignored -->
<endpoint address="net.tcp://inihost:10100/ApplicationService" binding="netTcpBinding"
bindingConfiguration="nosecNetTcpBinding" name="ApplicationServiceHost"
contract="Kaba.Exos.Transport.Infrastructure.ICommandExecutionService" />
<endpoint address="net.tcp://inihost:10100/ApplicationServiceSSO" binding="netTcpBinding"
bindingConfiguration="ssoNetTcpBinding" name="ApplicationServiceSsoHost"
contract="Kaba.Exos.Transport.Infrastructure.ICommandExecutionService" />
</client>
<bindings>
<netTcpBinding>
<binding name="nosecNetTcpBinding" receiveTimeout="00:30:00" sendTimeout="00:30:00" maxBufferPoolSize="134217728" maxBufferSize="134217728" maxReceivedMessageSize="134217728">
<security mode="None"></security>
</binding>
<binding name="ssoNetTcpBinding" receiveTimeout="00:30:00" sendTimeout="00:30:00" maxBufferPoolSize="134217728" maxBufferSize="134217728" maxReceivedMessageSize="134217728">
<security mode="Transport">
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>
设置 WCF 连接的 C# 代码:
var exeConfigFileFullPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\" + exeConfigFilename;
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = exeConfigFileFullPath };
var newConfig = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
try
{
this.channelFactory = new ConfigurationChannelFactory<ICommandExecutionServiceChannel>(endpointConfigurationName, newConfig, null);
}
catch (Exception e)
{
traceLogger.TraceException(e, "CommandExecutionServiceClient", "CommandExecutionServiceClient");
throw;
}
if (!string.IsNullOrEmpty(serviceConnection.Item1))
{
var builder = new UriBuilder(this.channelFactory.Endpoint.Address.Uri) { Host = serviceConnection.Item1, Port = serviceConnection.Item2 };
this.channelFactory.Endpoint.Address = new EndpointAddress(builder.Uri);
}
this.AddForwardExceptionToClientEndpointBehavior();
}
实施两个小改动后....
在 WCF 文件中
<!-- minimal needed config, address will be ignored -->
<endpoint address="net.tcp://inihost:10100/ApplicationServiceSSO" binding="netTcpBinding"
bindingConfiguration="ssoNetTcpBinding" name="ApplicationServiceSsoHost"
contract="Kaba.Exos.Transport.Infrastructure.ICommandExecutionService" behaviorConfiguration="kerberosFallbackToNtlm">
<behaviors>
<endpointBehaviors>
<behavior name="kerberosFallbackToNtlm">
<clientCredentials>
<!-- if Kerberos is required, set the following value to false and configure the proper identity for Exos9300ServiceSsoHost above. -->
<windows allowNtlm="true" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
在代码中
this.channelFactory.Endpoint.Address = new EndpointAddress(builder.Uri, EndpointIdentity.CreateSpnIdentity(String.Empty));
此设置适用于域设置,我们之前在域设置中遇到了 "SSPI context could not be established" 错误。
现在我的问题是:
为什么这个设置在一个域上运行良好,但在另一个域上却失败了。是否有任何可能影响此行为的 Active Directory 设置?
好吧,事实证明我被误导了....在它工作的情况下,我们有一个本地用户 运行 服务而不是域用户。因此,如果服务由本地管理员用户托管,服务身份验证将回退到 NTLM。
通过删除默认创建的 SPN 并手动添加新的 SPN,我确实设法让这个场景起作用。
删除默认创建的现有 SPN:
setspn -D HOST/{HOSTNAME server} {HOSTNAME server}
为域用户添加新的 SPN:
setspn -S HOST/{HOSTNAME server} {Domainuser service}
注意!!
一旦我发出命令:
setspn -D HOST/{FQDN server} {HOSTNAME server}
并设法禁止我的服务器使用域控制器对任何域用户进行身份验证,因为它不再位于信任数据库中。
我不太确定,这个问题就在 Whosebug 上...也许它属于 serverfault...无论如何,它是这样的:
我们有 server/client 实施 WCF 服务的设置。客户端和服务都在域用户下 运行。托管服务器端服务的域用户也是服务器上的本地管理员。此设置适用于大多数客户。某些客户抱怨说,他们无法使用服务器的主机名进行单点登录 (SSO)。我们跟进了那个问题并发现,如果我们指定服务器的 IP 地址,一切正常。对我来说,这表明我们的配置工作正常,但某些域配置会干扰我们的设置。
WCF 配置:
<configuration>
<system.serviceModel>
<client>
<!-- minimal needed config, address will be ignored -->
<endpoint address="net.tcp://inihost:10100/ApplicationService" binding="netTcpBinding"
bindingConfiguration="nosecNetTcpBinding" name="ApplicationServiceHost"
contract="Kaba.Exos.Transport.Infrastructure.ICommandExecutionService" />
<endpoint address="net.tcp://inihost:10100/ApplicationServiceSSO" binding="netTcpBinding"
bindingConfiguration="ssoNetTcpBinding" name="ApplicationServiceSsoHost"
contract="Kaba.Exos.Transport.Infrastructure.ICommandExecutionService" />
</client>
<bindings>
<netTcpBinding>
<binding name="nosecNetTcpBinding" receiveTimeout="00:30:00" sendTimeout="00:30:00" maxBufferPoolSize="134217728" maxBufferSize="134217728" maxReceivedMessageSize="134217728">
<security mode="None"></security>
</binding>
<binding name="ssoNetTcpBinding" receiveTimeout="00:30:00" sendTimeout="00:30:00" maxBufferPoolSize="134217728" maxBufferSize="134217728" maxReceivedMessageSize="134217728">
<security mode="Transport">
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
</configuration>
设置 WCF 连接的 C# 代码:
var exeConfigFileFullPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\" + exeConfigFilename;
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = exeConfigFileFullPath };
var newConfig = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
try
{
this.channelFactory = new ConfigurationChannelFactory<ICommandExecutionServiceChannel>(endpointConfigurationName, newConfig, null);
}
catch (Exception e)
{
traceLogger.TraceException(e, "CommandExecutionServiceClient", "CommandExecutionServiceClient");
throw;
}
if (!string.IsNullOrEmpty(serviceConnection.Item1))
{
var builder = new UriBuilder(this.channelFactory.Endpoint.Address.Uri) { Host = serviceConnection.Item1, Port = serviceConnection.Item2 };
this.channelFactory.Endpoint.Address = new EndpointAddress(builder.Uri);
}
this.AddForwardExceptionToClientEndpointBehavior();
}
实施两个小改动后....
在 WCF 文件中
<!-- minimal needed config, address will be ignored -->
<endpoint address="net.tcp://inihost:10100/ApplicationServiceSSO" binding="netTcpBinding"
bindingConfiguration="ssoNetTcpBinding" name="ApplicationServiceSsoHost"
contract="Kaba.Exos.Transport.Infrastructure.ICommandExecutionService" behaviorConfiguration="kerberosFallbackToNtlm">
<behaviors>
<endpointBehaviors>
<behavior name="kerberosFallbackToNtlm">
<clientCredentials>
<!-- if Kerberos is required, set the following value to false and configure the proper identity for Exos9300ServiceSsoHost above. -->
<windows allowNtlm="true" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
在代码中
this.channelFactory.Endpoint.Address = new EndpointAddress(builder.Uri, EndpointIdentity.CreateSpnIdentity(String.Empty));
此设置适用于域设置,我们之前在域设置中遇到了 "SSPI context could not be established" 错误。
现在我的问题是:
为什么这个设置在一个域上运行良好,但在另一个域上却失败了。是否有任何可能影响此行为的 Active Directory 设置?
好吧,事实证明我被误导了....在它工作的情况下,我们有一个本地用户 运行 服务而不是域用户。因此,如果服务由本地管理员用户托管,服务身份验证将回退到 NTLM。
通过删除默认创建的 SPN 并手动添加新的 SPN,我确实设法让这个场景起作用。
删除默认创建的现有 SPN:
setspn -D HOST/{HOSTNAME server} {HOSTNAME server}
为域用户添加新的 SPN:
setspn -S HOST/{HOSTNAME server} {Domainuser service}
注意!!
一旦我发出命令:
setspn -D HOST/{FQDN server} {HOSTNAME server}
并设法禁止我的服务器使用域控制器对任何域用户进行身份验证,因为它不再位于信任数据库中。