使用客户端证书的 WCF 服务需要在 IIS 中进行匿名访问,因此实际上不起作用?

标签 wcf iis-7.5 wcf-security wcf-client

我有一个托管在 IIS(Windows Server 2008 R2 上的 7.5)中的 WCF 服务(.NET 4)。我们的客户(我们正在为其构建服务)要求使用威瑞信的证书对服务的所有客户端进行身份验证。也就是说,客户从 Verisign 购买证书并向我们提供公钥。该服务应该只接受可以使用我们从客户端收到的公钥之一进行验证的请求。

我遇到的问题是 IIS 似乎要求启用匿名身份验证。如果不是,则“此服务的安全设置需要‘匿名’身份验证,但托管此服务的 IIS 应用程序未启用它。”引发错误。但是,如果我启用匿名身份验证,对提供​​ 的服务的任何调用任意 证书是允许的。我们需要将其限制为仅允许提供特定证书的调用(即我们已为其提供公钥的调用)。

在 IIS 中,我们需要 SSL 和客户端证书(在 SSL 设置下),并且(在身份验证下)禁用所有身份验证(匿名除外)。

web.config 是:

  <system.web>
    <compilation debug="false" targetFramework="4.0" />
    <authentication mode="Windows" />
    <authorization>
      <deny users="?" />
      <allow users="*" />
    </authorization>
    <customErrors mode="Off" />
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID" />
    <identity impersonate="false" />
  </system.web>

  <system.serviceModel>
    <services>
      <service behaviorConfiguration="XXXServiceBehavior" name="XXXService.NewService">
        <endpoint address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="XXXServiceBinding"
                  contract="XXXService.INewService"
                  bindingNamespace="http://XXXX.com.au/XXXService/NewService">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="XXXXServiceBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="PeerTrust" mapClientCertificateToWindowsAccount="true" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="XXXServiceBinding" maxReceivedMessageSize="1000000" maxBufferPoolSize="1000000">
          <readerQuotas maxStringContentLength="1000000" />
          <security mode="Transport">
            <transport clientCredentialType="Certificate" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

如果有人能够使这种情况正常工作,请告诉我您在 IIS 和配置中使用了哪些设置?

最佳答案

原来我需要的是使用绑定(bind)安全模式TransportWithMessageCredential , 和 message clientCredentialTypeCertificate (请参阅下面的完整配置列表)。

使用此绑定(bind)配置,我不需要要求主体权限或证书到 Windows 帐户的任何映射,因为如果调用者未提供可识别的证书(即已导入其公钥的证书),则服务将不会执行在机器级别的服务器上的“受信任的人”存储中)。

唯一的其他设置更改是在 IIS 和 SSL 设置中。我不得不将“客户端证书”设置从“要求”更改为“接受”。 (将其保留为“要求”会导致客户端收到“客户端身份验证方案'匿名'的 HTTP 请求被禁止”错误。)我不知道为什么会这样,但我不这么认为是一个问题,因为 WCF 将需要证书。

所以这里是相关的配置。这是服务器配置:

<system.web>
  <compilation debug="false" targetFramework="4.0" />
  <authentication mode="Windows" />
  <authorization>
    <deny users="?" />
    <allow users="*" />
  </authorization>
  <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID" />
  <identity impersonate="false" />
</system.web>

<system.serviceModel>
  <services>
    <service behaviorConfiguration="XXXWebServiceBehavior" name="XXXWebService.NewService">
      <endpoint address="" binding="wsHttpBinding" bindingConfiguration="XXXWebServiceBinding" contract="XXXWebService.INewService" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="XXXWebServiceBehavior">
        <serviceDebug includeExceptionDetailInFaults="false" />
        <serviceCredentials>
          <clientCertificate>
            <authentication certificateValidationMode="PeerTrust" />
          </clientCertificate>
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <wsHttpBinding>
      <binding name="XXXWebServiceBinding" maxReceivedMessageSize="1000000" maxBufferPoolSize="1000000">
        <readerQuotas maxStringContentLength="1000000" />
        <security mode="TransportWithMessageCredential">
          <message clientCredentialType="Certificate" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
</system.serviceModel>

这是客户端配置(主要由 Visual Studio 生成):
<system.serviceModel>
  <bindings>
    <wsHttpBinding>
      <binding name="WSHttpBinding_INewService" 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="TransportWithMessageCredential">
          <message clientCredentialType="Certificate" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <client>
    <endpoint address="https://XXXX.XXXX.com.au/XXXServices/NewService.svc"
              binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_INewService"
              contract="ServiceReference1.INewService" name="WSHttpBinding_INewService">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
  </client>
</system.serviceModel>

关于使用客户端证书的 WCF 服务需要在 IIS 中进行匿名访问,因此实际上不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9388469/

相关文章:

c# - 请求被中止 : Could not create SSL/TLS secure channel - IllegalMessage

c# - 如何模拟 WCF 服务?

wcf - 通过 wcf 将 byte[](超过 20 KB)发送到 silverlight

IIS 7.5 虚拟目录托管在第二台服务器上

asp.net - 如何将任何子域请求重定向到asp.net中的主域

c# - IIS 7.5 Fixing 尝试加载格式错误的程序?

c# - 使用 NetTCPBinding 进行回调

c# - WCF 安全认证

WCF 客户端使用证书和用户名/密码凭据?

access-token - 在遗留 .net 4.6.2 项目中使用 IdentityServer4.AccessTokenValidation