5

インターネットとイントラネットへの個別の接続を確立するために2つの異なるプロキシを使用する必要があるJavaWebサービスアプリケーション(JAX-WSを使用)を開発しています。解決策として、インターネットまたはイントラネット用のjava.net.Proxyインスタンス(HTTPタイプ)を返す独自のjava.net.ProxySelectorを作成しようとしました。

小さなテストアプリケーションで、 URL.openConnection()を介してWebページをダウンロードしようとしましたが、デフォルトのProxySelectorを自分のものに置き換える前に。ただし、例外が発生します。

java.net.SocketException:不明なプロキシタイプ:java.net.SocksSocketImpl.connect(SocksSocketImpl.java:370)のHTTP java.net.Socket.connect(Socket.java:519)のjava.net.Socket.connect( Socket.java:469)at sun.net.NetworkClient.doConnect(NetworkClient.java:163)at sun.net.www.http.HttpClient.openServer(HttpClient.java:394)at sun.net.www.http.HttpClient .openServer(HttpClient.java:529)at sun.net.www.http.HttpClient。(HttpClient.java:233)at sun.net.www.http.HttpClient.New(HttpClient.java:306)at sun.net .www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:844)at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:792)at sun.net.www.protocol.http.HttpURLConnection .connect(HttpURLConnection.java:703)(sun.net.www.protocol.http)。HttpURLConnection.getInputStream(HttpURLConnection.java:1026)at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:373)at norman.test.ProxyTest.conntectToRmViaProxy(ProxyTest.java:42)at norman.test.ProxyTest.main(ProxyTest .java:65)

  1. 質問:「ProxySelectorがHTTPプロキシのみを返すのに、なぜアプリケーションがSOCKSを介して接続を確立しようとするのですか?」

2質問:「接続ごとに異なるプロキシを定義するための代替手段はありますか?」

これは私のProxySelectorです:

public class OwnProxySelector extends ProxySelector {
private Proxy intranetProxy;
private Proxy extranetProxy;
private Proxy directConnection = Proxy.NO_PROXY;
private URI intranetAddress;
private URI extranetAddress;

/* (non-Javadoc)
 * @see java.net.ProxySelector#connectFailed(java.net.URI, java.net.SocketAddress, java.io.IOException)
 */
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
    // Nothing to do
}

/* (non-Javadoc)
 * @see java.net.ProxySelector#select(java.net.URI)
 */
public List select(URI uri) {
    ArrayList<Proxy> result = new ArrayList<Proxy>();

    if(intranetAddress.getHost().equals(uri.getHost()) && intranetAddress.getPort()==uri.getPort()){
        result.add(intranetProxy);
        System.out.println("Adding intranet Proxy!");
    }
    else if(extranetAddress.getHost().equals(uri.getHost()) && extranetAddress.getPort()==uri.getPort()){
        result.add(extranetProxy);
        System.out.println("Adding extranet Proxy!");
    }
    else{
        result.add(directConnection);
        System.out.println("Adding direct connection!");
    }

    return result;
}

public void setIntranetProxy(String proxyAddress, int proxyPort){
    if(proxyAddress==null || proxyAddress.isEmpty()){
        intranetProxy = Proxy.NO_PROXY;
    }
    else{
        SocketAddress address = new InetSocketAddress(proxyAddress, proxyPort);
        intranetProxy = new Proxy(Proxy.Type.HTTP, address);
    }
}

public void setExtranetProxy(String proxyAddress, int proxyPort){
    if(proxyAddress==null || proxyAddress.isEmpty()){
        extranetProxy = Proxy.NO_PROXY;
    }
    else{
        SocketAddress address = new InetSocketAddress(proxyAddress, proxyPort);
        extranetProxy = new Proxy(Proxy.Type.HTTP, address);
    }
}

public void clearIntranetProxy(){
    intranetProxy = Proxy.NO_PROXY;
}

public void clearExtranetProxy(){
    extranetProxy = Proxy.NO_PROXY;
}

public void setIntranetAddress(String address) throws URISyntaxException{
    intranetAddress = new URI(address);
}

public void setExtranetAddress(String address) throws URISyntaxException{
    extranetAddress = new URI(address);
}
}

これはテストクラスです:

public class ProxyTest {
OwnProxySelector ownSelector = new OwnProxySelector();

public ProxyTest(){
    ownSelector.setIntranetProxy("intranet.proxy", 8123);
    try {
        ownSelector.setIntranetAddress("http://intranet:80");
    } catch (URISyntaxException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    ownSelector.setExtranetProxy("", 0);
    try {
        ownSelector.setExtranetAddress("http://www.example.com:80");
    } catch (URISyntaxException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    ProxySelector.setDefault(ownSelector);
}

public void conntectToRmViaProxy(boolean internal, String connectAddress){
    try {
        URL url = new URL(connectAddress);

        HttpURLConnection conn = (HttpURLConnection)url.openConnection();

        conn.setRequestMethod("GET");
          if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            System.out.println(conn.getResponseMessage());
          }
          else{
              BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
              int tmp = reader.read();
              while(tmp != -1){
                  System.out.print((char)tmp);
                  tmp = reader.read();
              }
          }

    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public static void main(String[] args){
    ProxyTest proxyText = new ProxyTest();
    proxyText.conntectToRmViaProxy(true, "http://intranet:80");
}
}
4

1 に答える 1

6

わかりました、私は問題を見つけました。

要求されたURLにポートが含まれていない場合、HttpURLConnectionはOwnProxySelector.select()を2回実行しました。

最初に、HttpURLConnectionは、「http」のスキームを使用して、ポートを使用せずにURIを使用してselect()を呼び出しました。select()は、ホストアドレスとポートがintranetAddressまたはextranetAddressのどちらに相当するかを確認します。ポートが指定されていないため、これは一致しませんでした。したがって、selectは直接接続のプロキシを返します。

2番目のHttpURLConnectionは、「ソケット」とポート80のスキームを使用してURIを使用してselect()を呼び出しました。したがって、select()はホストアドレスとポートをチェックしますが、スキームはチェックしないため、HTTPプロキシを返しました。

これがOwnProxySelectorの修正バージョンです。スキームをチェックし、ポートがURIで指定されていない場合は、HTTPまたはHTTPSのデフォルトポートを設定します。また、HTTPまたはHTTPSスキームが指定されていない場合は、Java標準のProxySelectorに問い合わせます。

public class OwnProxySelector extends ProxySelector {
private ProxySelector defaultProxySelector;
private Proxy intranetProxy;
private Proxy extranetProxy;
private Proxy directConnection = Proxy.NO_PROXY;
private URI intranetAddress;
private URI extranetAddress;


public OwnProxySelector(ProxySelector defaultProxySelector){
    this.defaultProxySelector = defaultProxySelector;
}

/* (non-Javadoc)
 * @see java.net.ProxySelector#connectFailed(java.net.URI, java.net.SocketAddress, java.io.IOException)
 */
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
    // Nothing to do
}

/* (non-Javadoc)
 * @see java.net.ProxySelector#select(java.net.URI)
 */
public List select(URI uri) {
    ArrayList<Proxy> result = new ArrayList<Proxy>();
    
    if(uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equalsIgnoreCase("https")){
        int uriPort = uri.getPort();
        
        // set default http and https ports if port is not given in URI
        if(uriPort<1){
            if(uri.getScheme().equalsIgnoreCase("http")){
                uriPort = 80;
            }
            else if(uri.getScheme().equalsIgnoreCase("https")){
                uriPort = 443;
            }
        }
        
        if(intranetAddress.getHost().equals(uri.getHost()) && intranetAddress.getPort()==uriPort){
            result.add(intranetProxy);
            System.out.println("Adding intranet Proxy!");
        }
        else if(extranetAddress.getHost().equals(uri.getHost()) && extranetAddress.getPort()==uriPort){
            result.add(extranetProxy);
            System.out.println("Adding extranet Proxy!");
        }
    }
    
    if(result.isEmpty()){
        List<Proxy> defaultResult = defaultProxySelector.select(uri);
        if(defaultResult!=null && !defaultResult.isEmpty()){
            result.addAll(defaultResult);
            System.out.println("Adding Proxis from default selector.");
        }
        else{
            result.add(directConnection);
            System.out.println("Adding direct connection, because requested URI does not match any Proxy");
        }
    }
    
    return result;
}

public void setIntranetProxy(String proxyAddress, int proxyPort){
    if(proxyAddress==null || proxyAddress.isEmpty()){
        intranetProxy = Proxy.NO_PROXY;
    }
    else{
        SocketAddress address = new InetSocketAddress(proxyAddress, proxyPort);
        intranetProxy = new Proxy(Proxy.Type.HTTP, address);
    }
}

public void setExtranetProxy(String proxyAddress, int proxyPort){
    if(proxyAddress==null || proxyAddress.isEmpty()){
        extranetProxy = Proxy.NO_PROXY;
    }
    else{
        SocketAddress address = new InetSocketAddress(proxyAddress, proxyPort);
        extranetProxy = new Proxy(Proxy.Type.HTTP, address);
    }
}

public void clearIntranetProxy(){
    intranetProxy = Proxy.NO_PROXY;
}

public void clearExtranetProxy(){
    extranetProxy = Proxy.NO_PROXY;
}

public void setIntranetAddress(String address) throws URISyntaxException{
    intranetAddress = new URI(address);
}

public void setExtranetAddress(String address) throws URISyntaxException{
    extranetAddress = new URI(address);
}

}

しかし、HttpURLConnectionが最初の呼び出しから直接接続プロキシを取得したときにselect()の2番目の呼び出しを行ったことは私には不思議です。

于 2010-03-19T16:21:32.697 に答える