HTTP URL と HTTPS URL の間のリダイレクトが行われない

症状

アプレットを Sun JRE を使用したブラウザで実行している場合、HTTP URL にリダイレクトするサーバに対してアプレットが HTTP 要求を行うと、リダイレクトに失敗します。また、HTTP URL にリダイレクトするサーバに対して HTTPS 要求を行う場合も失敗します。同じアプレットが Microsoft 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){
   URLConnection conn = url.openConnection();
   InputStream is = openConnectionCheckRedirects(conn);
   ....
   is.close();
}

詳細情報

なし