我已经关注了许多msdn文章和codeplex指南,但无法让WCF使用Kerberos身份验证和委派,并希望得到一些帮助。
设置
我在远程计算机上的IIS网站上有WCF服务
我在8080上使用Brian Booth's debug site,该网站传递了Kerberos委派的所有要求。调试IIS站点已关闭匿名身份验证,并且已启用集成Windows身份验证。
我已将这些设置镜像到托管WCF服务的网站。
网络服务 - 网络配置(原创)
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WsHttpBindingConfig">
<security>
<message negotiateServiceCredential="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="ServiceBehavior" name="Service">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="WsHttpBindingConfig"
contract="IService">
<identity>
<servicePrincipalName value="http/myserver" />
<dns value="" />
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization
impersonateCallerForAllOperations="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
网络服务 - 网络方法
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetCurrentUserName()
{
string name = WindowsIdentity.GetCurrent().Name;
return name;
}
客户端应用 - 应用配置
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService"
... />
...
<security mode="Message">
<transport clientCredentialType="Windows"
proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows"
negotiateServiceCredential="true"
algorithmSuite="Default"
establishSecurityContext="true" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://myserver/Service.svc"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService"
contract="KerberosService.IService"
name="WSHttpBinding_IService">
<identity>
<servicePrincipalName value="http/myserver" />
</identity>
</endpoint>
</client>
</system.serviceModel>
应用程序错误
当我的测试应用程序(WinForms应用程序)尝试调用Web方法时,会发生以下错误:
“HTTP请求未经授权 客户认证方案 '匿名'。身份验证标头 从服务器收到了 '协商,NTLM'“。
事件记录
事件日志中出现以下错误:
例外: System.ServiceModel.ServiceActivationException: 服务'/Service.svc'不能 由于异常期间激活 汇编。异常消息 是:此服务的安全设置 需要'匿名'身份验证但是 它没有启用IIS 承载此服务的应用程序。
我不明白。此服务的重点是不允许匿名身份验证,每个用户/请求必须使用Kerberos票证进行身份验证,然后将其传递给其他计算机。
如何为Kerberos身份验证和委派配置此WCF服务?
修订版1
阅读this SO question后,我删除了元数据端点。这还没有解决问题。
修订版2
经过更多的研究,我发现了一些建议将wsHttpBinding更改为basicHttpBinding的帖子。下面包含了对web.config部分的修改,并且服务端点已更新以引用该绑定。
网络服务 - 网络配置(已修订)
<basicHttpBinding>
<binding name="basicBindingConfig">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"
proxyCredentialType="Windows"
realm="" />
</security>
</binding>
</basicHttpBinding>
客户端应用 - 应用配置(已修订)
<!-- ... -->
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"
proxyCredentialType="Windows"
realm="" />
<message clientCredentialType="UserName"
algorithmSuite="Default" />
</security>
<!-- ... -->
错误(已修订)
当前错误看起来像包含Kerberos身份验证标头。
HTTP请求未经授权 客户认证方案 '谈判'。身份验证标头 从服务器收到了 '谈判SOMEHUGESCARYKEYHERE
答案 0 :(得分:7)
对我来说,目前的设置确实有效:
在服务器上:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttpBindingConf" useDefaultWebProxy="true"/>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="returnFaults" name="Epze.BusinessLayer.ZeitManager">
<endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBindingConf" contract="Epze.Contract.IZeitManager"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="returnFaults">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization impersonateCallerForAllOperations="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
在WCF的所有方法上设置以下属性:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
在客户端:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IZeitManager" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>
<message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="Delegation">
<clientCredentials>
<windows allowedImpersonationLevel="Delegation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="http://server.mydomain.net/ePZEsvc/ZeitManager.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IZeitManager"
contract="External.Epze.IZeitManager" name="WSHttpBinding_IZeitManager" behaviorConfiguration="Delegation">
<identity>
<servicePrincipalName value="HOST/localhost"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
HTH,Sven
答案 1 :(得分:3)
我注意到的一点:客户端和服务器配置似乎不同意安全模式。
在原始部分中,您在web.config中有<security>.....
(省略了mode =“message”),在客户端有<security mode="Message">
。
编辑后,似乎客户端未更改,但服务器(web.config)现在包含<security mode="TransportCredentialOnly">
。
真正的问题是:你能保证在客户端和被叫服务器之间只有一个网络支路吗?即这是企业防火墙的背后吗?在这种情况下,我建议在两端使用<security mode="Transport">
进行netTcp绑定。
如果情况并非如此,那么你可以使用wsHttpBinding(它支持更多安全性和可靠性功能,但速度更慢,更“重”)或basicHttpBinding。在这种情况下,您必须在两端使用<security mode="Message">
,并使用证书对服务进行身份验证(以便服务和客户端具有用于加密的共同“秘密”)。
我会尝试在开始时省略模拟部分,然后首先获得服务和客户端之间的基本通信和相互身份验证 - 一旦到位,您可以开始向其添加模拟位,并且你可以随时使用已知的配置。
大卫·萨克斯坦(David Sackstein)有一个great series of blog posts解释了行业大师Juval Lowy已经确定的五种安全方案(在他的Programming WCF书中 - WCF圣经)是最常见和最有用的 - 以限制您可能想要调整的参数组合的数量。其中一个是“互联网”场景,如果您的服务面向外,这可能适用于此。马克
答案 2 :(得分:2)
您需要在客户端配置中指定behaviorConfiguration。 SVCUtil不会自动生成。这解决了我的问题,现在我成功使用了Kerberos。这是一个使命!
<client>
<endpoint address="..."
binding="customBinding" bindingConfiguration="..."
contract="..." name="..." behaviorConfiguration="ImpersonationBehavior" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="ImpersonationBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation"/> </clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
答案 3 :(得分:1)
您应该尝试初始配置,并确保同时将IIS设置为匿名和Windows身份验证。原因是当您使用wsHttpBinding时,默认安全性是邮件安全性,除非您需要,否则没有定义传输安全性做https。 SO Clr声明它需要在IIS上启用匿名身份验证。