当前位置: 首页 > 知识库问答 >
问题:

用于索赔模式xRM的Apache CXF客户端(Microsoft Dynamics CRM 2011)?

邹英发
2023-03-14

我试图创建一个Apache CXF(2.7.5)客户端,用于Microsoft Dynamics CRM 2011(xRM)Web服务(我理解为基于WCF 4),其中CRM处于索赔模式,因此此Web服务的WSDL指向STS(在我的情况下AD FS 2.0)。

我的主要问题是:是否有任何教程、建议和博客帖子可以帮助我(或者描述如何发送声明,或者如何避免声明,而是使用Windows身份验证)?

下面是我到目前为止所做工作的描述。

我已经有了相同网络服务的工作代码,当客户关系管理处于视窗身份验证模式时,该服务可以工作。该代码基于Groovy Tom's Blog上的CXF and MS CRM 2011。

为了支持索赔模式,我还需要加入org。阿帕奇。cxf:cxf rt ws-mex,这样xRM WSDL就可以被cxf解析。然后我需要让CXF内置的STS客户端使用SOAP 1.2:

client.getRequestContext().put("ws-security.sts.client-soap12-binding", "true");

以避免AD FS 2.0出现错误500。(显然,AD FS 2.0希望使用SOAP 1.2调用/adfs/services/trust/mexendpoint,而CXF默认为SOAP 1.1。我必须从AD FS的WCF跟踪中找到这一点,该跟踪报告

系统服务模型。ProtocolException:内容类型text/xml;charset=UTF-8被发送到一个需要应用程序/soap xml的服务;字符集=utf-8。客户端和服务绑定可能不匹配。

当Apache CXF使用SOAP 1.1。(

然后还有另一个问题:AD FS /adfs/services/trust/mexendpoint返回的WSDL似乎不完整,因为它包含

<wsdl:types>
    <xsd:schema
        targetNamespace="http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice/Imports">
        <xsd:import namespace="http://schemas.microsoft.com/Message" />
        <xsd:import namespace="http://schemas.xmlsoap.org/ws/2005/02/trust" />
        <xsd:import namespace="http://docs.oasis-open.org/ws-sx/ws-trust/200512" />
    </xsd:schema>
</wsdl:types>

因此,imports中没有一个具有schemaLocation。这让CXF抱怨

org.apache.cxf.wsdl11。WSDLRuntimeExcema:部分请求定义为元素{http://docs.oasis-open.org/ws-sx/ws-trust/200512}请求安全令牌,该元素不在模式中。

我发现了是什么导致了这种情况:包含的模式是在mex SOAP调用结果中,但在单独的中。

因此,我放置了自己的WSDLFactory WSDLReader(使用属性{javax.wsdl.factory.WSDLFactory}),它只将三个名称空间的模式插入到它读取的任何wsdl中。

现在我在下一点被阻止了:xRM WSDL(格式化后)包含一个地址http://www.w3.org/2005/08/addressing/anonymous(见下文),这会以某种方式导致CXF在AD FS的元数据中查找该endpoint。然而,这样的endpoint当然不存在:它包含,例如,https://...:.../adfs/services/trust/2005/usernamemixed

<wsdl:definitions
    targetNamespace="http://schemas.microsoft.com/xrm/2011/Contracts/Services"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
    snipped="other xmlns attributes">
    <wsp:Policy wsu:Id="CustomBinding_IOrganizationService_policy">
        <wsp:ExactlyOne>
            <wsp:All>
                <!-- snip -->
                <sp:EndorsingSupportingTokens
                    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                    <wsp:Policy>
                        <sp:IssuedToken
                            sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
                            <Issuer
                                xmlns="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
                                <Address xmlns="http://www.w3.org/2005/08/addressing">
                                    http://www.w3.org/2005/08/addressing/anonymous
                                </Address>

那我现在能做什么?

更一般地说,我现在的问题是:在索赔模式下为xRM构建Java客户机的道路是否正确?其他人是怎么做到的?或者有没有办法避免使用声明,而是在声明模式下使用Windows身份验证和xRM?


共有2个答案

蒋星雨
2023-03-14

我已经将“匿名”问题的修复程序合并到CXF:

https://issues.apache.org/jira/browse/CXF-5807

当颁发者地址为“匿名”时,您可以通过元数据指定所需的STSendpoint名称,否则它将退回到只选择接收到的WSDL中的第一个端口。

科尔姆。

雍嘉勋
2023-03-14

我们最终实现了它,不仅使用了Groovy Tom的博客上的“CXF和MS CRM 2011”,我在这个问题中提到过,还使用了Jan Hendrik Kuperus在JH on Java博客(archive.org cached copy)上的“使用Apache CXF连接到Microsoft Dynamics”,此外还修改了(?)adfs2.0wsdl。

不幸的是,出于许可的原因,我不能直接发布任何代码,但下面是我们所做工作的概述。

Jan Hendrik Kuperus解决方案的关键部分是我们创建自己的STSClient,而不是让CXF创建一个。这解决了被忽略的

在该定制STS客户端中,我们指向特定的AD FSendpoint,确保使用SOAP 1.2(防止HTTP错误500,请参阅问题),并关闭“续订”:

STSClient stsClient = new STSClient(bus);
stsClient.setSoap12();
stsClient.setWsdlLocation(wsdlLocation.toExternalForm());
stsClient.setServiceQName(new QName("http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice", "SecurityTokenService"));
stsClient.setEndpointQName(new QName("http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice", "UserNameWSTrustBinding_IWSTrust13Async"));
stsClient.setSendRenewing(false);

(如果未关闭续订,则AD FS 2.0返回SOAP错误ID3035:请求无效或格式错误。AD FS跟踪表示"Microsoft.识别模型。SecurityTokenService.Invalid刚需异常:MSIS3137:刚需安全令牌元素包含一个不受支持的WS-Trust参数:'Renewing'。(

现在在请求上下文中的属性Security常量下注册stsClient。STS_CLIENT"ws-security.sts.client"),设置请求上下文属性Security常量。USERNAME,并且在属性Security常量中。CALLBACK_HANDLER注册一个CallbackHandler,它处理生成的WSPasswordCallback并设置密码,您就可以开始工作了。除了。

除了在那一点上,我们发现CXF 2.7.5阻塞了AD FS的WSDL:java.lang.IllegalArgumentExc0019: sp: KeyValueToken/wsp:策略必须在KeyValueTokenBuilder#build()中有一个值。事实证明,WSDL包含许多具有属性wsp:可选="true"的安全策略,对于这些策略中的每一个,CXF都期望嵌套

(我们不知道CXF 2.7.5在这里是否过于严格,或者AD FS 2.0的WSDL是否不符合标准。)

此外,通过查看

private static class XRMAuthSecurityModeInterceptor extends AbstractSoapInterceptor {
    public XRMAuthSecurityModeInterceptor() {
        super(Phase.PREPARE_SEND);
        addBefore("IssuedTokenOutInterceptor");
    }

    public void handleMessage(SoapMessage message) throws Fault {
        // if the custom assertion with security mode Federation is present, then create STSClient and...
            message.setContextualProperty(SecurityConstants.STS_CLIENT, stsClient);
    }
}

最后,由于我们不想使用AD FS的WSDL的下载版本,所以我们通过获取SP12常量,在同一个'out拦截器'中对该WSDL进行了'修复'。ISSUED_TOKEN断言,获取它的. getIssuerEpr(). getMetadata(). getany(),并从中获得{http://www.w3.org/2005/08/addressing}地址。结果类似http://example.com:12345/adfs/services/trust/mex.我们检索该URL,解析XML,添加

希望这能帮助其他人;如果你不能让它发挥作用,请随时提问。

 类似资料:
  • 问题内容: 到现在为止,我主要是利用,,用于构建Web应用程序技术堆栈。关键是,提到的堆栈使用服务器端模式。Web浏览器的主要作用仅限于请求/响应周期(+客户端验证)。数据检索,业务逻辑,接线和验证是服务器端的主要职责。 我对 AngularJS 框架有几个疑问,这些疑问是由我阅读过以下引号引起的: 从 AngularJS教程中 : 对于Angular应用,我们鼓励使用Model-View-Con

  • 关于AngularJS框架,我有几个问题是从我读到的以下引用中得到启发的: 从AngularJS教程: 对于有角度的应用程序,我们鼓励使用Model-View-Controller(MVC)设计模式来解耦代码并分离关注点。 我知道我的问题有些奇怪,但我认为原因是,我对传统的服务器端MVC模式有些敏感。我确信有人已经做了同样的转变。

  • 问题内容: 有了JSR 311及其实现,我们有了一个强大的标准,可以通过REST公开Java对象。但是,在客户端,似乎缺少与SOAP的Apache Axis类似的东西-隐藏了Web服务并将数据透明地封送回Java对象的东西。 您如何创建Java RESTful客户端?使用HTTPConnection和手动解析结果?还是专业客户(例如Jersey或Apache CXR)? 问题答案: 这是一个古老的

  • 问题内容: 我正在开发一个项目,该项目需要解析一些受保护的网页中的数据。为了获得对这些页面的访问权限,我必须克服SAML身份验证形式(Shibboleth)。是否有人能够在Android(Java)中实现此标准?我已经读过这个线程:Android的SAML客户端实现? 但这并不能给我一个很好的解决方案。实际上,我需要 获取某些受保护网页的数据 以便对其进行解析,而不是让用户看到此类网页的内容。因此

  • 问题内容: 有人知道iOS的Elasticsearch客户端库吗?如果它也是迅速写的,那将是一个好处。 elasticsearch的“客户端”部分显示了多个平台的多个库,但对于iOS没有任何显示,我觉得有人必须这样做吗? 干杯 问题答案: 我怀疑是否有人- 上次我检查时没有,并且有充分的理由。请记住,为了允许IOS客户端(或Android)使用客户端库连接到Elasticsearch,您必须打开集

  • 问题内容: 我正在尝试从Java连接到ElasticSearch,但只能通过HTTP连接。我不能使用。ElasticSearch REST API周围是否有Java客户端包装?如果可以,该如何使用? 问题答案: 嗨,有一个全新的项目正好满足您的需求。基于Java的RestAPI for Elasticsearch 看看这个!它的名字是JEST