3

我正在开发一个基于供应商实现的 WCF 服务,以从他们那里接收数据。我有一个使用单向 SSL 的服务的工作版本,客户端使用我们的服务器证书。由于最近对他们的实现进行了更改,我现在需要使用证书而不是用户名和密码来验证他们的客户端。

他们用 Java 开发,我无法控制客户端或他们生成证书的方式。它们不支持 WSHttpBinding,所以我必须使用 BasicHttpBinding。他们的证书是自签名的,很遗憾在生产中也是如此。我尝试使用 Transport 来保证安全性,根据我们的服务器管理员的说法,他们的证书已正确安装在我们的服务器上(我无权访问我们的 IIS 服务器)。我相信 IIS 存在证书问题,因为它是自签名的,所以我放弃了该实现。

经过大量研究后,我确定只有通过从OperationContext.Current.ServiceSecurityContext.AuthorizationContext.ClaimSets[0]. 这是我的第一个 WCF 服务,所以我相信我已经正确设置了它,但是在从我的 WCF 测试客户端进行测试时出现以下错误:The private key is not present in the X.509 certificate. 当我从他们的客户那里得到供应商测试时,他们得到了An error occurred when verifying security for the message.

我有什么配置不正确吗?是否支持此实现?

服务 Web.Config:

<?xml version="1.0"?>
    <configuration>
        <system.serviceModel>
                 <behaviors>
                <serviceBehaviors>
                    <behavior name="FileReceiverServiceBehavior">
                        <useRequestHeadersForMetadataAddress/>
                        <serviceMetadata httpsGetEnabled="true"/>
                    </behavior>
                </serviceBehaviors>
            </behaviors>
            <bindings>
                <basicHttpBinding>
                    <binding name="FileReceiverServiceBinding">
                        <security mode="TransportWithMessageCredential">
                            <message clientCredentialType="Certificate"/>
                        </security>
                        <readerQuotas maxStringContentLength="2147483647"/>
                    </binding>
                </basicHttpBinding>
            </bindings>
            <services>
                <service behaviorConfiguration="FileReceiverServiceBehavior" name="FileReceiverService.FileReceiverService">
                    <endpoint address="" binding="basicHttpBinding" bindingConfiguration="FileReceiverServiceBinding" contract="FileReceiverServiceSoap" bindingNamespace="http://www.openuri.org/" />
                    <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
                </service>
            </services>
        </system.serviceModel>
    </configuration>

我的 WCF 测试客户端配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="test">
          <clientCredentials>
            <clientCertificate findValue="Users"
                               x509FindType="FindBySubjectName"
                               storeLocation="LocalMachine"
                               storeName="My"/>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_FileReceiverServiceSoap" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="Certificate" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://mydomain.com/vendor/FileReceiverService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_FileReceiverServiceSoap"
        contract="ServiceReference1.FileReceiverServiceSoap" name="BasicHttpBinding_FileReceiverServiceSoap" behaviorConfiguration="test" />
    </client>
  </system.serviceModel>
</configuration>

更新:

供应商向我发送了正确的证书。它是由商业 CA 颁发的有效证书。当我在本地查看证书时,我可以看到到受信任根的链,并且状态显示为“OK”。

如果我使用security mode="Transport"transport clientCredentialType="Certificate"得到:HTTP 请求被客户端身份验证方案“匿名”禁止

如果我使用security mode="TransportWithMessageCredential"message clientCredentialType="Certificate"得到: X.509 证书中不存在私钥。

我想我可能需要严格使用传输,以便它可以与 Java 客户端互操作,所以我专注于“客户端身份验证方案‘匿名’禁止 HTTP 请求”错误。这是 IIS 设置的问题,还是只是在证书到达服务器时无法正确验证证书?证书在受信任的人中,我没有尝试任何客户端,certificateValidationMode但也和. 任何帮助将不胜感激。PeerTrustChainTrustPeerOrChainTrust

更新2:

我专注于让它与我的原始服务器配置的以下更改以及与我的测试客户端的匹配更改一起工作:

<security mode="Transport">
  <transport clientCredentialType="Certificate"/>

我仍然得到:客户端身份验证方案 'Anonymous' 禁止 HTTP 请求我在这里找到了一个解释,基本上可以确认客户端证书无法被服务器验证。我如何让我们的服务器管理员在 IIS 中配置此应用程序并安装证书以使其正常工作?

4

1 回答 1

3

在我们的评论中进行了长时间的讨论之后,我将向您指出文章WCF 中 X.509 证书的九个简单步骤。我知道这只是一个链接,但这是一篇很长的文章。

似乎您的问题实际上是您的客户没有可以对其进行身份验证的证书。在您正在争取的方案中,每个客户端都需要有一个私钥来识别它们,并且服务器/服务需要有相应的公钥来验证签名(至少安装在密钥库中)。

您当前的设置似乎每个客户端都将服务器的公钥作为受信任的服务器。因此,您可以让它们通过 SSL 连接和加密,客户端将信任服务器,但服务器实际上不知道客户端是谁,或者至少无法在没有识别它们的情况下对它们进行身份验证。您之前使用用户名和密码的方式是之前识别它们的方式,但现在使用 x.509 证书,每个拥有用户名-密码组合的人都需要一个带有私钥的唯一证书,以便进行身份验证。

然后,您需要将这些用户映射到 Windows/LDAP 帐户以便于管理和访问控制,或者您需要实施自定义验证器(可能还有 IIdentity、主体和服务凭证)以验证私有证书并“登录”用户。

我希望这对您有所帮助。 这是关于 x509 自定义身份验证和验证的另一个

编辑:响应 Update2,尝试在 SSL 设置下将 IIS 站点/应用程序设置为“IGNORE User Certificates”,并查看是否出现不同的错误,反之亦然。如果您将其设置为需要,但在代码中没有启用ASP 兼容模式,则 IIS 不会通过 IIdentity,除非您在 IIS 中设置了某种身份验证方案,否则它不会为您做任何事情。如果您将此设置为忽略,您可以快速设置自定义验证器并查看证书通过,然后您可以在其上构建链并在其上创建某种授权。

于 2012-10-29T16:24:35.610 回答