摘要 : 最近遇到了一个奇怪的 WCF 安全配置问题, WCF Service 上面配置了Windows Authentication. IIS上也启用了 Windows Authentication, 但是仍然出现IIS没有启用Windows Authentication的问题. 在网络上能查到的资料很少. 通过自己的troubleshooting发现所遇到的错误提示比较具有迷惑性. 所以POST上来给大家分享一下.

问题 :

最近遇到了一个奇怪的 WCF 安全配置问题, WCF Service 上面配置了Windows Authentication. IIS上也启用了 Windows Authentication, 但是仍然出现IIS没有启用Windows Authentication的问题.  然而在启动这个WCF Service的时候遇到了如下的错误.

Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.NotSupportedException: Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service. Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below. Stack Trace: [NotSupportedException: Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service.]
System.ServiceModel.Channels.HttpChannelListener.ApplyHostedContext(VirtualPathExtension virtualPathExtension, Boolean isMetadataListener) +15710645
System.ServiceModel.Channels.HttpsChannelListener.ApplyHostedContext(VirtualPathExtension virtualPathExtension, Boolean isMetadataListener) +27
System.ServiceModel.Channels.HttpsTransportBindingElement.BuildChannelListener(BindingContext context) +105
System.ServiceModel.Channels.BindingContext.BuildInnerChannelListener() +95
System.ServiceModel.Channels.MessageEncodingBindingElement.InternalBuildChannelListener(BindingContext context) +102
System.ServiceModel.Channels.TextMessageEncodingBindingElement.BuildChannelListener(BindingContext context) +70
System.ServiceModel.Channels.BindingContext.BuildInnerChannelListener() +95
System.ServiceModel.Channels.Binding.BuildChannelListener(Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, BindingParameterCollection parameters) +166
System.ServiceModel.Description.DispatcherBuilder.MaybeCreateListener(Boolean actuallyCreate, Type[] supportedChannels, Binding binding, BindingParameterCollection parameters, Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, ServiceThrottle throttle, IChannelListener& result, Boolean supportContextSession) +399
System.ServiceModel.Description.DispatcherBuilder.BuildChannelListener(StuffPerListenUriInfo stuff, ServiceHostBase serviceHost, Uri listenUri, ListenUriMode listenUriMode, Boolean supportContextSession, IChannelListener& result) +499
System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost) +1937
System.ServiceModel.ServiceHostBase.InitializeRuntime() +61
System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +63
System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +563
System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +135
System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +654 [ServiceActivationException: The service '/WinAuthService.svc' cannot be activated due to an exception during compilation. The exception message is: Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service..]
System.ServiceModel.AsyncResult.End(IAsyncResult result) +15786048
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +15706393
System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, Boolean flowContext) +265
System.ServiceModel.Activation.HttpModule.ProcessRequest(Object sender, EventArgs e) +227
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +171

下面是这个WCF Service的配置. 按照这个配置, 是需要在IIS上启用Windows Authentication.

<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="myBasicBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="WCFSample.WinAuthService">
<endpoint address="WinAuthService.svc" binding="basicHttpBinding"
bindingConfiguration="myBasicBinding" contract="WCFSample.IWinAuthService" />
</service>
</services>
</system.serviceModel>

在IIS的管理界面上, 已经按照启用了Windows Authentication并且禁用了Anonymous Authentication.

分析 :

报错信息的最顶上一条已经提示了抛出这个异常的CALL STACK 是 System.ServiceModel.Channels.HttpChannelListener.ApplyHostedContext. 因为是托管代码, 所以用工具ILSPY来检查这段代码看什么情况下会抛出这样的错误. 从代码上看, 这个异常是在做了一定逻辑的校验之后, 主动抛出来.

internal override void ApplyHostedContext(VirtualPathExtension virtualPathExtension, bool isMetadataListener)
{
ServiceNameCollection customServiceNames;
base.ApplyHostedContext(virtualPathExtension, isMetadataListener);
AuthenticationSchemes authenticationSchemes = HostedTransportConfigurationManager.MetabaseSettings.GetAuthenticationSchemes(base.HostedVirtualPath);
if (this.AuthenticationScheme == AuthenticationSchemes.Anonymous && (authenticationSchemes & AuthenticationSchemes.Anonymous) == AuthenticationSchemes.None && isMetadataListener)
{
if ((authenticationSchemes & AuthenticationSchemes.Negotiate) == AuthenticationSchemes.None)
{
this.authenticationScheme = authenticationSchemes;
}
else
{
this.authenticationScheme = AuthenticationSchemes.Negotiate;
}
}
if ((authenticationSchemes & this.AuthenticationScheme) == AuthenticationSchemes.None)
{
if (!AuthenticationSchemesHelper.IsWindowsAuth(this.AuthenticationScheme))
{
ExceptionUtility exceptionUtility = DiagnosticUtility.ExceptionUtility;
object[] str = new object[] { this.AuthenticationScheme.ToString() };
throw exceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString("Hosting_AuthSchemesRequireOtherAuth", str)));
}
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString("Hosting_AuthSchemesRequireWindowsAuth")));
}
if (this.AuthenticationScheme != AuthenticationSchemes.Anonymous)
{
ExtendedProtectionPolicy extendedProtectionPolicy = HostedTransportConfigurationManager.MetabaseSettings.GetExtendedProtectionPolicy(base.HostedVirtualPath);
if (extendedProtectionPolicy == null)
{
if (this.extendedProtectionPolicy.PolicyEnforcement == PolicyEnforcement.Always)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString("ExtendedProtectionNotSupported")));
}
}
else if (!isMetadataListener || !ChannelBindingUtility.IsDefaultPolicy(this.extendedProtectionPolicy))
{
ChannelBindingUtility.ValidatePolicies(extendedProtectionPolicy, this.extendedProtectionPolicy, true);
if (this.usingDefaultSpnList)
{
customServiceNames = null;
}
else
{
customServiceNames = this.extendedProtectionPolicy.CustomServiceNames;
}
if (!ChannelBindingUtility.IsSubset(extendedProtectionPolicy.CustomServiceNames, customServiceNames))
{
object[] objArray = new object[] { SR.GetString("Hosting_ExtendedProtectionSPNListNotSubset") };
string str1 = SR.GetString("Hosting_ExtendedProtectionPoliciesMustMatch2", objArray);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(str1));
}
}
else
{
this.extendedProtectionPolicy = extendedProtectionPolicy;
}
}
if (!ServiceHostingEnvironment.IsSimpleApplicationHost)
{
this.realm = HostedTransportConfigurationManager.MetabaseSettings.GetRealm(virtualPathExtension.VirtualPath);
}
}

不过由于不是我们确切看到的错误. 所以需要在DLL的Resources中确切的验证一下. 在这里明确

Hosting_AuthSchemesRequireWindowsAuth=Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service.

往上判断, 能够进入到 if ((authenticationSchemes & this.AuthenticationScheme) == AuthenticationSchemes.None) . AuthenticationSchemes是一个枚举类型. 在这里注意到了有两个分开的定义, NegotiateNtlm. 在 IIS Windows Authentication 可以配置多个Provider. 默认情况下有2个, 分别是NegotiateNTLM.

namespace System.Net
{
/// <summary>Specifies protocols for authentication.</summary>
[Flags]
public enum AuthenticationSchemes
{
/// <summary>No authentication is allowed. A client requesting an <see cref="T:System.Net.HttpListener" /> object with this flag set will always receive a 403 Forbidden status. Use this flag when a resource should never be served to a client.</summary>
None = ,
/// <summary>Specifies digest authentication.</summary>
Digest = ,
/// <summary>Negotiates with the client to determine the authentication scheme. If both client and server support Kerberos, it is used; otherwise, NTLM is used.</summary>
Negotiate = ,
/// <summary>Specifies NTLM authentication.</summary>
Ntlm = ,
/// <summary>Specifies Windows authentication.</summary>
IntegratedWindowsAuthentication = ,
/// <summary>Specifies basic authentication. </summary>
Basic = ,
/// <summary>Specifies anonymous authentication.</summary>
Anonymous =
}
}

在得到这些线索之后, 检查了Windows Authentication的Providers. 果然只有一个NTLM. 添加了一个新的Negotiate 的 Provider之后, WCF Service就得到了解决.

结论 :

这篇文章中仅讨论其中一种可能造成这样问题的情况. 这里我遇到的问题与Windows Authentication的Provider有关系.

当 WCF Service 上启用了Transport 层面上的安全设定之后, 可以配置某一种类型的ClientCredentialType. 其中可以包括 None, Basic, Digest, Ntlm, Windows, Certificate 和 Password.

当指定为Windows的时候, 实质是要求Kerboer或者NTLM两者皆可. Server先去尝试Kerberos验证, 如果Kerberos验证失败, 则会尝试通过NTLM. 也可以通过设置另外的属性 AllowNtlm为false来强制使用Kerberos. Kerberos和Ntlm是两种不同的验证方式.

由于这一点的不同, 在IIS上要确保做出相应的配置. 即, 开启IIS的Windows Authentication的同时, 要确保Negotiate Provider也在列表中. 只有Ntlm会被认为是错误的配置.

可以参考这里的链接 :

Sonic Guo

WCF : 修复 Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service 问题的更多相关文章

  1. [Windows Azure] Create and use a reporting service in Windows Azure SQL Reporting

    Create and use a reporting service in Windows Azure SQL Reporting In this tutorial you will learn ab ...

  2. 客户端通过wcf来启动或者停止服务器上的windows service

    1.设置服务器上的windows service的security,下面的命令只能用cmd.exe来运行(以管理员模式) sc sdset "LISA_43_Dev_Batch" ...

  3. Windows 7下安装MySQL Server卡在Apply Security Settings的解决方案(转)

    如果操作无效,请卸载MySQL Server后换一个位置安装 例如默认的是C:\Program Files\MySQL 安装时选Custom修改到D:\Program Files\MySQL试试 == ...

  4. 重温WCF之构建一个简单的WCF(一)(2)通过Windows Service寄宿服务和WCF中实现操作重载

    参考地址:http://www.cnblogs.com/zhili/p/4039111.html 一.如何在Windows Services中寄宿WCF服务 第一步:创建Windows 服务项目,具体 ...

  5. MySQL安装最后一步apply security settings错误

    网上查了很久都是说删除各种文件什么的,直接百度apply security settings,说是mysql没卸载干净.不是的. 看日志发现 You must SET PASSWORD before ...

  6. MySQL安装问题:Unable to update security settings解决方案

    主要问题还是之前装过,卸载的时候卸载不干净导致的. 如下: 安装到最后出现: Unable to update security settings. Access denied for user 'r ...

  7. the security settings could not be applied to the database(mysql安装error)【简记】

    在安装mysql时,出现“The security settings could not be applied to the database because the connection has f ...

  8. How to resolve "your security settings have blocked an untrusted application from running" in Mac

    If you encounter the error "your security settings have blocked an untrusted application from r ...

  9. Mysql安装过程中出现apply security settings错误的解决方法

    在学习Mysql的过程中,首先要安装Mysql.然而在第一遍安装过程中难免会出现安装错误的时候,当卸载后第二次安装(或者第三次甚至更多次)的时候,往往在安装最后一步会出现apply security ...

随机推荐

  1. Jade模板引擎让你飞

    写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...

  2. .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整(续)-使用配置文件动态注入

    上次实现了依赖注入,但是web项目必须要引用业务逻辑层和数据存储层的实现,项目解耦并不完全:另一方面,要同时注入业务逻辑层和数据访问层,注入的服务直接写在Startup中显得非常臃肿.理想的方式是,w ...

  3. spring boot 部署为jar

    前言 一直在ide中敲代码,使用命令行mvn spring-boot:run或者gradlew bootRun来运行spring boot项目.想来放到prod上面也应该很简单.然而今天试了下,各种问 ...

  4. FullCalendar日历插件说明文档

    FullCalendar提供了丰富的属性设置和方法调用,开发者可以根据FullCalendar提供的API快速完成一个日历日程的开发,本文将FullCalendar的常用属性和方法.回调函数等整理成中 ...

  5. IteratorPattern(迭代子模式)

    /** * 迭代子模式 * @author TMAC-J * 聚合:某一类对象的集合 * 迭代:行为方式,用来处理聚合 * 是一种行为模式,用于将聚合本身和操作聚合的行为分离 * Java中的COLL ...

  6. Extjs 让combobox写起来更简单

    也已经写了很久时间的extjs ,每次都用到很多的combobox,配置很多东西觉得实在是太麻烦,所以根据常用到的情况写了一个简便的combobox,再次记录下来,以免放在某个地方忘记了找不到了. 定 ...

  7. listview下拉刷新和上拉加载更多的多种实现方案

    listview经常结合下来刷新和上拉加载更多使用,本文总结了三种常用到的方案分别作出说明. 方案一:添加头布局和脚布局        android系统为listview提供了addfootview ...

  8. Kafka1 利用虚拟机搭建自己的Kafka集群

    前言:       上周末自己学习了一下Kafka,参考网上的文章,学习过程中还是比较顺利的,遇到的一些问题最终也都解决了,现在将学习的过程记录与此,供以后自己查阅,如果能帮助到其他人,自然是更好的. ...

  9. [翻译]Orchard如何工作

    Orchard一直是博主心中神一般的存在,由于水平比较菜,Orchard代码又比较复杂看了几次都不了了之了.这次下定决心要搞懂其工作原理,争取可以在自己的项目中有所应用.为了入门先到官网去学习一下相关 ...

  10. 在 Linux 中使用 Eclipse 和 Gnu Autotools 管理 C/C++ 项目

    在我该系列的之前的所有随笔中,都是采用 Linux 发行版自带的包管理工具(如 apt-get.yum 等)进行软件的安装和卸载,从来没有向大家展示使用源代码自行编译安装软件的方法.但是长期混迹于 U ...