LoginSignup
50
46

More than 1 year has passed since last update.

JavaでHTTPSのサイトに認証付きプロキシ経由でアクセスしようとすると407エラー

Last updated at Posted at 2016-12-14

はじめに

Java 8 Update 111 からjava.netパッケージの HTTPS 接続の際のトンネリングに Basic 認証を使用できない設定がデフォルトになったようです。
回避するにはjdk.http.auth.tunneling.disabledSchemesに空文字列を設定する必要があるそうです。

事象

背景

Java のjava.net.HttpURLConnectionを利用して、認証付きプロキシ内の環境から https のサイトにアクセスしようとした時に、どんな方法でプロキシの認証情報を付与しても407 Proxy Authentication Requiredエラーを解消できなかった。

Sample.java
import java.util.*;
import java.net.*;

public class Sample {
        private static String PROXY_HOST = "example.proxy.com";
        private static String PROXY_PORT = "8080";
        private static String PROXY_USER = "user";
        private static String PROXY_PASSWORD = "password";

        public static void main(String[] args) throws Exception {
                String url = "https://news.google.com";
                System.setProperty("proxySet", "true");
                System.setProperty("proxyHost", PROXY_HOST);
                System.setProperty("proxyPort", PROXY_PORT);

                Authenticator.setDefault(new Authenticator() {
                        @Override
                        protected PasswordAuthentication getPasswordAuthentication() {
                                return new PasswordAuthentication(PROXY_USER, PROXY_PASSWORD.toCharArray());
                        }
                });

                HttpURLConnection urlconn = (HttpURLConnection) new URL(url).openConnection();
                urlconn.setRequestMethod("GET");
                urlconn.connect();
        }
}

現象

上記の Java コードを実行すると下記のエラーが発生する。

$ java Sample
Exception in thread "main" java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
        at sun.net.www.protocol.http.HttpURLConnection.doTunneling(HttpURLConnection.java:2124)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:183)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
        at Sample.main(Sample.java:25)

コード内での認証プロキシ設定だけでなく、下記も試しましたが結果はかわらず。

  1. Java 起動オプションに proxy の設定をする
  • 例: java -Dhttp.proxyHost="example.proxy.com" -Dhttp.proxyPort=8080 -Dhttp.proxyUser=user -Dhttp.proxyPassword=password (httpsに関しても同様に設定) Sample
  1. System デフォルトを参照するよう設定
  • 例: java -Djava.net.useSystemProxies=true Sample

環境

OS は Ubuntu 16.04、Java のバージョンは下記です。

$ java -version
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)

結論

2016/10 にリリースされた 8u111 以降から、デフォルトの設定として HTTPS 接続する際のトンネリングに Basic 認証を利用することができなくなりました。

Java 8 リリースの変更

HTTPS トンネリングの Basic 認証の無効化
一部の環境で、HTTPS プロキシ時に特定の認証スキームが不適切である場合があります。そのため、Basic 認証スキームは、デフォルトでは Oracle Java Runtime で jdk.http.auth.tunneling.disabledSchemes ネットワーク・プロパティに Basic を追加することで非アクティブ化されています。HTTPS のトンネルの設定時に Basic 認証を必要とするプロキシは、デフォルトでは成功しないようになりました。必要な場合、jdk.http.auth.tunneling.disabledSchemes ネットワーク・プロパティから Basic を削除するか、コマンド行で同じ名前のシステム・プロパティを"" (空)に設定することで、この認証スキームを再度アクティブ化できます。また、jdk.http.auth.tunneling.disabledSchemes および jdk.http.auth.proxying.disabledSchemes ネットワーク・プロパティと同じ名前のシステム・プロパティは、それぞれ HTTPS のトンネルの設定時またはプレーンな HTTP のプロキシ時に、アクティブ化されている可能性があるその他の認証スキームを無効化するために使用できます。JDK-8160838 (非公開)

英語版のリリースノートを見ると、core-libs/java.netと書いてあるので、java.netパッケージ内のクラスの機能を使って HTTPS 接続する際のデフォルトの挙動の変更だと思われます。

回避方法

  1. JVM オプションjdk.http.auth.tunneling.disabledSchemes=""を設定する。
  • 実行時: java -Djdk.http.auth.tunneling.disabledSchemes="" Sample
  • コード内: System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
  1. 他のライブラリを使う
  • Apache の HTTPClient など

補足

System.getProperty("jdk.http.auth.tunneling.disabledSchemes")を sysout してみましたが、結果はnullでした。

50
46
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
46