背景(有点长):
几年前,我为客户编写了一个WCF服务,该服务被配置为使用带有clientCredentialType =“Certificate”的安全模式=“Transport”的basicHttpBinding,即客户端使用(客户端)证书对自己进行身份验证。该服务使用自定义AuthorizationManager来检查传入证书的指纹是否存在于有效证书指纹的预定义列表中。如果认为传入证书有效,则允许操作继续(如果不是,则抛出异常)。
这项服务已经完美无缺地工作了大约四年,每个人都很开心。但是,由于需求经常发生变化,最近我的客户已经被希望将其应用程序连接到客户服务的开发人员所接洽。唯一的问题是这些开发人员使用Java的一些变体作为他们的首选平台,现在我们面临一些严重的问题。长话短说,没有人设法让他们的Java实现(例如Metro,Axis2)与目前配置的服务一起使用。
上周,我们尝试通过使用Message clientCeredentialType =“UserName”将安全模式=“TransportWithMessageCredential”更改绑定到wsHttpBinding来使用Java编写的客户端(Metro,JAX-WS)。我还在配置文件中的服务凭证元素中添加了自定义UserNamePassWordValidatorType。
然后我注释掉了自定义AuthorizationManager,因为没有证书来自客户端。
Lo'看哪,这次我们让SoapUI和Java客户端都适当地与服务对话。
(顺便说一下,我们的服务是在Windows服务中自托管的)
很高兴,我们决定使用两个绑定来配置服务,现有的basicHttpBinding在很长一段时间内没有出现故障,以及新测试的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)在另一个URL上创建另一个托管我们的WCF服务的Windows服务。然后两个服务都将有一个单独的配置。
备选方案2)创建在同一Windows服务中托管的两个服务实现,并在元素中公开它们,每个元素都有自己的绑定和serviceBehaviour
备选方案3)弄清楚是否可以保持当前配置并使CustomUserNameValidator与AuthorizationManager和平共存
对于这篇长篇文章感到抱歉,但在提供问题的背景时我需要彻底。
问题1)有没有人让WCF使用非常重要的配置来使用Java客户端?
问题2)有没有人对如何解决备选方案3有任何建议? (如果可能的话)
问题3)您会推荐哪一种(如果有的话)?
问题4)您还知道其他我没想过的其他选择吗?
为了记录,我已经研究了WCF互操作性工具,但我无法真正看到它如何帮助我们。如果使用互操作性“向导”,那么阅读本文的人都有很好的结果,
请告诉我。
提前致谢。
- norgie
答案 0 :(得分:0)
我首先在//服务中添加第二个元素,然后使用新的@bindingConfiguration属性和不同的@address属性对其进行配置。我认为替代方案1,2或3会更简单;或者它可能是另类3,我不知道。
存在Web服务以提供语言,供应商,平台和供应商中立的互操作。 WCF和Java每天都在现实世界的解决方案中互操作。
您是否在WCF and Java interoperation上看了这个系列?
此外,听起来您可以从使用一些诊断工具中受益,这些工具可以让您看到.NET / WCF客户端消息和Java客户端消息之间的差异。使用Fiddler或其他一些嗅探工具来查看线路上的消息。打开WCF跟踪以查看WCF收到消息后所执行的操作。