WCF : 修复 Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service 问题
2015-02-10 21:55
951 查看
摘要 : 最近遇到了一个奇怪的 WCF 安全配置问题, WCF Service 上面配置了Windows Authentication. IIS上也启用了 Windows Authentication, 但是仍然出现IIS没有启用Windows Authentication的问题. 在网络上能查到的资料很少. 通过自己的troubleshooting发现所遇到的错误提示比较具有迷惑性. 所以POST上来给大家分享一下.
下面是这个WCF Service的配置. 按照这个配置, 是需要在IIS上启用Windows Authentication.
在IIS的管理界面上, 已经按照启用了Windows Authentication并且禁用了Anonymous Authentication.
不过由于不是我们确切看到的错误. 所以需要在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是一个枚举类型. 在这里注意到了有两个分开的定义, Negotiate和Ntlm. 在 IIS Windows Authentication 可以配置多个Provider. 默认情况下有2个, 分别是Negotiate 和 NTLM.
在得到这些线索之后, 检查了Windows Authentication的Providers. 果然只有一个NTLM. 添加了一个新的Negotiate 的 Provider之后, WCF Service就得到了解决.
当 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会被认为是错误的配置.
可以参考这里的链接 :
https://msdn.microsoft.com/library/ms733836%28v=vs.110%29.aspx
http://blogs.msdn.com/b/benjaminperkins/archive/2011/09/14/iis-integrated-windows-authentication-with-negotiate.aspx
Sonic Guo
问题 :
最近遇到了一个奇怪的 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是一个枚举类型. 在这里注意到了有两个分开的定义, Negotiate和Ntlm. 在 IIS Windows Authentication 可以配置多个Provider. 默认情况下有2个, 分别是Negotiate 和 NTLM.
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 = 0, /// <summary>Specifies digest authentication.</summary> Digest = 1, /// <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 = 2, /// <summary>Specifies NTLM authentication.</summary> Ntlm = 4, /// <summary>Specifies Windows authentication.</summary> IntegratedWindowsAuthentication = 6, /// <summary>Specifies basic authentication. </summary> Basic = 8, /// <summary>Specifies anonymous authentication.</summary> Anonymous = 32768 } }
在得到这些线索之后, 检查了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会被认为是错误的配置.
可以参考这里的链接 :
https://msdn.microsoft.com/library/ms733836%28v=vs.110%29.aspx
http://blogs.msdn.com/b/benjaminperkins/archive/2011/09/14/iis-integrated-windows-authentication-with-negotiate.aspx
Sonic Guo
相关文章推荐
- The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the ser
- BEA-290074 <Deployment service servlet received file download request for file "security/SerializedSystemIni.dat". The file may exist, but download of this file is not allowed.>
- A ship is always safe at the shore - but that is not what it is built for.
- ArcGIS Engine中初始化许可常见问题归纳,the application is not licensed to create or modify schema for this type of data
- WCF:The caller was not authenticated by the service. ---> System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
- The error indicates that IIS is in 64 bit mode, while this application is a 32 bit application and thus not compatible
- It is not possible to run two different versions of ASP.NET in the same IIS process.问题的解决
- the selected server is enabled,but is not configured properly.Deployment to it will not be permitted
- "this class is not key value coding-compliant for the key ..."问题的解决
- The PDO extension is required for this adapter but the extension is not loaded 错误解决方案
- Service Broker message delivery is not enabled in this database. Use the ALTER DATABASE statement to
- "this class is not key value coding-compliant for the key ..."问题的解决(转)
- The PDO extension is required for this adapter but the extension is not loaded解决方案:
- ASP.Net DebugError解决方案[转]:Unable to start debugging on the web server.Debugging failes because integrated Windows authentication is not enabled.
- A file with the correct name was found in this directory, but it is not the correct one.
- 解决php的It is not safe to rely on the system’s timezone settings的问题
- php5.3的It is not safe to rely on the system’s timezone settings的问题的解决方案
- IE 去掉提示信息" This page is accessing information that is not under its control. This poses a security risk.”
- com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException: This application is out of date, please click the refresh but
- Zend:The PDO extension is required for this adapter but not loaded