使用ProxySelector

时间:2017-08-30 15:41:37

标签: ssl proxy jax-ws axis2 apache-commons-httpclient

在我的项目中,我有以下项目结构:

我有一个生成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>

我尝试使用我自己定义的MyCommonsHttpTransportSender覆盖我的axis2.xml配置中的transportSender:

<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配置,而是使用它自己的轴配置,而不是#39;了解代理。

这会导致以下错误,您会清楚地看到它使用默认的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    

有没有办法让子jar中的WS客户端使用父模块的相同axis2配置(这是一个可部署的war并具有axis2依赖?)

更新:

我的WAR文件有一个axis2配置,从这场战争的源代码中,调用一个用wsimport生成的服务,该服务位于JAR中,该JAR是父WAR的依赖关系。此服务调用外部WebService,这通过Axis发生(虽然没有使用axis2.xml配置文件,因为这个文件位于JAR的WEB-INF文件夹中。 是否有可能在没有Axis的情况下在JAR中进行外部WebService调用并仅使用JAXWS?这可以解决我的问题......

1 个答案:

答案 0 :(得分: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运行时注册此自定义套接字工厂(Axis 使用库存java HTTPUrlConnection,如堆栈跟踪所示):

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

这仅适用于TLS连接。(尽管自定义套接字工厂也适用于非https端点)。您还需要将超时设置为0 so we can guarantee that your overriden createSocket gets invoked