2014-06-10 3 views
5

Я пытаюсь создать клиент Apache CXF (2.7.5) для веб-сервисов Microsoft Dynamics CRM 2011 («xRM») (который, как я понял, основан на WCF 4), где CRM находится в режиме претензий, так что WSDL для этой веб-службы указывает на STS (в моем случае AD FS 2.0).Клиент Apache CXF для режима требований xRM (Microsoft Dynamics CRM 2011)?

Мой главный вопрос: Есть ли какой-либо учебник, предложения, сообщения в блогах, чтобы помочь мне (описав, как отправлять претензии, или как их избежать, и вместо этого использовать проверку подлинности Windows)?

Ниже приведено описание того, что я делал до сих пор.


я уже работающий код для того же веб-сервис, который работает, когда CRM в режиме проверки подлинности Windows. Этот код основан на "CXF and MS CRM 2011" on Groovy Tom's Blog.

Для поддержки режима с претензиями, мне также необходимо включить org.apache.cxf:cxf-rt-ws-mex, так что xRM WSDL может быть проанализирован CXF. Тогда мне нужно сделать CXF встроенный STS-клиент использовал SOAP 1.2:

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

, чтобы избежать ошибки 500 из AD FS 2.0. (По-видимому AD FS 2.0 ожидает/ADFS/услуги/доверие/MEX конечной точкой будет вызываться с использованием SOAP 1.2, и CxF по умолчанию SOAP 1.1. Я должен был это выяснить из AD FS's WCF trace, который сообщил

System.ServiceModel .ProtocolException: Тип содержимого текст/XML; кодировка = UTF-8, был отправлен в службу ожидая приложения/мыло + XML; кодировка = UTF-8 привязок клиента и службы могут быть несовпадающие

, когда Apache CXF.. используется SOAP 1.1.)

Тогда возникла и другая проблема: WSDL, возвращаемый AD FS/adfs/services/trust/mex конечная точка казалась неполной, в том, что она содержит

<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> 

так ни один из import с не имеет schemaLocation. Это делает CXF жалуются, что

org.apache.cxf.wsdl11.WSDLRuntimeException: часть запроса определяется как элемент {http://docs.oasis-open.org/ws-sx/ws-trust/200512} RequestSecurityToken которая не находится в схеме.

я узнал, что это вызвано: Схемы, содержащие RequestSecurityToken и т.д. в результате вызова MEX SOAP, но в отдельных <wsx:MetadataSection Dialect="http://www.w3.org/2001/XMLSchema"> секций, код в AbstractSTSClient полностью игнорирует.

Итак, я установил собственный WSDLFactory + WSDLReader (используя свойство {{javax.wsdl.factory.WSDLFactory}}), который просто вставляет схемы для трех пространств имен в любой WSDL, который он читает.

Теперь я заблокирован в следующем пункте: XRM WSDL (после форматирования) содержит Address из 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> 

Так что теперь я могу сделать?


В более общем плане, на мой вопрос теперь: Я на правильном пути для построения клиента Java для XRM-в-тяжб режиме? Как другие получили работу? Или, может быть, есть способ избежать использования с использованием утверждений, а вместо этого использовать проверку подлинности Windows с режимом xRM-in-Claim-mode?

ответ

5

Мы, наконец, получили его на работу, используя не только "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.

К сожалению, я не могу напрямую публиковать код по причинам лицензирования, но вот обзор того, что мы сделали.


Ключевая часть решения Ян-Хендрик Kuperus является то, что мы создаем нашу собственную STSClient, вместо того, чтобы позволить CXF создать. Это касается вопроса об игнорируемых разделах <wsx:MetadataSection Dialect="http://www.w3.org/2001/XMLSchema">. Он также работает вокруг проблемы адресации из моего вопроса, так как был исправлен в CXF trunk. (К сожалению, мы не можем перейти к последней версии 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: «Обновление».)

Теперь зарегистрировать stsClient в контексте запроса по собственности SecurityConstants.STS_CLIENT ("ws-security.sts.client"), установите свойство контекста запроса SecurityConstants.USERNAME, а в собственности SecurityConstants.CALLBACK_HANDLER регистрации CallbackHandler, который обрабатывает полученную WSPasswordCallback и устанавливает пароль, и вы в бизнесе. Кроме.

За исключением того, что в этот момент мы обнаружили, что CXF 2.7.5 дросселирует WSDL AD FS: java.lang.IllegalArgumentException: sp:KeyValueToken/wsp:Policy must have a value в KeyValueTokenBuilder # build(). Оказывается, WSDL содержит ряд политик безопасности с атрибутом wsp:Optional="true", и для каждого из этих CXF ожидается вложенный элемент <wsp:Policy>. Итак, мы сделали предварительную обработку AD FS WSDL и просто добавили пустые <wsp:Policy/> элементы в этих местах.

(Мы не знаем, является ли CXF 2.7.5 слишком строгим, или WSDL AD FS 2.0 не соответствует стандартам.)


Кроме того, мы достигли в динамически переключатель между Windows, режим XRM и системы XRM требований режима, глядя на <ms-xrm:AuthenticationPolicy> элемент политики безопасности XRM WSDL, и проверить <ms-xrm:Authentication> содержит ли либо ActiveDirectory или Федерации. Мы сделали это, создав расширение пользовательской политики, простирающееся на XmlPrimitiveAssertion и зарегистрировав соответствующий пользовательский строитель в bus.getExtension(AssertionBuilderRegistry.class). Затем мы создаем пользовательский 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); 
    } 
} 

Наконец, так как мы не хотим работать с загруженной версией WSDL AD FS, мы сделали «фиксирование» этот WSDL в тот же самый «перехватчик», получив утверждение SP12Constants.ISSUED_TOKEN, получив его .getIssuerEpr().getMetadata().getAny(), и оттуда {http://www.w3.org/2005/08/addressing}Address. В результате чего-то вроде http://example.com:12345/adfs/services/trust/mex. Мы извлекаем этот URL-адрес, анализируем XML, добавляем элементы <wsp:Policy/>, как описано выше, сохраняем результат в файле и используем URL этого файла в качестве wsdlLocation STSClient.


Надеюсь, это поможет другим; не стесняйтесь задавать вопросы, если вы не получите этого, чтобы работать.

+0

Не предполагайте, что вы могли бы прояснить, что «Итак, что мы сделали, это предварительная обработка AD FS WSDL, а просто добавленные пустые элементы в этих местах означает? Я получаю ту же ошибку, застрял на пару дней –

+0

В частности, где я могу добавить пустой в/mex wsdl. Справка * сильно * оценена. –

+1

@AlanHollis Как я уже писал, мне нужно было добавить '' непосредственно внутри всех элементов с помощью 'wsp: Optional = true ". См. например https://corp.sts.microsoft.com/adfs/services/trust/mex, где вы можете увидеть такие элементы, как' и ''. –

2

Я слился исправление для «анонимного» вопроса к CXF:

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

Когда адрес Эмитента «анонимный», вы можете указать нужное имя STS Endpoint через метаданные, или в противном случае он вернется к простому выбору первого порта в полученном WSDL.

Кол.

+0

+1 Спасибо за исправление! У меня нет возможности переключиться на более новую версию CXF, но хорошо знать, что это было подобрано. За полноту обратите внимание, что также остается проблема игнорируемых разделов '' в 'AbstractSTSClient'. –

Смежные вопросы