2017-08-30 74 views
8

在我的項目SSL錯誤,我有以下項目結構:JAX-WS Axis2的代理在使用的ProxySelector

我有一個生產WAR文件,可以部署在Tomcat應用服務器中的模塊。該模塊具有依賴於Axis2的庫:

<dependency> 
     <groupId>org.apache.axis2</groupId> 
     <artifactId>axis2</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.axis2</groupId> 
     <artifactId>axis2-transport-http</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.axis2</groupId> 
     <artifactId>axis2-webapp</artifactId> 
     <type>war</type> 
    </dependency> 

而這個類包含在WEB-INF下的conf文件夾的axis2.xml文件。

現在這個模塊依賴於一個單元模塊,它有一個jar包的類型。

在我的網絡模塊

現在,在我的存根代碼,我下面的代碼:

GazelleObjectValidator.getInstance()validateObject();

XcpdValidationService是jar模塊(依賴項)中的一個類,此方法通過SSL調用外部Web服務並使用代理。

此Web服務客戶端是通過JAX WS RI

產生,但是這個類不從父模塊使用axis2.xml配置和使用它自己的軸配置,是默認的,我的代理是沒有配置...

@WebEndpoint(name = "GazelleObjectValidatorPort") 
public GazelleObjectValidator getGazelleObjectValidatorPort() { 
    return super.getPort(new QName("http://ws.validator.sch.gazelle.ihe.net/", "GazelleObjectValidatorPort"), GazelleObjectValidator.class); 
} 

的方法本身是這樣的:

@WebMethod 
@WebResult(name = "validationResult", targetNamespace = "") 
@RequestWrapper(localName = "validateObject", targetNamespace = "http://ws.validator.sch.gazelle.ihe.net/", className = "net.ihe.gazelle.schematron.ValidateObject") 
@ResponseWrapper(localName = "validateObjectResponse", targetNamespace = "http://ws.validator.sch.gazelle.ihe.net/", className = "net.ihe.gazelle.schematron.ValidateObjectResponse") 
public String validateObject(
    @WebParam(name = "base64ObjectToValidate", targetNamespace = "") 
    String base64ObjectToValidate, 
    @WebParam(name = "xmlReferencedStandard", targetNamespace = "") 
    String xmlReferencedStandard, 
    @WebParam(name = "xmlMetadata", targetNamespace = "") 
    String xmlMetadata) 
    throws SOAPException_Exception 
; 

我GazelleObjectValidatorService由以下插件生成:

<plugin> 
    <groupId>org.apache.axis2</groupId> 
    <artifactId>axis2-aar-maven-plugin</artifactId> 
    <version>${axis2.version}</version> 
    <extensions>true</extensions> 
    <executions> 
     <execution> 
      <id>package-aar</id> 
      <phase>prepare-package</phase> 
      <goals> 
       <goal>aar</goal> 
      </goals> 
     </execution> 
    </executions> 
    <configuration> 
     <fileSets> 
      <fileSet> 
      <directory>${project.basedir}/src/main/resources/wsdl</directory> 
       <outputDirectory>META-INF</outputDirectory> 
       <includes> 
        <include>**/*.xsd</include> 
       </includes> 
      </fileSet> 
     </fileSets> 
     <servicesXmlFile>${project.build.outputDirectory}/axis2/services.xml</servicesXmlFile> 
     <wsdlFile>${project.build.outputDirectory}/wsdl/ClientConnectorService.wsdl</wsdlFile> 
    </configuration> 
</plugin> 

我試圖重寫我的axis2.xml配置transportSender用我自己的定義MyCommonsHttpTransportSender:

<transportSender name="http" 
       class="eu.epsos.pt.cc.MyCommonsHTTPTransportSender"> 
    <parameter name="PROTOCOL">HTTP/1.1</parameter> 
    <parameter name="Transfer-Encoding">chunked</parameter> 

<transportSender name="https" 
       class="eu.epsos.pt.cc.MyCommonsHTTPTransportSender"> 
    <parameter name="PROTOCOL">HTTP/1.1</parameter> 
    <parameter name="Transfer-Encoding">chunked</parameter> 
</transportSender> 

知道該代理。

但不幸的是,由於Web服務客戶端在作爲戰爭依賴的jar內部,它似乎並不使用我的axis2.xml配置,而是使用它自己的軸配置,它不知道代理。

這導致以下錯誤,你清楚地看到,它使用默認CommonsHTTPTransportSender並因此引發錯誤:

Caused by: java.net.ConnectException: Connection refused (Connection refused) 
    at java.net.PlainSocketImpl.socketConnect(Native Method) 
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) 
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) 
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) 
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) 
    at java.net.Socket.connect(Socket.java:589) 
    at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:668) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.apache.commons.httpclient.protocol.ReflectionSocketFactory.createSocket(ReflectionSocketFactory.java:140) 
    at org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory.createSocket(SSLProtocolSocketFactory.java:130) 
    at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707) 
    at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361) 
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387) 
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171) 
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) 
    at org.apache.axis2.transport.http.AbstractHTTPSender.executeMethod(AbstractHTTPSender.java:621) 
    at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:193) 
    at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:75) 
    at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:404) 
    at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:231) 
    at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:443) 
    at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:406) 
    at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229) 
    at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165) 
    at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.execute(AxisInvocationController.java:578) 
    at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.doInvoke(AxisInvocationController.java:127) 
    at org.apache.axis2.jaxws.core.controller.impl.InvocationControllerImpl.invoke(InvocationControllerImpl.java:93) 
    at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:373) 
    ... 40 common frames omitted  

有沒有辦法讓孩子罐子WS客戶端使用相同的父模塊的Axis2配置(即一個可部署的戰爭和具有的axis2依賴性?)

UPDATE:

我WAR文件具有Axis2配置,從這個戰爭的源代碼,以產生服務調用wsimport,它位於父WAR中的依賴項的JAR中。該服務調用外部WebService,這發生在Axis上(儘管不使用axis2.xml配置文件,因爲該文件位於JAR的WEB-INF文件夾中。 沒有任何可能性在沒有Axis的JAR中使用外部WebService調用並僅使用JAXWS?這將解決我的問題...

+1

您是否正在使用代理選擇器,或者您只需要爲存根配置代理? – kolossus

+0

我只想知道如何爲我的存根配置代理。如果使用我的代理選擇器是可行的,那就太好了。如果有另一種方式,它也是我的一個解決方案。現在他通過套接字並忽略我的代理選擇器,因爲Axis在 –

+1

內使用HTTP客戶端我想我找到了原因:Axis不是JAX-WS的真正實現。 [根據我以前的答案](https://stackoverflow.com/q/30636982/),我們應該使用這兩種方法之一來設置安全套接字工廠(而不是'JAXWSProperties.SSL_SOCKET_FACTORY' )在我的答案。你也應該刪除你的答案,並添加任何進一步的更新問題 – kolossus

回答

2

Axis2提供了一種方便的方法to configure the HTTP Transport。所以,從你的示例代碼如下:

HttpTransportProperties.ProxyProperties proxyProperties = new HttpTransportProperties.new ProxyProperties(); 
proxyProperties.setProxyHostName("hostName"); 
proxyProperties.setProxyPort("hostPort"); 
proxyProperties.setUsername("User"); 
proxyProperties.setPassword("pw"); 
//set the properties 
objectValidatorService.getServiceClient().getOptions().setProperty(HttpConstants.PROXY, proxyProperties); 

以上,因爲你使用的股票JAX-WS實現,而不是the Axis2-specific client不會爲你工作。 根據您的堆棧跟蹤,看起來您正在連接到TLS安全端點。 There's a solution for that

我已經做了大量的研究,並且使用庫存JAX-WS無法訪問底層HTTPUrlConnection。我們有什麼,是一種方式set a custom SSLContextFactory。因此,我們首先創建一個自定義的工廠,that will connect to the proxy first

public class CustomSocketFactory extends SSLProtocolSocketFactory { 

    private static final CustomSocketFactory factory = new CustomSocketFactory(); 

    static CustomSocketFactory getSocketFactory(){ 
     return factory; 
    }  

    public CustomSocketFactory() { 
     super(); 
    } 

    @Override 
    public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) { 
     Socket socket = null; 
     try { 
      int proxyPort = 1000; 
      InetSocketAddress proxyAddr = new InetSocketAddress("proxyAddr", proxyPort); 
      Socket proxyConn = new Socket(new Proxy(Proxy.Type.SOCKS, proxyAddr)); 
      proxyConn.connect(new InetSocketAddress("endHost", 443)); 
      socket = (SSLSocket) super.createSocket(proxyConn, "proxyEndpoint", proxyPort, true); 

     } catch (IOException ex) { 

     Logger.getLogger(CustomSocketFactory.class.getName()).log(Level.SEVERE, null, ex); 
    } 
     return socket; 
    } 
} 

我們現在要註冊這個自定義套接字工廠與Apache運行的HTTPClient(軸不使用java的股票HttpURLConnection的,因爲是由您的堆棧跟蹤證明):

Protocol.registerProtocol("https",new Protocol("https", new CustomSocketFactory(), 443)); 

這隻適用於TLS連接。(但是,自定義套接字工廠也適用於非https端點)。您還需要將超時設置爲0 so we can guarantee that your overriden createSocket gets invoked

+0

感謝您的回答。但不幸的是,我的GazelleObjectValidatorService沒有getServiceClient()方法。我的GazelleObjectValidatorService是由JAX-WS RI生成的類2.2.8 –

+0

public class GazelleObjectValidatorService extends Service(javax.xml.ws.Service) –

+0

我添加了用於生成GazelleObjectValidator的插件的配置 –