1

背景(有点长)

几年前,我为客户编写了一个 WCF 服务,该服务配置为使用 basicHttpBinding,安全模式 = "Transport",clientCredentialType = "Certificate",即客户端使用(客户端)证书对自己进行身份验证。该服务使用自定义 AuthorizationManager 检查传入证书的指纹是否存在于有效证书指纹的预定义列表中。如果传入的证书被认为是有效的,则允许操作继续(如果不是,则抛出异常)。

该服务已经完美运行了大约四年,每个人都很高兴。然而,由于经常发生需求变化,最近开发人员联系了我的客户,希望将他们的应用程序连接到我的客户服务。唯一的问题是这些开发人员正在使用 Java 的一些变体作为他们的首选平台,现在我们面临着一些严重的问题。长话短说,没有人设法让他们的 Java 实现(例如 Metro、Axis2)与当前配置的服务一起工作。

上周,我们尝试通过将绑定更改为安全模式 =“TransportWithMessageCredential”和 Message clientCeredentialType =“UserName”的 wsHttpBinding 来使其与用 Java(Metro、JAX-WS)编写的客户端一起工作。我还在配置文件中的服务凭证元素中添加了一个自定义 UserNamePassWordValidatorType。

然后我注释掉了自定义 AuthorizationManager,因为没有来自客户端的证书。

瞧,这一次我们让 SoapUI 和 Java 客户端都可以与服务对话。

(顺便说一句,我们的服务在 Windows 服务中自托管)

很高兴,我们决定使用两个绑定配置服务,现有的基本HttpBinding 已经运行了很长时间而没有出现故障,以及新测试的 wsHttpBinding。所以我们会有类似的东西:

<services>
    <service name="SuperDuperService" behaviorConfiguration="superDuperBehaviour">
        <endpoint binding="basicHttpBinding" contract="ISuperDuperService" bindingConfiguration="SecureTransport"/>
        <endpoint binding="wsHttpBinding" address="stws" contract="ISuperDuperService" bindingConfiguration="SecureTransportAndSoap"/>
        <endpoint binding="mexHttpsBinding" address="mex" contract="IMetadataExchange" />
        <host>
            <baseAddresses>
                <add baseAddress="https://<url + port>/SuperDuperService"/>
            </baseAddresses>
        </host>
    </service>
</services>
<bindings>
    <basicHttpBinding>
        <binding name="SecureTransport" maxBufferSize="2065536" maxBufferPoolSize="524288" maxReceivedMessageSize="2065536">
            <security mode="Transport">
                <transport clientCredentialType="Certificate"/>
            </security>
            <readerQuotas maxDepth="32" maxStringContentLength="6553600" maxArrayLength="2065536"
                maxBytesPerRead="4096" maxNameTableCharCount="16384" />
        </binding>
    </basicHttpBinding>
    <wsHttpBinding>
        <binding name="SecureTransportAndSoap">
            <security mode="TransportWithMessageCredential">
                <message clientCredentialType="UserName"/>
            </security>
        </binding>
    </wsHttpBinding>
</bindings>
<behaviors>
    <serviceBehaviors>
        <behavior name="superDuperBehaviour">
            <serviceCredentials>
                <!-- The following element specifies the certificate use by this service for HTTPS (SSL) based transport security -->
                <serviceCertificate findValue="<some identifier>"
                        storeLocation="LocalMachine"
                        storeName="My"
                        x509FindType="FindBySubjectName" />
                <userNameAuthentication userNamePasswordValidationMode ="Custom" customUserNamePasswordValidatorType 

="SupportClasses.CustomUserNameValidator,SupportClasses"/>
            </serviceCredentials>
            <!-- The following element specifies how we're authorizing based on the client certificates received -->
            <serviceAuthorization serviceAuthorizationManagerType="SupportClasses.AuthorizationManager, SupportClasses"/>
            <serviceMetadata httpsGetEnabled="true"/>
            <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
    </serviceBehaviors>
</behaviors>

那么你可能会问的问题在哪里?好吧,看到那个<serviceBehavior>元素了吗?您可能知道此元素全局应用于服务,这意味着在运行时将调用 CustomUserNameValidator 和 AuthorizationManager。后者会抱怨当客户端使用 wsHttpBinding 调用服务时没有证书存在!

啊!

替代解决方案

到目前为止,这些是我提出的替代解决方案:

备选方案 1)创建另一个 Windows 服务,在不同的 URL 上托管我们的 WCF 服务。然后这两个服务将有一个单独的配置。

备选方案 2)创建两个托管在同一个 Windows 服务中的服务实现,并将它们都暴露在元素中,每个都有自己的绑定和 serviceBehaviour

备选方案 3)确定是否有可能保留当前配置并让 CustomUserNameValidator 和 AuthorizationManager 和平共存

很抱歉这篇长文,但在为我的问题提供背景时,我需要彻底。

问题 1)有没有人让 WCF 使用非平凡的配置与 Java 客户端一起工作?

问题 2)有没有人对如何解决替代方案 3 提出建议?(如果可能的话)

问题 3)如果有的话,您会推荐上述替代方案中的哪一个?

问题 4)您知道我还没有想到的其他替代方案吗?

作为记录,我研究了 WCF 互操作性工具,但我真的看不出它对我们有什么帮助。如果有人阅读本文后使用互操作性“向导”取得了良好的效果,

请告诉我。

提前致谢。

——诺吉

4

1 回答 1

0

我将首先在 //services 中添加第二个元素,并使用新的 @bindingConfiguration 属性和不同的 @address 属性对其进行配置。我认为这会比备选方案 1、2 或 3 更简单;或者也许它是替代 3,我不知道。

Web 服务的存在是为了提供与语言、供应商、平台和供应商无关的互操作。WCF 和 Java 每天都在现实世界的解决方案中进行互操作。

你看过这个关于WCF 和 Java 互操作的系列吗?

此外,听起来您会从使用一些诊断工具中受益,这些工具可以让您看到 .NET/WCF 客户端消息和 Java 客户端消息之间的差异。使用 Fiddler 或其他一些嗅探器实用程序查看线路上的消息。打开 WCF 跟踪以查看 WCF 在收到消息后执行的操作。

于 2011-11-13T05:53:35.747 回答