2008-09-22 94 views
2

我們正在努力配置我們的Web應用程序,以便能夠通過Spring WS與Web服務進行連接。我們試圖使用客戶端Spring-WS文檔中的示例,但最終得到了一個WebServiceTransportException。 XML配置看起來是這樣的:WebServiceTransportException:未授權[401]在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> 

我們已經能夠以編程方式配置的應用,但是這種配置是不可能的「轉移」到Spring的XML配置,因爲一些制定者並沒有使用格式春天的期望。 (HttpState.setCredentials(...)需要兩個參數)。該配置從公司的其他Spring-WS客戶端代碼中解脫出來。

這是工作的配置:

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

有誰知道如何解決我的問題?我看到的每個教程都列出了第一個配置。看來,當我設置messageSender,和對象的憑據,他們只是忽略...

回答

1

你如何區分這些:

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

試着和這個替換:

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

希望它有幫助。

+0

當如上述規定,由春季出現的順序區分構造函數的參數。 表示法只能在通過構造函數設置屬性和通過訪問器設置屬性之間進行切換。恐怕,這不會改變任何事情。 – 2013-05-03 14:27:23

2

覆蓋HttpClient的一個構造函數,通過彈簧使用構造-ARGS

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

如果您使用的是defaultHttpClient你是在你的榜樣,你的HTTPMessageSender和使用的afterPropertiesSet方法採用的參數和線應該在我們的項目像這樣正確

0

應用憑據起初,我們設置憑據解決您的問題:

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

這是我們的cridentials啓用選項。當我們設置這樣的憑據時出現問題。 如果我們發送消息的服務器(有Axis impl)沒有獲得用戶名密碼憑據,我們會得到「未授權」異常。因爲當我們跟蹤TCPMon時,我們意識到「username:password:」字符串已被髮送,因爲您可以看到用戶名和密碼沒有任何價值。

之後,我們設置這樣的憑據:

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()); 
     } 
    } 

而且getCredentials methos是:

@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; 
}