2008-09-22 13 views
2

Nous avons du mal à configurer notre application Web pour pouvoir nous connecter aux services Web via Spring WS. Nous avons essayé d'utiliser l'exemple de la documentation de Spring-WS côté client, mais nous nous retrouvons avec une exception WebServiceTransportException. La configuration XML ressemble à ceci:WebServiceTransportException: non autorisé [401] dans Spring-WS

<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate"> 
    <constructor-arg ref="messageFactory"/> 
    <property name="messageSender"> 
     <bean class="org.springframework.ws.transport.http.CommonsHttpMessageSender"> 
      <property name="credentials"> 
       <bean class="org.apache.commons.httpclient.UsernamePasswordCredentials"> 
        <constructor-arg value="john"/> 
        <constructor-arg value="secret"/> 
       </bean> 
      </property> 
     </bean> 
    </property> 
</bean> 

Nous avons été en mesure de configurer l'application par programme, mais cette configuration n'a pas été possible de « transférer » à une configuration XML Spring parce que certains organismes de normalisation n'utilisent le format Spring attend. (HttpState.setCredentials (...) prend deux paramètres). La config a été levée à partir d'un autre code client Spring-WS dans la société.

Ceci est la configuration qui fonctionne:

public List<String> getAll() { 
    List<String> carTypes = new ArrayList<String>(); 

    try { 
     Source source = new ResourceSource(request); 
     JDOMResult result = new JDOMResult(); 


     SaajSoapMessageFactory soapMessageFactory = new SaajSoapMessageFactory(MessageFactory.newInstance()); 

     WebServiceTemplate template = new WebServiceTemplate(soapMessageFactory); 

     HttpClientParams clientParams = new HttpClientParams(); 
     clientParams.setSoTimeout(60000); 
     clientParams.setConnectionManagerTimeout(60000); 
     clientParams.setAuthenticationPreemptive(true); 

     HttpClient client = new HttpClient(clientParams); 
     client.getState().setCredentials(AuthScope.ANY, 
       new UsernamePasswordCredentials("username", "password")); 

     CommonsHttpMessageSender messageSender = new CommonsHttpMessageSender(client); 

     template.setMessageSender(messageSender); 
     template.sendSourceAndReceiveToResult(SERVICE_URI, 
       source, result); 

     // Handle the XML 

    } catch (IOException e) { 
     throw new RuntimeException(e); 
    } catch (SOAPException e) { 
     throw new RuntimeException(e); 
    } 

    return carTypes; 
} 

Est-ce que quelqu'un sait comment résoudre mon problème? Chaque tutoriel que j'ai vu là-bas répertorie la première configuration. Il semble que quand je mets les informations d'identification sur l'objet messageSender, ils sont tout simplement ignorés ...

Répondre

1

Comment distinguez-vous ces:

<constructor-arg value="john"/> 
<constructor-arg value="secret"/> 

essayer et de le remplacer par ceci:

<property name="userName" value="john" /> 
<property name="password" value="secret" /> 

J'espère que ça aide.

+0

Quand il est spécifié comme ci-dessus, Spring distingue arguments du constructeur par ordre d'apparition. La notation basculerait seulement entre la définition des attributs par le constructeur et leur définition par l'accesseur. J'ai peur, cela ne changera rien. –

2

Remplacer HttpClient avec un constructeur qui prend les paramètres et fil à travers Spring en utilisant constructeur-args

public MyHttpClient(HttpClientParams params, UsernamePasswordCredentials usernamePasswordCredentials) { 
     super(params);   
     getState().setCredentials(AuthScope.ANY, usernamePasswordCredentials); 
    } 
0

Si vous utilisez un defaultHttpClient comme vous êtes dans votre exemple, utilisez la méthode afterPropertiesSet sur votre HTTPMessageSender et que devrait résoudre votre problème en appliquant les informations d'identification correctement

0

au début, nous mettions dans notre projet des informations d'identification comme celui-ci:

<bean id="authenticationEnabledCommonsHttpMessageSender" parent="commonsHttpMessageSender" 
    p:credentials-ref="clientCredentials" lazy-init="true" /> 
<bean id="clientCredentials" 
    class="org.apache.commons.httpclient.UsernamePasswordCredentials" 
    c:userName="${clientCredentials.userName}" 
    c:password="${clientCredentials.password}" 
    lazy-init="true" /> 

Ceci est notre option de cridentials activée. Un problème est survenu pendant que nous définissons des informations d'identification de ce type. Si le serveur auquel nous envoyons un message (implicitement Axis) n'a pas d'informations d'identification de mot de passe, nous recevons une exception "Non autorisé". Parce que, quand nous tracons vie TCPMon, nous avons réalisé que la chaîne "nom d'utilisateur: mot de passe:" a été envoyée, car vous pouvez voir le nom d'utilisateur et le mot de passe n'ont aucune valeur.

Après que nous fixons les pouvoirs comme ça:

public Message sendRequest(OutgoingRequest message, MessageHeaders headers, 
         EndpointInfoProvider endpointInfoProvider, 
         WebServiceMessageCallback requestCallback){ 
    Assert.notNull(endpointInfoProvider, "Destination provider is required!"); 
    final Credentials credentials = endpointInfoProvider.getCredentials(); 
    URI destinationUri = endpointInfoProvider.getDestination(); 
    for (WebServiceMessageSender messageSender : webServiceTemplate.getMessageSenders()) { 
     if (messageSender instanceof CommonsHttpMessageSender) { 
      HttpClient httpClient = ((CommonsHttpMessageSender) messageSender).getHttpClient(); 
      httpClient.getState().setCredentials(
        new AuthScope(destinationUri.getHost(), 
          destinationUri.getPort(), AuthScope.ANY_REALM, 
          AuthScope.ANY_SCHEME), credentials 
      ); 
      httpClient.getParams().setAuthenticationPreemptive(true); 
      ((CommonsHttpMessageSender) messageSender) 
        .setConnectionTimeout(endpointInfoProvider 
          .getTimeOutDuration()); 
     } 
    } 

Et les GetCredentials methos est:

@Override 
public Credentials getCredentials(){ 
    if (credentials != null) { 
     return credentials; 
    } 
    String username = parameterService.usernameFor(getServiceName()); 
    String password = parameterService.passwordFor(getServiceName()); 
    if (username == null && password == null) { 
     return null; 
    } 
    credentials = new UsernamePasswordCredentials(username, password); 
    return credentials; 
}