将 IIS 应用程序池帐户委托给 WCF 服务调用
Delegate IIS Application Pool account to WCF service calls
我在 IIS(确切地说是 IIS 7.5)中开发了 运行 的 WCF 服务。此服务在其自己的应用程序池下运行,在特定的域身份下。此服务引用并调用网络中其他地方托管的其他 WCF 服务,这些服务依次访问各种资源(事件日志、SQL 服务器等)。
通过自定义 UserNamePasswordValidator
使用用户名和密码对对我的服务的调用进行身份验证。使用的用户名 不是 域凭据。
我想做的是,当我的服务被调用时,它又使用生成的代理 类 调用引用的服务,它将应用程序池身份委托为调用身份,因为此域帐户已被授予访问后台资源的权限,例如 SQL Server.
我目前的实现如下:
服务配置
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="RemoteServiceBinding" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="MyServiceBinding" closeTimeout="00:10:00" openTimeout="00:10:00"
receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" />
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://remote.service.address/Service.svc"
binding="basicHttpBinding" bindingConfiguration="RemoteServiceBinding"
contract="RemoteService.IRemoteService" name="RemoteServiceBinding" />
</client>
<services>
<service name="MyService.MyService" behaviorConfiguration="MyServiceBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyServiceBinding" contract="MyService.IMyService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/MyService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="None" />
</clientCertificate>
<serviceCertificate findValue="AuthCert" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyService.CredentialValidator, MyService" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
服务行为代码
using (var client = new Proxy.RemoteServiceClient()) {
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
return client.PerformAction();
}
使用此代码,每当客户端调用我的服务时,都会抛出以下内容:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'.
有人可以帮助我,或者为我指明如何实施此身份验证配置的正确方向吗?
我设法找到了可行的解决方案。它是这样实现的:
客户端代理凭据需要设置为 IIS 应用程序池的凭据,因为这些不会自动获取:
client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
另外,我连接的远程服务有一个服务主体需要包含在端点配置中。所以我将 VS 工具生成的配置修改为以下内容:
<client>
<endpoint address="http://remote.service.address/Service.svc"
binding="basicHttpBinding" bindingConfiguration="RemoteServiceBinding"
contract="RemoteService.IRemoteService" name="RemoteServiceBinding">
<identity>
<servicePrincipalName value="spn_name" />
</identity>
</endpoint>
</client>
使用此配置,我能够通过用户名和密码对我的服务进行身份验证,然后让我的服务使用应用程序池 运行 所在的域凭据访问 SQL 服务器实例在 IIS 中。
我在 IIS(确切地说是 IIS 7.5)中开发了 运行 的 WCF 服务。此服务在其自己的应用程序池下运行,在特定的域身份下。此服务引用并调用网络中其他地方托管的其他 WCF 服务,这些服务依次访问各种资源(事件日志、SQL 服务器等)。
通过自定义 UserNamePasswordValidator
使用用户名和密码对对我的服务的调用进行身份验证。使用的用户名 不是 域凭据。
我想做的是,当我的服务被调用时,它又使用生成的代理 类 调用引用的服务,它将应用程序池身份委托为调用身份,因为此域帐户已被授予访问后台资源的权限,例如 SQL Server.
我目前的实现如下:
服务配置
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="RemoteServiceBinding" closeTimeout="00:10:00"
openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"
maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="MyServiceBinding" closeTimeout="00:10:00" openTimeout="00:10:00"
receiveTimeout="00:10:00" sendTimeout="00:10:00" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"
maxBytesPerRead="2147483647" />
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://remote.service.address/Service.svc"
binding="basicHttpBinding" bindingConfiguration="RemoteServiceBinding"
contract="RemoteService.IRemoteService" name="RemoteServiceBinding" />
</client>
<services>
<service name="MyService.MyService" behaviorConfiguration="MyServiceBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MyServiceBinding" contract="MyService.IMyService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/MyService/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="None" />
</clientCertificate>
<serviceCertificate findValue="AuthCert" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyService.CredentialValidator, MyService" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
服务行为代码
using (var client = new Proxy.RemoteServiceClient()) {
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Delegation;
return client.PerformAction();
}
使用此代码,每当客户端调用我的服务时,都会抛出以下内容:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'.
有人可以帮助我,或者为我指明如何实施此身份验证配置的正确方向吗?
我设法找到了可行的解决方案。它是这样实现的:
客户端代理凭据需要设置为 IIS 应用程序池的凭据,因为这些不会自动获取:
client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
另外,我连接的远程服务有一个服务主体需要包含在端点配置中。所以我将 VS 工具生成的配置修改为以下内容:
<client>
<endpoint address="http://remote.service.address/Service.svc"
binding="basicHttpBinding" bindingConfiguration="RemoteServiceBinding"
contract="RemoteService.IRemoteService" name="RemoteServiceBinding">
<identity>
<servicePrincipalName value="spn_name" />
</identity>
</endpoint>
</client>
使用此配置,我能够通过用户名和密码对我的服务进行身份验证,然后让我的服务使用应用程序池 运行 所在的域凭据访问 SQL 服务器实例在 IIS 中。