Redirection between HTTP and HTTPS URLs is not followed.

Symptoms

When running an applet in a browser using the Sun JRE, if the applet makes HTTP requests to a server which redirects to an HTTPS URL, the redirection fails. It fails also in the case of making HTTPS requests to a server which redirects to an HTTP URL. The same applet runs without error in the Microsoft VM.

Cause

The issue is caused by the HTTP/HTTPS redirection policy implemented in Sun JRE; because of serious security consequences, redirection between HTTP and HTTPS is not automatically followed.

With the Microsoft VM, a security warning dialog prompts the user for consent for any redirection. Redirection occurs only if the user consents to it.

Resolution

To work around the problem, it is the application's responsibility to check the response code and recognize it as a redirect. The Location header field value can be checked for the redirect information, and then the application must decide whether or not to follow the redirect using the new protocol. For example, the following code

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

should be changed to

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();
}

Related Information

N/A