WCF和Kerberos身份验证 - IT宝库 (2024)

问题描述

本文来自:IT宝库(https://www.itbaoku.cn)

我遵循了许多MSDN文章和Codeplex指导,但无法让WCF与Kerberos身份验证和委派一起工作,并感谢您一些帮助.

设置

我在远程计算机上的IIS网站上拥有WCF服务

  • Windows 2003 R2上的IIS 6.0 -SP 2
  • 已经添加了机器的SPN(http/myserver && http/myserver:8080)
  • 为IIS应用程序池创建了一个广告帐户
  • 广告帐户具有设置,允许委派(对于kerberos),设置为true

我正在使用 Brian Booth的调试站点在8080上,该网站通过Kerberos委派的所有要求. Debug IIS网站具有匿名身份验证,并集成了Windows身份验证.

我将这些设置镜像到托管WCF服务的站点.

Web服务 - Web Config(原始)

<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>

Web服务 - Web方法

[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

阅读这个问题我删除了元数据端口.这尚未解决问题.

修订2

在进行了更多的研究之后,我发现了一些帖子建议将wshtpbinding更改为basichttpbinding.下面包括对Web.config的部分的修改,并且已更新服务端点以参考该绑定.

Web服务 - Web配置(修订)

<basicHttpBinding> <binding name="basicBindingConfig"> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" proxyCredentialType="Windows" realm="" /> </security> </binding></basicHttpBinding>

客户端应用-App config(修订)

<!-- ... --><security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" proxyCredentialType="Windows" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /></security><!-- ... -->

错误(修订)

当前错误看起来包含一个Kerberos身份验证标头.

HTTP请求未经授权 客户认证方案 '谈判'.身份验证标题 从服务器收到的是 '谈判somehugescarykeykeyhere

推荐答案

对我来说,当前的设置确实有效:

在服务器上:

<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

其他推荐答案

我注意到的东西:客户端和服务器配置似乎在安全模式下不同意.

在原始部分中,您在web.config中具有<security>.....(省略了模式=" message"),在客户端.

.

您进行编辑后,客户端似乎没有变化,但是服务器(web.config)现在包含<security mode="TransportCredentialOnly">.

问题确实是:您能保证客户端和所调用服务器之间只有一个网络腿吗? IE.这是公司防火墙的背后吗?在这种情况下,我建议两端都使用<security mode="Transport">绑定NetTCP.

如果不是这种情况,那么您可以使用WSHTTPBINDING(它支持更多的安全性和可靠性功能,但较慢,"更重")或basichttpbinding.在这种情况下,您必须在两端都使用<security mode="Message">,并使用证书对服务进行身份验证(以便服务和客户端具有通用的"秘密",可用于加密).

我会尝试将模仿零件遗漏为一开始,而只需在服务和客户端启动和运行之间进行基本的沟通和相互认证 - 一旦到位,您就可以开始向其添加模拟位,然后您始终可以根据有效的已知配置来倒退.

戴维·萨克斯坦(David Sackstein)有一系列博客文章解释行业大师朱瓦尔·洛伊(Guru Juval Lowy)已经确定的五种安全方案(在他的编程wcf book book -the wcf圣经)是最常见和最有用的,以限制您可能可能的参数组合数量想调整.其中之一是一个"互联网"场景,如果您的服务在外面面对面,可能会在这里适用.

马克

其他推荐答案

您需要在客户端配置中指定行为con仪. 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> 

本文地址:https://www.itbaoku.cn/post/1526495.html

百度翻译此文有道翻译此文

问题描述

I have followed numerous msdn articles and the codeplex guidance but cannot get WCF to work with Kerberos authentication and delegation and would appreciate a little help.

Setup

I have the WCF service in an IIS website on a remote machine

  • IIS 6.0 on Windows 2003 R2 - SP 2
  • The SPN for the machine has been added (http/myserver && http/myserver:8080)
  • An AD account has been created for the IIS app pool
  • The AD account has the setting, allow delegation (for Kerberos), set to true

I am using Brian Booth's debug site on 8080 and the site passes all requirements for Kerberos delegation. The debug IIS site has anonymous authentication off, and Integrated Windows authentication on.

I have mirrored these settings to the site hosting the WCF service.

Web Service - Web Config (Original)

<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>

Web Service - Web Method

[OperationBehavior(Impersonation = ImpersonationOption.Required)]public string GetCurrentUserName(){ string name = WindowsIdentity.GetCurrent().Name; return name;}

Client App - App Config

<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>

Application Error

The following error occurs when my test application, a WinForms app, tries to call the web method:

"The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Negotiate,NTLM'."

Event Log

The following error is in the event log:

Exception: System.ServiceModel.ServiceActivationException: The service '/Service.svc' cannot be activated due to an exception during compilation. The exception message is: Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.

Which I don't understand. The whole point of this service is to not allow anonymous authentication, every user/request must be authenticated using Kerberos tickets, then passing them through to other machines.

How should I configure this WCF service for Kerberos authentication and delegation?

Revision 1

After reading this SO question I removed the metadata endpoint. This has not resolved the issue.

Revision 2

After more researching I found a few posts suggesting to change wsHttpBinding to basicHttpBinding. The modification to that portion of the web.config has been included below, and the service endpoint has been updated to refer to that binding.

Web Service - Web Config (Revised)

<basicHttpBinding> <binding name="basicBindingConfig"> <security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" proxyCredentialType="Windows" realm="" /> </security> </binding></basicHttpBinding>

Client App - App Config (Revised)

<!-- ... --><security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows" proxyCredentialType="Windows" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /></security><!-- ... -->

Error (Revised)

The current error looks like it contains a Kerberos authentication header.

The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate SOMEHUGESCARYKEYHERE

推荐答案

For me the current setup does work:

On the Server:

<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>

Set the following attribute on all methods for the WCF:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]

On the Client:

<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

其他推荐答案

Something that I notice: the client and server config don't seem to agree on security mode.

In the original section, you have <security>..... in the web.config (omitted the mode="message"), and <security mode="Message"> on the client side.

After your edit, it seems that the client side is unchanged, but the server (web.config) now contains <security mode="TransportCredentialOnly">.

The question really is: can you guarantee that there's only ever going to be one network leg between the client and the server being called? I.e. is this behind a corporate firewall? In that case, I would recommend netTcp binding with <security mode="Transport"> on both ends.

If that's not the case, then you're ok with either wsHttpBinding (which supports more security and reliability features, but is slower and "heavier") or basicHttpBinding. In that case, you would have to use <security mode="Message"> on both ends, and authenticate the service with a certificate (so that the service and client have a common "secret" which to use for encryption).

I would try to leave out the impersonation parts out for the beginning and just get the basic communication and mutual authentication between service and client up and running first - once that's in place, you can start adding the impersonation bits to it, and you can always fall back on a known configuration which works.

David Sackstein has a great series of blog posts explaining the five security scenarios that industry guru Juval Lowy has identified (in his Programming WCF book - the WCF Bible) as the most common and most useful - in order to limit the number of possible combinations of parameters you might want to tweak. One of them is a "Internet" scenario which would probably apply here, if your service is outward facing.

Marc

其他推荐答案

You need to specify a behaviorConfiguration in your client config. SVCUtil does not auto generate. This resolved my issue and I am now successfully using Kerberos. It was a mission though!

<client> <endpoint address="..." binding="customBinding" bindingConfiguration="..." contract="..." name="..." behaviorConfiguration="ImpersonationBehavior" /> </client> <behaviors> <endpointBehaviors> <behavior name="ImpersonationBehavior"> <clientCredentials> <windows allowedImpersonationLevel="Impersonation"/> </clientCredentials> </behavior> </endpointBehaviors> </behaviors> 
WCF和Kerberos身份验证 - IT宝库 (2024)

References

Top Articles
Latest Posts
Article information

Author: Jerrold Considine

Last Updated:

Views: 5981

Rating: 4.8 / 5 (78 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Jerrold Considine

Birthday: 1993-11-03

Address: Suite 447 3463 Marybelle Circles, New Marlin, AL 20765

Phone: +5816749283868

Job: Sales Executive

Hobby: Air sports, Sand art, Electronics, LARPing, Baseball, Book restoration, Puzzles

Introduction: My name is Jerrold Considine, I am a combative, cheerful, encouraging, happy, enthusiastic, funny, kind person who loves writing and wants to share my knowledge and understanding with you.