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
不幸的是, res
variables包含相同的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的用户由您来解释响应。 没有规范就无法读懂开发者的意图。
- 获取java.net.SocketTimeoutException:连接在android中超时
- 如何在Java中进行HTTP GET?
- 为什么你必须调用URLConnection#getInputStream才能写出URLConnection#getOutputStream?
- 从HttpURLConnection对象parsingJSON
- org.apache.http.entity.FileEntity在Android 6(棉花糖)
- 如何在HttpURLConnection上设置内容types?
- Java – 通过POST方法轻松发送HTTP参数
- HttpURLConnection.getResponseCode()在第二次调用时返回-1
- 如何在Java中发送Https Post请求