2012-08-16 18 views
7

Sto riscontrando qualche problema nell'impostazione dell'intestazione dell'autorizzazione HTTP per una richiesta di servizio Web utilizzando Apache CXF. Io ho la mia installazione del client attraverso la primavera:Autenticazione di base HTTP tramite intercettore CXF non funzionante

<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" /> 
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> 

<bean id="myHTTPAuthInterceptor" class="my.app.MyHTTPAuthInterceptor" autowire="constructor" /> 

<bean id="webServiceFactory" class="my.app.WebServiceFactory"> 
    <property name="wsdlLocation" value="classpath:/my/app/webservice.wsdl" /> 
    <property name="serviceURL"> 
     <jee:jndi-lookup jndi-name="webservice/url" /> 
    </property> 
    <property name="inInterceptors"> 
     <list> 
      <ref bean="loggingInInterceptor" /> 
     </list> 
    </property> 
    <property name="outInterceptors"> 
     <list> 
      <ref bean="loggingOutInterceptor" /> 
      <ref bean="myHTTPAuthInterceptor" /> 
     </list> 
    </property> 
</bean> 

<bean id="myWebService" factory-bean="webServiceFactory" factory-method="getInstance" /> 

intestazioni vengono impostati tramite MyHTTPAuthInterceptor come questo:

public MyHTTPAuthInterceptor(ConfigDao configDao) 
{ 
    super(Phase.POST_PROTOCOL); 

    this.configDao = configDao; 
} 

@Override 
public void handleMessage(Message message) throws Fault 
{ 
    Map<String, List<?>> headers = (Map<String, List<?>>) message.get(Message.PROTOCOL_HEADERS); 

    String authString = configDao.getUsername() + ":" + config.getPassword(); 
    headers.put("Authorization", Collections.singletonList("Basic " + new String(Base64.encodeBase64(authString.getBytes())))); 
} 

con username e entrambi impostati su 'test', tutto sembra essere OK nei registri:

Headers: {SOAPAction=[""], Accept=[*/*], Authorization=[Basic dGVzdDp0ZXN0]} 

Tuttavia, il server restituisce un HTTP 401: Non autorizzato.

Non sapendo cosa non va, ho adottato un altro approccio cambiando il codice di fabbrica del client del servizio web. Ho aggiunto una politica di autorizzazione di base per il condotto del cliente in questo modo:

HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); 
AuthorizationPolicy authorizationPolicy = new AuthorizationPolicy(); 
authorizationPolicy.setUserName("test"); 
authorizationPolicy.setPassword("test"); 
authorizationPolicy.setAuthorizationType("Basic"); 
httpConduit.setAuthorization(authorizationPolicy); 

Testato nuovo la mia messa a punto, lo stesso ceppo (ordine diverso però):

Headers: {SOAPAction=[""], Authorization=[Basic dGVzdDp0ZXN0], Accept=[*/*]} 

Ora la risposta del server è 200 OK!

Problema risolto si potrebbe pensare, ma il secondo approccio non funziona davvero per me. La mia applicazione è un ambiente multi-tenant, il tutto con nome utente e password diversi. Con il secondo approccio non posso riutilizzare il mio cliente.

Come posso far funzionare correttamente il mio intercettore? Sto collegando nella fase sbagliata? Importa l'ordine delle intestazioni? Se sì, come posso cambiarlo?

risposta

5

Ho quasi la stessa configurazione della tua ma sto mettendo il mio intercettore nella fase PRE_PROTOCOL. Finora, non ho avuto alcun problema. Potresti provarlo.

Penso che POST_PROTOCOL sia troppo tardi perché troppo è già stato scritto nello stream.

+0

Provato, ma ahimè, senza fortuna ... – verhage

+2

Ok, devo correggermi qui. Ho fatto un errore. Funziona! Grazie mille, la tua risposta è accettata qui :) – verhage

3

Se stai cercando di esternare il cliente e l'autenticazione approccio migliore è quello di impostare httpConduit nel contesto primavera ..

**in your spring context file...** 

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:jaxws="http://cxf.apache.org/jaxws" 
     ... 

    <bean id="properties" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"> 
    <property name="locations"> 
     <util:list> 
      <value>file:${config.dir}/application.properties</value> 
     </util:list> 
    </property> 
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> 
</bean> 
    ... 
    <jaxws:client id="serviceClient" serviceClass="com.your.ServiceClass" address="${webservice.soap.address}" > 
    <jaxws:inInterceptors> 
     <bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" > 
      <property name="prettyLogging" value="true" /> 
     </bean> 
    </jaxws:inInterceptors> 
    <jaxws:outInterceptors> 
     <bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" > 
      <property name="prettyLogging" value="true" /> 
     </bean> 
    </jaxws:outInterceptors> 
    </jaxws:client> 
    ... 


applicaiton.properties 
--------------------- 
webservices.http.auth.username=userName 
webservices.http.auth.password=Password 
webservice.soap.address=https://your.service.url/services/service 

a) menzionando l'indirizzo SOAP in name. che la vostra latta trovare nella vostra WSDL

Ex: if in your WSDL.. 
    <wsdl-definitions ... targetNamespace="http://your.target.namespace.com/" ...> 
    ... 
    <wsdl:port binding="tns:YourServiceSoapBinding" 
     name="YourServiceImplPort"> 
     <soap:address location="https://your.service.url/services/service" /> 

Poi

... 
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration" 
xmlns:sec="http://cxf.apache.org/configuration/security" 
... 
<http-conf:conduit name="https://your.service.url/services/service"> 
    <http-conf:authorization> 
     <sec:UserName>${webservices.http.auth.username}</sec:UserName> 
     <sec:Password>${webservices.http.auth.password}</sec:Password> 
     <sec:AuthorizationType>Basic</sec:AuthorizationType> 
    </http-conf:authorization> 
</http-conf:conduit> 

O attributo b) nome dovrebbe essere {} targetNamespace portName.http_conduit

<http-conf:conduit name="{http://your.target.namespace.com/}YourServiceImplPort.http_conduit"> 
    <http-conf:authorization> 
     <sec:UserName>${webservices.http.auth.username}</sec:UserName> 
     <sec:Password>${webservices.http.auth.password}</sec:Password> 
     <sec:AuthorizationType>Basic</sec:AuthorizationType> 
    </http-conf:authorization> 
</http-conf:conduit> 
Problemi correlati