我开发了一个在IIS中运行的WCF服务(确切地说是IIS 7.5)。此服务在其自己的应用程序池下,在特定的域标识下运行。这项服务参考&调用网络中其他地方托管的其他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'.
有人可以帮助我,或指出我如何实施此身份验证配置的正确方向?
答案 0 :(得分:0)
我设法找到了一个有效的解决方案。它实现如下:
客户端代理凭据需要设置为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>
通过这种配置,我能够通过用户名和电子邮件对我的服务进行身份验证。密码,然后让我的服务使用IIS中运行应用程序池的域凭据访问SQL Server实例。