【问题标题】:WCF Service for Java Client Using Service Certificate and Self Signed Client Certificate Supplied by Client Developer使用客户端开发人员提供的服务证书和自签名客户端证书的 Java 客户端 WCF 服务
【发布时间】:2012-10-23 21:14:30
【问题描述】:

我正在开发一个基于供应商实现的 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"/>

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

【问题讨论】:

  • 我猜您只需要在 IIS 服务器上的受信任存储中安装客户端证书即可。由于它是自签名证书,您可能会遇到 IIS 抛出的异常,它无法验证证书。您可以在不验证客户端证书的链信任的 serviceBehaviour 中尝试以下设置:
  • @Rajesh 谢谢你的回复。我尝试使用安全模式 = 传输和传输 clientCredentialType = 证书设置并收到以下错误:“HTTP 请求被客户端身份验证方案‘匿名’禁止。”这是我在没有您建议的设置更改的情况下使用该设置收到的错误。我可能有一个解决方案。供应商可能给我发错了证书。我正在使用“正确”证书进行测试,看看它是否有效。
  • @Rajesh 我在使用正确的证书时遇到了同样的错误。有关完整信息,请参阅我的更新。
  • @user1769388 我看不到您在 web.config 中添加自定义验证的位置(您在顶部提到了这一点)。 Check out MSDN on custom cert validation
  • @user1769388 此外,私钥不存在错误可能表明“算法套件”的选择存在问题。尝试在两侧专门设置它,某些证书不支持所有不同的套件。我必须先将我的设置为 DES,然后从那里向上移动。测试这一点的一个好方法是在证书上设置一个 pin(或密码),它应该在访问签名时(通过客户端)提示您,如果没有,则该证书不支持您的签名算法。跨度>

标签: c# wcf ssl authentication java-client


【解决方案1】:

在我们的 cmets 进行了长时间的讨论后,我会为您指出文章Nine simple steps to X.509 certificates in WCF。我知道这只是一个链接,但这是一篇很长的文章。

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

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

然后,您需要将这些用户映射到 Windows/LDAP 帐户以便于管理和访问控制,或者您需要实施 custom validator(可能还有 IIdentity、principal 和 service 凭据)以便验证私有证书并“登录”用户。

我希望这对您有所帮助。 Here is one more on x509 custom auth and val

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

【讨论】:

  • 我在尝试设置时很早就发现了您的第一个链接。问题是,他正在创建服务、客户端和两个证书。我正在根据从我们的贸易伙伴那里收到的 WSDL 开发服务,以便他们可以从他们的 Java 客户端使用它。他们不支持我创建客户端证书供他们使用的场景。他们只支持在验证我们的服务器证书后给我一个他们的证书来验证传入的请求。
  • 你的第三段基本上是正确的,除了他们只有一个网络应用程序的客户,通过他们的公司证书。考虑到这一点,有没有办法使用我们的服务器证书设置 SSL,然后使用他们的证书进行身份验证?正如我在更新中所说,我认为我可能不得不使用传输安全性来实现互操作性。如果我们将证书安装在我们的商店中,是否无法让 IIS 验证其证书?
  • 将 IIS 更改为忽略但离开我的服务会给我服务“SslRequireCert”的 SSL 设置与 IIS“Ssl”的设置不匹配。 IIS 没有通过它,但我正在尝试设置 IIS 以进行身份​​验证,因为我最近验证他们希望在握手期间进行身份验证,而不是实际通过请求传递证书。我想我也意识到(我应该早点意识到)我无法用他们的证书正确测试这个,因为它没有他们的私钥并且握手会失败。
  • 感谢您的所有帮助。我们的服务器管理员认为此服务不需要这样做。
猜你喜欢
  • 2020-10-23
  • 1970-01-01
  • 2011-06-11
  • 1970-01-01
  • 2013-07-14
  • 2015-01-04
  • 1970-01-01
  • 1970-01-01
  • 2011-09-28
相关资源
最近更新 更多