2017-02-23 66 views
0

Я должен реализовать JAX-WS-Client, который использует сервис от внешнего партнера. Я использую Apache CXF. Служба определяет два WS-Policies для аутентификации в wsdl - KerberosToken и UsernameToken. Поскольку услуга предоставляется внешним партнером, она не может быть изменена.JAX-WS Client CXF WS-Policy Issue

Проблема: аутентификация завершается с ошибкой в ​​Kerberos-Authentication, так как я хочу использовать простую аутентификацию UsernameToken.

WSLD-политики Часть:

<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
    wsu:Id="SecurityServiceUsernameUnsecureTransportPolicy"> 
    <wsp:ExactlyOne> 
    <wsp:All> 
    <sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> 
    <wsp:Policy> 
     <sp:KerberosToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> 
     <wsp:Policy> 
     <sp:WssGssKerberosV5ApReqToken11/> 
     </wsp:Policy> 
     </sp:KerberosToken> 
    </wsp:Policy> 
    </sp:SupportingTokens> 
    </wsp:All> 
    <wsp:All> 
    <sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> 
    <wsp:Policy> 
     <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"> 
     <wsp:Policy> 
     <sp:WssUsernameToken10/> 
     </wsp:Policy> 
     </sp:UsernameToken> 
    </wsp:Policy> 
    </sp:SupportingTokens> 
    </wsp:All> 
    </wsp:ExactlyOne> 
</wsp:Policy> 

Установка Имя пользователя/Пароль на CXF-конечной точки:

public void addAuthenticationProperties(Endpoint endpoint) { 
    endpoint.put(SecurityConstants.USERNAME, userName); 
    endpoint.put(SecurityConstants.PASSWORD, password); 
} 

Как я понимаю -tag означает, что если какой-либо (одно все тоже) этого политика полностью заполнена. Но CXF даже не пытается заполнить UserToken - Policy.

Если я удаляю -Block для проверки подлинности KerberosToken, это нормально, но в производстве это невозможно.

Любые подсказки? Если в wsdl или в моем подходе есть ошибка, сообщите мне. И, пожалуйста, уточните, что я в этой области.

Заранее благодарен!

ответ

0

Несколько дней спустя я нашел обходной путь для этой проблемы - не назвал бы это решение ;-)

Сначала старой версии: CXF генерируется класс ExampleWS_Service и соответствующий интерфейс ExampleWS. Таким образом, я использовал ExampleWS_Service установить Everthing и вызывать службу:

// creating Port 
URL url = new URL(config.getSchema(), config.getHost(), config.getPort(), config.getPath()); 

ExampleWS_Service service = new ExampleWS_Service(url); 
ExampleWS port = service.getExampleWSPort(); 

// Adding authentication-info 
Client client = ClientProxy.getClient(port); 
Endpoint cxfEndpoint = client.getEndpoint(); 

cxfEndpoint.put(SecurityConstants.USERNAME, userName); 
cxfEndpoint.put(SecurityConstants.PASSWORD, password); 

... 
// invoke service 
port.doSomething([data]); 

обходной: я перешел на JaxWsProxyFactoryBean и установка Everthing вверх. В этом случае WSS4JOutInterceptor необходим для размещения данных аутентификации в заголовке запроса. Некоторый код:

URL url = new URL(config.getSchema(), config.getHost(), config.getPort(), config.getPath()); 

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); 
factory.setServiceClass(ExampleWS.class); 
factory.setAddress(url.toString()); 
factory.setBindingId("http://schemas.xmlsoap.org/wsdl/soap12/"); 

ExampleWS port = (ExampleWS)factory.create(); 

// Adding authentication-info using WSS4JOutInterceptor 
Client client = ClientProxy.getClient(port); 
Endpoint cxfEndpoint = client.getEndpoint(); 

Map<String, Object> outProps = new HashMap<>(); 
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); 
outProps.put(WSHandlerConstants.USER, userName); 
outProps.put(WSHandlerConstants.PASSWORD_TYPE, passwordType); 
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, [Instance of javax.security.auth.callback.CallbackHandler]); 

WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); 
cxfEndpoint.getOutInterceptors().add(wssOut); 

... 
// invoke service 
port.doSomething([data]); 

Я не знаю, почему именно этот способ на самом деле работает, но это :-) Может быть кто-то из вас может дать мне так просветление.

0

CXF не обрабатывает множество параметров политики исходящей стороны для обеспечения безопасности, только со стороны входящего. Таким образом, ваш единственный вариант - это ужесточение политики для Kerberos или UsernameToken, в зависимости от политики, которую вы хотите использовать для своего клиента.

+0

Спасибо Colm O hEigeartaigh! Есть ли способ сказать клиенту игнорировать эти политики и просто отправить UsernameToken-Request? Я не могу затягивать политики, потому что серверная сторона определяется внешним партнером. –

+0

Это может помочь вам: http://cxf.apache.org/ws-policy-framework.html. По умолчанию выбирается первая альтернатива политики, но может быть способ ее настройки. –

+0

Thx Colm O hEigeartaigh! Я посмотрю. Помимо этого, я нашел обходное решение. Возможно, вы можете дать некоторые плюсы или минусы этому обходному пути. –