HTTP URL と HTTPS URL の間のリダイレクトが追跡されない

症状

Sun JavaTM Runtime Environment (JRETM) を使ってブラウザ内でアプレットを実行する場合、要求を HTTPS URL にリダイレクトするサーバーに対してアプレットが HTTP 要求を行うと、そのリダイレクションは失敗します。また、HTTP URL に要求をリダイレクトするサーバーに対して HTTPS 要求を行う場合もリダイレクションが失敗する。同じアプレットが、Microsoft Virtual Machine (VM) では何のエラーもなく実行されます。

原因

この問題の原因は、Sun JRE に実装されている HTTP または HTTPS リダイレクションポリシーにあります。HTTP と HTTPS 間のリダイレクションはセキュリティー上の重大な結果につながるため、自動的には追跡されません。

Microsoft VM を使ってブラウザ内でアプレットを実行すると、セキュリティー警告ダイアログがユーザーにリダイレクションへの同意を求めます。ユーザーがそれに同意しなかった場合はリダイレクションが失敗します。

解決方法

ブラウザ内でアプレットを実行するアプリケーションは、その応答コードをチェックし、それをリダイレクションとして認識する必要があります。Location ヘッダーフィールド値はリダイレクト情報としてチェック可能であるため、アプリケーションは新しいプロトコルを使用してリダイレクトを行うかどうかを決定する必要があります。たとえば、アプリケーション内で次のコードを使用できます。

public void makeConnection(URL url)
{
URLConnection conn = url.openConnection();
InputStream is = conn.getInputStream();
....
is.close();
}

上記のコードは次のコードに変更するようにしてください。

private InputStream openConnectionCheckRedirects(URLConnection c) throws IOException
{

   boolean redir;
   int redirects = 0;
   InputStream in = null;
   do
   {
      if (c instanceof HttpURLConnection)

      {
         ((HttpURLConnection) c).setInstanceFollowRedirects(false);
      }
      // We want to open the input stream before getting headers
      // because getHeaderField() et al swallow IOExceptions.
      in = c.getInputStream();
      redir = false;
      if (c instanceof HttpURLConnection)
      {
         HttpURLConnection http = (HttpURLConnection) c;
         int stat = http.getResponseCode();
         if (stat >= 300 && stat <= 307 && stat != 306 &&
            stat != HttpURLConnection.HTTP_NOT_MODIFIED)
         {
            URL base = http.getURL();
            String loc = http.getHeaderField("Location");
            URL target = null;
            if (loc != null)
            {
               target = new URL(base, loc);
            }
            http.disconnect();
        
   // Redirection should be allowed only for HTTP and HTTPS
            // and should be limited to 5 redirections at most.
            if (target == null || !(target.getProtocol().equals("http")
               || target.getProtocol().equals("https"))
               || redirects >= 5)
            {

               throw new SecurityException("illegal URL redirect");
            }

            redir = true;
            c = target.openConnection();
            redirects++;
         }
      }
   }
   while (redir);
   return in;
}

public void makeConnection(URL url){
try{
   URLConnection conn = url.openConnection();
   InputStream is = openConnectionCheckRedirects(conn);
   ....
   is.close();
}catch (IOException e){ } }

詳細情報

なし