加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

wcf – 用于声明模式xRM(Microsoft Dynamics CRM 2011)的Apache

发布时间:2020-12-14 01:59:32 所属栏目:Windows 来源:网络整理
导读:我正在尝试为Microsoft Dynamics CRM 2011(“xRM”)Web服务(我理解为基于WCF 4)创建Apache CXF(2.7.5)客户端,其中CRM处于声明模式,因此WSDL这个Web服务指向STS(在我的情况下是AD FS 2.0). 我的主要问题:是否有任何教程,建议,博客文章可以帮助我(描述如何发
我正在尝试为Microsoft Dynamics CRM 2011(“xRM”)Web服务(我理解为基于WCF 4)创建Apache CXF(2.7.5)客户端,其中CRM处于声明模式,因此WSDL这个Web服务指向STS(在我的情况下是AD FS 2.0).

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

以下是我到目前为止所做的事情的描述.

我已经拥有相同Web服务的工作代码,当CRM处于Windows身份验证模式时,该服务可以正常运行.该代码基于“CXF and MS CRM 2011” on Groovy Tom’s Blog.

为了支持声明模式,我还需要包含org.apache.cxf:cxf-rt-ws-mex,以便CXF可以解析xRM WSDL.然后我需要让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 / mex端点,而CXF默认使用SOAP 1.1.我必须从AD FS’s WCF trace发现这一点,

System.ServiceModel.ProtocolException: Content Type text/xml; charset=UTF-8 was sent to a service expecting application/soap+xml; charset=utf-8. The client and service bindings may be mismatched.

当Apache CXF使用SOAP 1.1时.)

然后还有另一个问题:AD FS的/ adfs / services / trust / mex端点返回的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>

所以没有一个导入有一个schemaLocation.这让CXF抱怨道

org.apache.cxf.wsdl11.WSDLRuntimeException: Part request defined as element {07003}RequestSecurityToken which is not in the schema.

我发现了导致这种情况的原因:包含RequestSecurityToken等的模式在mex SOAP调用结果中,但在单独的< wsx:MetadataSection Dialect =“http://www.w3.org/2001/XMLSchema”>中.部分,AbstractSTSClient中的代码完全忽略.

所以我使用了我自己的WSDLFactory WSDLReader(使用属性{{javax.wsdl.factory.WSDLFactory}}),它只是将三个命名空间的模式插入到它读取的任何WSDL中.

现在我被阻止了下一点:xRM WSDL(格式化后)包含一个http://www.w3.org/2005/08/addressing/anonymous的地址(见下文),它以某种方式导致CXF查找AD FS元数据中的该端点.但是,这样的端点当然不存在:它包含例如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-in-claims-mode构建Java客户端?其他人如何让这个工作?或者是否有办法避免使用声明,而是使用xRM-in-claims-mode的Windows身份验证?

解决方法

我们终于使用了它,不仅使用了我在这个问题中提到的 “CXF and MS CRM 2011” on Groovy Tom’s Blog,还使用了 “Using Apache CXF to connect to Microsoft Dynamics” by Jan-Hendrik Kuperus on the JH on Java blog,另外还修正了(?)AD FS 2.0 WSDL.

遗憾的是,出于许可原因,我无法直接发布任何代码,但这里概述了我们所做的工作.

Jan-Hendrik Ku??perus解决方案的关键部分是我们创建自己的STSClient,而不是让CXF创建一个.这解决了被忽略的< wsx:MetadataSection Dialect =“http://www.w3.org/2001/XMLSchema”>的问题.部分.它也解决了我的问题中的寻址问题,因为已经在CXF中继中修复了. (不幸的是,我们无法切换到最新的CXF版本:所有这些都是使用CXF 2.7.5完成的.)

在该自定义STS客户端中,我们指向特定的AD FS端点,确保我们使用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.IdentityModel.SecurityTokenService.InvalidRequestException:MSIS3137:RequestSecurityTokenElement包含一个不受支持的WS-Trust参数:’Renewing’.“)

现在在属性SecurityConstants.STS_CLIENT(“ws-security.sts.client”)下的请求上下文中注册stsClient,设置请求上下文属性SecurityConstants.USERNAME,并在属性SecurityConstants.CALLBACK_HANDLER中注册一个CallbackHandler,它处理生成的WSPasswordCallback并设置密码,你在做生意.除了.

除此之外我们发现AD FS的WSDL上有CXF 2.7.5 choke:java.lang.IllegalArgumentException:sp:KeyValueToken / wsp:Policy必须在KeyValueTokenBuilder#build()中有一个值.事实证明,WSDL包含许多具有属性wsp:Optional =“true”的安全策略,并且对于这些CXF中的每一个,期望嵌套的< wsp:Policy>元件.所以我们做的是预处理AD FS WSDL,并添加空的< wsp:Policy />这些地方的元素.

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

此外,我们通过查看< ms-xrm:AuthenticationPolicy>来实现在Windows模式xRM和声明模式xRM系统之间动态切换. xRM WSDL的安全策略中的元素,并检查< ms-xrm:Authentication>包含ActiveDirectory或Federation.我们通过创建扩展XmlPrimitiveAssertion的自定义策略扩展并在bus.getExtension(AssertionBuilderRegistry.class)中注册相应的自定义构建器来完成此操作.然后我们在自定义’out interceptor’中创建自定义STSClient:

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,我们通过获取SP12Constants.ISSUED_TOKEN断言获取其.getIssuerEpr(),在同一个“out interceptor”中对该WSDL进行“修复”. getMetadata().getAny(),以及{http://www.w3.org/2005/08/addressing}Address.结果类似于http://example.com:12345/adfs/services/trust/mex.我们检索该URL,解析XML,添加< wsp:Policy />如上所述的元素,将结果保存到文件,并将该文件的URL用作STSClient的wsdlLocation.

希望这有助于其他人;如果你没有让它工作,请随时提问.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读