Невозможно установить заголовок Basic Auth динамически через HandlerResolver внутри контейнера - PullRequest
0 голосов
/ 16 октября 2018

У нас есть требование установить заголовок Basic Auth Authorization для всех исходящих вызовов SOAP.Наше J2EE-приложение использует Spring, выступая в качестве SOAP-клиента.

<bean id="myServices"
    class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
    <property name="serviceInterface"
        value="training.service.mybusinessservices.myBusinessServicesPort" />
    <property name="wsdlDocumentUrl" value="${my.service.wsdlDocumentUrl}" />
    <property name="endpointAddress" value="${my.service.endpoint}" />
    <property name="namespaceUri"
        value="http://training.org/myBusinessServices" />
    <property name="serviceName" value="myBusinessServices" />
    <property name="portName" value="myBusinessServices" />
    <property name="lookupServiceOnStartup" value="false" />
    <property name="handlerResolver" ref="serviceSecurityHandler" />
</bean>

Наше требование заключается в получении имени пользователя и пароля из центрального хранилища на основе вызываемого нами serviceName.Следовательно, подход состоял в том, чтобы использовать handlerResolver для установки заголовка http через перехватчик (вместо использования свойств JaxWsProxy .... имя пользователя и пароль)

Наша реализация перехватчика handlerResolver

@Override
public boolean handleMessage(SOAPMessageContext context) {
    logger.debug("handleMessage()-start");
    boolean isOutBound = true;

    try {

        Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        if(context.getMessage() !=null && outboundProperty.booleanValue()) {

            MessageLogger.logMessage(AuthConstants.HANDLE_MESSAGE, "Context not null " + context.getMessage(),AuthConstants.DEBUG, null);

            String sourceAppID = getValueByTagName(context,AuthConstants.SOURCE_APPID);
            String channelID = getValueByTagName(context,AuthConstants.CHANNEL_ID);




            logger.debug("Retrieving the basic auth token details for sourceAppID:{}, channelID:{}",sourceAppID,channelID );

            /*
             * Retrieve the Basic Auth Token for the key
             * sourceAppID~channelID
             * e.g.
             * MOBILEAPP~ONLINE
             * or
             * MYWEBAPP~PORTAL
             */
            String encodedBasicAuthCredentials = getAuthorizationDetails (sourceAppID, channelID);
            String[] userDetailsPair = getUserDetailsPairFromBasicAuthCredentials(encodedBasicAuthCredentials);
            logger.debug("Obtained the userDetailsPair:{}",userDetailsPair);
            if(userDetailsPair !=null && userDetailsPair.length ==2) {
                logger.debug("Settings the context header:{}",userDetailsPair);
                logger.debug("Settings the context with username:{} and password:{}",userDetailsPair[0],userDetailsPair[1]);
                context.put("javax.xml.ws.security.auth.username", userDetailsPair[0]);
                context.put("javax.xml.ws.security.auth.password", userDetailsPair[1]);

                //Came across a forum where it was recommended to call saveChanges() for container starting from Tomcat v8.0
                context.getMessage().saveChanges();
            }
            else {
                logger.error("The authorization header is not set because of unavailability for sourceAppID:{}, channelID:{}",sourceAppID,channelID );
            }

        } else {

            isOutBound = false;
        }

    }catch (Exception e) {
        logger.error("Exception  in handleMessage:{}", e.getMessage());
        if(logger.isDebugEnabled()){
            logger.error("Exception  in handleMessage:" , e);
        }
    }

    logger.debug("handleMessage()-end");
    return isOutBound;
}

Тот же код работаетнормально через Junit

Но когда я тестирую через JBOSS EAP 7.0, заметил, что заголовок Authorization не установлен.Также замечено, что внутри JBOSS CXF имеет приоритет как клиентский атрибут и не устанавливает заголовок авторизации

Любые указатели будут действительно полезны

1 Ответ

0 голосов
/ 17 октября 2018

Эта проблема была решена с помощью org.apache.cxf.jaxws.JaxWsProxyFactoryBean и заменила обработчик outInterceptor

Так что теперь конфигурация выглядит как

<bean id="saajOutInterceptor" class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
<bean id="myServices" factory-bean="myServicesClientFactory"
        factory-method="create" />
<bean id="myServicesClientFactory"
    class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
    <property name="serviceInterface"
        value="training.service.mybusinessservices.myBusinessServicesPort" />
    <property name="wsdlLocation" value="${my.service.wsdlDocumentUrl}" />
    <property name="address" value="${my.service.endpoint}" />
        <property name="outInterceptors">
            <list>
                <ref bean="saajOutInterceptor" /> <!-- This important, if we need to read any data from the requestXml and generate dynamic auth headers -->
                <ref bean="clientAuthInterceptor" />
            </list>
        </property>
</bean>

Справочные статьи

Как динамически добавлять заголовки HTTP в клиенте CXF?

Примечание. Убедитесь, что включен cxf-rt-bindings-soap-3.xxjar (перехватчик SAAJOutInterceptor)

Итак, при следующем подходе теперь заголовок Basic Auth генерируется динамически и работает

...