【问题标题】:SecurityNegotiationException in WCF Service Hosted on IIS 6.0IIS 6.0 上托管的 WCF 服务中的 SecurityNegotiationException
【发布时间】:2011-01-10 06:34:20
【问题描述】:

我在 IIS 上托管了 WCF 服务。配置文件如下。

<?xml version="1.0"?>
<!--
    Note: As an alternative to hand editing this file you can use the
    web admin tool to configure settings for your application. Use
    the Website->Asp.Net Configuration option in Visual Studio.
    A full list of settings and comments can be found in
    machine.config.comments usually located in
    \Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration>


    <configSections>
      <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
        <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
          <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
          <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" />
            <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
            <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
            <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
          </sectionGroup>
        </sectionGroup>
      </sectionGroup>
    </configSections>


    <appSettings/>
    <connectionStrings/>

    <system.web>
        <!--
            Set compilation debug="true" to insert debugging
            symbols into the compiled page. Because this
            affects performance, set this value to true only
            during development.
        -->
        <compilation debug="false">

          <assemblies>
            <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
            <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
          </assemblies>

        </compilation>
        <!--
            The <authentication> section enables configuration
            of the security authentication mode used by
            ASP.NET to identify an incoming user.
        -->
        <authentication mode="Windows" />
        <!--
            The <customErrors> section enables configuration
            of what to do if/when an unhandled error occurs
            during the execution of a request. Specifically,
            it enables developers to configure html error pages
            to be displayed in place of a error stack trace.

        <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
            <error statusCode="403" redirect="NoAccess.htm" />
            <error statusCode="404" redirect="FileNotFound.htm" />
        </customErrors>
        -->


      <pages>
        <controls>
          <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </controls>
      </pages>

      <httpHandlers>
        <remove verb="*" path="*.asmx"/>
        <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
      </httpHandlers>
      <httpModules>
        <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </httpModules>


    </system.web>

    <system.codedom>
      <compilers>
        <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"
                  type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <providerOption name="CompilerVersion" value="v3.5"/>
          <providerOption name="WarnAsError" value="false"/>
        </compiler>
      </compilers>
    </system.codedom>

    <system.web.extensions>
      <scripting>
        <webServices>
          <!--
              Uncomment this section to enable the authentication service. Include
              requireSSL="true" if appropriate.

          <authenticationService enabled="true" requireSSL = "true|false"/>
          -->
          <!--
              Uncomment these lines to enable the profile service, and to choose the
              profile properties that can be retrieved and modified in ASP.NET AJAX
              applications.

          <profileService enabled="true"
                          readAccessProperties="propertyname1,propertyname2"
                          writeAccessProperties="propertyname1,propertyname2" />
          -->
          <!--
              Uncomment this section to enable the role service.

          <roleService enabled="true"/>
          -->
        </webServices>
        <!--
        <scriptResourceHandler enableCompression="true" enableCaching="true" />
        -->
      </scripting>
    </system.web.extensions>
    <!--
        The system.webServer section is required for running ASP.NET AJAX under Internet
        Information Services 7.0.  It is not necessary for previous version of IIS.
    -->
    <system.webServer>
      <validation validateIntegratedModeConfiguration="false"/>
      <modules>
        <add name="ScriptModule" preCondition="integratedMode" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </modules>
      <handlers>
        <remove name="WebServiceHandlerFactory-Integrated"/>
        <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode"
             type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode"
             type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </handlers>
    </system.webServer>


  <system.serviceModel>
    <services>
      <service name="IISTest2.Service1" behaviorConfiguration="IISTest2.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="" binding="wsHttpBinding" contract="IISTest2.IService1">
          <!--
              Upon deployment, the following identity element should be removed or replaced to reflect the
              identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="IISTest2.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

客户端配置文件如下

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IService1" 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>
        <client>
            <endpoint address="http://yyy.zzz.xxx.net/IISTest2/Service1.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
                contract="ServTest.IService1" name="WSHttpBinding_IService1">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

当我尝试从客户端应用程序访问服务时,我得到了

SecurityNegotiationException

细节是

无法打开安全通道 因为与安全协商 远程端点失败。这可能 由于缺席或不正确 中指定的 EndpointIdentity EndpointAddress 用于创建 渠道。请验证 指定或暗示的 EndpointIdentity 通过 EndpointAddress 正确 标识远程端点。

如果我将服务托管在 ASP.NET 开发服务器上,它运行良好,但如果我托管在 IIS 上,则会出现上述错误。

【问题讨论】:

  • 您的 IIS 是否与客户端安装在同一台机器上?
  • @Ladislav Mrnka :它安装在同一台机器上。我也尝试将服务托管在另一个 IIS 上,结果是一样的。 :(。
  • 你的用户权限是什么?是管理员吗?你在目录安全选项卡->认证方式中设置了什么用户?

标签: c# .net asp.net wcf web-config


【解决方案1】:

我认为您应该从客户端和服务器配置中删除 &lt;identity&gt; 节点。这可能已经使它起作用了。如果这还不起作用,我会将wsHttpBinding 从客户端复制到服务器配置。可能仍然缺少某些东西,但您应该更近一些。

但是还有另一个问题:我认为您应该清楚自己想要什么样的安全性。您有很多不同的设置(例如,您配置了安全模式Transport,但您也有Message 安全设置。我认为this 帮助我为WCF 设置Kerberos。一切都在代码中完成,但是您可以轻松猜出配置的样子。

【讨论】:

    【解决方案2】:

    我注意到您的客户端代码中的 clientCredentialType 设置为“windows”。这使用了内置的 Windows 身份验证,因此运行客户端的用户可能在服务主机上没有适当的权限。

    话虽如此,我不确定它应该是什么,但它可能是一条值得探索的道路。

    【讨论】:

      【解决方案3】:

      创建一个新的测试应用程序并向 IIS 上托管的服务添加服务引用。 完成后,检查客户端 app.config 中的安全配置。然后只需找出与原始客户端应用程序的差异即可。

      通常,当客户端和服务器之间的安全配置不同时会引发此异常,WCF 无法找到满足双方的通用安全策略集。

      【讨论】:

      • 您指的是新的控制台应用程序吗?当前的客户端应用程序是我创建的仅用于测试此服务的 winform 应用程序。
      【解决方案4】:

      如果您的 IIS 是 Active Directory 域的成员,则它必须具有有效的服务主体名称 (SPN)(请参阅:Setspn on Technet

      您还必须更改客户端端点配置以指定预期的 SPN。

      尝试对您的 IIS 托管服务 运行 svcutil 以生成新的客户端配置文件。

      例如:svcutil.exe @987654322@

      然后找到生成的端点的&lt;identity&gt; 部分。它应该包含一个&lt;servicePrincipalName&gt; 节点。现在用这个配置文件试试你的客户端。

      【讨论】:

        【解决方案5】:

        【讨论】:

        • 我浏览了这篇文章,但没有得到我真正需要做的事情:(。
        • @Ram: 你的 iis 版本是多少?
        • 在 IIS 中托管服务后,从浏览器调用服务时是否遇到任何错误?
        • 不,我没有收到任何错误。我从浏览器浏览服务。
        【解决方案6】:

        绑定部分是在客户端上定义的,而不是在服务器上。

        客户端上定义的内容与服务器上使用的默认值之间的差异可能会导致问题。

        这可能是部分信任问题。 WCF 中的安全性需要完全信任才能获得全部功能。如果没有这个,它只支持功能的子集,请参阅 Partial Trust Feature Compatibility

        【讨论】:

          猜你喜欢
          • 2011-05-11
          • 1970-01-01
          • 1970-01-01
          • 2022-12-13
          • 1970-01-01
          • 1970-01-01
          • 2012-07-06
          • 1970-01-01
          相关资源
          最近更新 更多