2015-12-11 8 views
1

Я использую Apache Camel для доступа к веб-сервису и возникла странная проблема с вызовом .NET-сервиса .NET.Код ответа 302 о доступе к правильному URL-адресу с Apache Camel

Это запрос POST посланный Camel:

ID: 1 
Address: http://<domainName>/<pathToService>.asmx 
Encoding: UTF-8 
Http-Method: POST 
Content-Type: text/xml 
Headers: {Accept=[*/*], breadcrumbId=[ID-someId-1449849054155-0-1], SOAPAction=["http://<someNamespace>/<SoapActionName>"]} 
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body>/soap:Body></soap:Envelope> 

Вот ответ:

ID: 1 
Response-Code: 302 
Encoding: UTF-8 
Content-Type: text/html; charset=utf-8 
Headers: {Cache-Control=[private], Content-Length=[223], content-type=[text/html; charset=utf-8], Location=[/<somePath>/CustomError.htm?aspxerrorpath=/<pathToService>.asmx], Persistent-Auth=[true], Server=[Microsoft-IIS/7.5], X-AspNet-Version=[4.0.30319], X-Powered-By=[ASP.NET], X-UA-Compatible=[IE=7]} 
Payload: <html><head><title>Object moved</title></head></html> 

Когда я прошу "HTTP: // Домена/pathToService" в браузере, я вижу правильный ответ.

Когда я прошу "HTTP: // Домена/pathToService .asmx WSDL" Я получаю файл WSDL.

Если изменить SoapActionName к неправильному значению Я получаю

"java.lang.IllegalArgumentException: Can't find the BindingOperationInfo with operation name ..." 

это правильное поведение, конечно, тоже.

Я предполагаю, что мне нужно настроить Camel, чтобы он мог работать с веб-сервисом .NET.

Но как?

конфигурации Camel (все в Spring DSL):

<?xml version="1.0" encoding="UTF-8"?> 
    <beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:cxf="http://camel.apache.org/schema/cxf" 
    xmlns:http="http://cxf.apache.org/transports/http/configuration" 
    xmlns:sec="http://cxf.apache.org/configuration/security" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 

http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd 
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd 
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd 
http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd"> 

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/> 

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

<bean id="exceptionHandler" class="...ExceptionHandler"/> 

<cxf:cxfEndpoint id="wsEndpoint" 
       address="${ws.host}/service.asmx" 
       serviceClass="pathToServiceClass" 
       loggingFeatureEnabled="true" 
       endpointName="endpointName"> 
    <cxf:outInterceptors> 
     <ref bean="loggingOutInterceptor"/> 
    </cxf:outInterceptors> 
    <cxf:inInterceptors> 
     <ref bean="loggingInInterceptor"/> 
    </cxf:inInterceptors> 
    <cxf:properties> 
     <entry key="dataFormat" value="POJO"/> 
    </cxf:properties> 
</cxf:cxfEndpoint> 

<http:conduit name="{serviceClass}endpointName.http-conduit"> 
    <http:authorization> 
     <sec:UserName>domain\username</sec:UserName> 
     <sec:Password>password</sec:Password> 
     <sec:AuthorizationType>NTLM</sec:AuthorizationType> 
    </http:authorization> 
</http:conduit> 

<camelContext xmlns="http://camel.apache.org/schema/spring"> 

    <route id="mainRoute"> 
     <from uri="file://inbox"/> 
     <setHeader headerName="operationName"> 
      <constant>AcquireTicket</constant> 
     </setHeader> 
     <to uri="cxf:bean:wsEndpoint" pattern="InOut"/> 
     <onException> 
      <exception>java.lang.Exception</exception> 
      <process ref="exceptionHandler"/> 
     </onException> 
     <to uri="log:mylog?Level=INFO"/> 
    </route> 
</camelContext> 

Я призываю верблюд с JUnit:

@Test 
public void testWebservice() throws Exception { 
    ... 
    forming request 
    ... 

    context.getRouteDefinition("mainRoute") 
      .adviceWith(context, new AdviceWithRouteBuilder() { 
       @Override 
       public void configure() throws Exception { 
        replaceFromWith("direct:in"); 
       } 
      }); 
    context.start(); 


    ProducerTemplate template = context.createProducerTemplate(); 
    template.sendBody("direct:in",request); 
} 

Я пытался использовать запрос веб-сервиса без Camel, с Apache HttpClient :

DefaultHttpClient httpClient = new DefaultHttpClient(); 
    httpClient.getAuthSchemes().register(AuthPolicy.NTLM,new JCIFSNTLMSchemeFactory()); 
    httpClient.getAuthSchemes().register(AuthPolicy.SPNEGO,new JCIFSNTLMSchemeFactory()); 
    CredentialsProvider credsProvider = new BasicCredentialsProvider(); 
    NTCredentials ntCredentials = new NTCredentials(USERNAME, PASSWORD, 
      InetAddress.getLocalHost().getHostName(), DOMAIN); 
    HttpHost target = new HttpHost(HOST,80,"http"); 
    credsProvider.setCredentials(new AuthScope(target.getHostName(), target.getPort(), 
      AuthScope.ANY_REALM, "NTLM"), ntCredentials); 
    httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, ntCredentials); 

    HttpPost post = new HttpPost(URL); 

    post.addHeader("SOAPAction", SOAP_ACTION); 
    post.addHeader("Content-Type",CONTENT_TYPE); 
    post.addHeader("Accept-Encoding",ACCEPT_ENCODING); 
    HttpEntity httpEntity = new StringEntity(getShortText()); 
    post.setEntity(httpEntity); 

    HttpResponse response = httpClient.execute(post); 

Существует последний (3 из 3 запросов NTLM) запрос POST, созданный Camel:

POST /<pathToService>.asmx HTTP/1.1 
    Content-Type: text/xml; charset=UTF-8 
    Accept: */* 
    SOAPAction:<someNamespace>/<SoapActionName> 
    User-Agent: Apache CXF 3.1.4 
    Cache-Control: no-cache 
    Pragma: no-cache 
    Host: localhost:8013 
    Connection: keep-alive 
    Content-Length: 269 
    Authorization: NTLM <Token> 

Существует последний (3 из 3 запросов NTLM) запрос POST создан с указанным кодом с помощью Apache HTTPClient:

POST /<pathToService>.asmx HTTP/1.1 
    Content-Type: text/xml; charset=utf-8 
    Accept-Encoding: gzip,deflate 
    SOAPAction:<someNamespace>/<SoapActionName> 
    User-Agent: Apache-HttpClient/4.1.1 (java 1.5) 

    Host: localhost:8013 
    Connection: Keep-Alive 
    Content-Length: 269 
    Authorization: NTLM <Token> 

Оба запроса выглядит равен мне, но IIS ответа для запроса верблюд HTTP 302 и ответ IIS для Apache HTTPClient является HTTP 200.

хоста локальный: 8013, потому что я использую слушатель для анализа HTTP трафика , что слушатель направляет все запросы на удаленный сервер.

ответ

0

Поскольку ваш браузер может следовать перенаправлению 302 из заголовка местоположения.

Ответ, который вы получаете, - это HTTP 302, который перенаправляется на основе заголовка местоположения. Поэтому вам нужно сказать, что Camel следует за 302 и получает URI из заголовка местоположения.

+0

Благодарим за отзыв. Проблема в том, что я использую правильное местоположение. –

+0

Я добавил новую информацию в свой вопрос, пожалуйста, посмотрите на нее. –

+0

Можете ли вы показать нам свой код верблюда? –

0

Решение:

  1. Добавить <http:client/> элемент <http:conduit/>. Мой пример:

    <http:conduit name="*.http-conduit"> 
        <http:client 
         AllowChunking="false" 
         MaxRetransmits="11" 
         Connection="Keep-Alive" 
         ReceiveTimeout="30000" 
         CacheControl="No-Cache" 
        /> 
        <http:authorization> 
         <sec:UserName>domain\username</sec:UserName> 
         <sec:Password>password</sec:Password> 
         <sec:AuthorizationType>NTLM</sec:AuthorizationType> 
        </http:authorization> 
    </http:conduit> 
    
  2. Force JRE использовать свойства Camel. Мой пример:

2,1 Создать класс, который изменяет параметр авторизации NTLM в конструкторе:

public class NTLMCallbackHelper { 

public NTLMCallbackHelper() { 
    NTLMAuthenticationCallback.setNTLMAuthenticationCallback(
      new NTLMAuthenticationCallback() { 
       @Override 
       public boolean isTrustedSite(URL url) { 
        return false; 
       } 
      } 
    ); 
} 

2,2 Добавить компонент в контекст приложения перед любой CxF фасоли:

<bean id = "NTLMCallbackHelper" class="my.package.NTLMCallbackHelper"/> 

С помощью этого решения Я получил код ответа HTTP 200 из IIS.