URLConnection不遵循redirect

我不明白为什么Java的HttpURLConnection不遵循redirect。 我使用下面的代码来获取此页面 :

 import java.net.URL; import java.net.HttpURLConnection; import java.io.InputStream; public class Tester { public static void main(String argv[]) throws Exception{ InputStream is = null; try { String bitlyUrl = "http://bit.ly/4hW294"; URL resourceUrl = new URL(bitlyUrl); HttpURLConnection conn = (HttpURLConnection)resourceUrl.openConnection(); conn.setConnectTimeout(15000); conn.setReadTimeout(15000); conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; ru; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729)"); conn.connect(); is = conn.getInputStream(); String res = conn.getURL().toString(); if (res.toLowerCase().contains("bit.ly")) System.out.println("bit.ly is after resolving: "+res); } catch (Exception e) { System.out.println("error happened: "+e.toString()); } finally { if (is != null) is.close(); } } } 

此外,我得到以下回应(这似乎是绝对正确的!):

 GET /4hW294 HTTP/1.1 Host: bit.ly Connection: Keep-Alive User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; ru-RU; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729) HTTP/1.1 301 Moved Server: nginx/0.7.42 Date: Thu, 10 Dec 2009 20:28:44 GMT Content-Type: text/html; charset=utf-8 Connection: keep-alive Location: https://www.myganocafe.com/CafeMacy MIME-Version: 1.0 Content-Length: 297 

不幸的是, resvariables包含相同的URL和stream包含以下内容(显然,Java的HttpURLConnection不遵循redirect!):

 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <HTML> <HEAD> <TITLE>Moved</TITLE> </HEAD> <BODY> <H2>Moved</H2> <A HREF="https://www.myganocafe.com/CafeMacy">The requested URL has moved here.</A> <P ALIGN=RIGHT><SMALL><I>AOLserver/4.5.1 on http://127.0.0.1:7400</I></SMALL></P> </BODY> </HTML> 

我不认为它会自动从HTTPredirect到HTTPS(反之亦然)。

即使我们知道它反映了HTTP,但从HTTP协议的angular度来看,HTTPS只是一些其他完全不同的未知协议。 在没有用户批准的情况下遵循redirect是不安全的。

例如,假设应用程序设置为自动执行客户端身份validation。 用户希望匿名浏览,因为他使用的是HTTP。 但是如果他的客户端没有询问HTTPS,他的身份就会显示给服务器。

devise HttpURLConnection不会自动从HTTPredirect到HTTPS(反之亦然)。 redirect后可能会有严重的安全后果。

正如erickson指出的,假设应用程序被设置为自动执行客户端身份validation。 用户希望匿名浏览,因为他使用的是HTTP。 但是如果他的客户端没有询问HTTPS,他的身份就会显示给服务器。

有了这个了解,这里的代码将遵循redirect。

  URL resourceUrl, base, next; HttpURLConnection conn; String location; ... while (true) { resourceUrl = new URL(url); conn = (HttpURLConnection) resourceUrl.openConnection(); conn.setConnectTimeout(15000); conn.setReadTimeout(15000); conn.setInstanceFollowRedirects(false); // Make the logic below easier to detect redirections conn.setRequestProperty("User-Agent", "Mozilla/5.0..."); switch (conn.getResponseCode()) { case HttpURLConnection.HTTP_MOVED_PERM: case HttpURLConnection.HTTP_MOVED_TEMP: location = conn.getHeaderField("Location"); location = URLDecoder.decode(location, "UTF-8"); base = new URL(url); next = new URL(base, location); // Deal with relative URLs url = next.toExternalForm(); continue; } break; } is = conn.openStream(); ... 

有什么叫HttpURLConnection.setFollowRedirects(false)的任何机会?

你可以随时打电话

 conn.setInstanceFollowRedirects(true); 

如果你想确保你不会影响应用程序的其他行为。

正如上面你们中的一些人所提到的,setFollowRedirect和setInstanceFollowRedirects只在redirect的协议相同时自动工作。 即从http到http和https到https。

setFolloRedirect处于类级别,并为url连接的所有实例设置此属性,而setInstanceFollowRedirects仅用于给定实例。 这样我们可以对不同的实例有不同的行为。

我在这里find一个很好的例子http://www.mkyong.com/java/java-httpurlconnection-follow-redirect-example/

它是正确的响应,但你知道必须从响应中获取新的位置,并将其用作url

HTTPUrlConnection不负责处理对象的响应。 这是预期的性能,它抓住了所请求的URL的内容。 function的用户由您来解释响应。 没有规范就无法读懂开发者的意图。