HttpUrlConnection 出现 503 错误,但网站在浏览器上加载
Getting 503 error with HttpUrlConnection but site loading on browser
url = "https://www.lmcu.org/?__cf_chl_jschl_tk__=9c114404052361017d9cfe1247981e24813649c7-1592389426-0-AfP07ha5TxZHf64q5tb5nJf9BJguC4U553-OJzJWivTqfgwYLqUODkXj-XsOjZTwpC71ROxHWx4Xhdp2S0LgAVlKgXpy7KWOex7lkoGBm8mNpBsCeJapdYNWty-X2oHE6gp_TtMfH0dcBabvWr_mXV1djsVR_IGlYJA-wCuZpPTGOozyzN9TFwjMPxU-3o6BIUxTh6DDcHmJ_Bw48EYKGpq6n57bVdeLezEs9PduataW1JUcF4GqLE2EHiUxWGubtS8YgcxkkGin4zitHXENMbFi1kMhxI77LsORzKyhkAD1OkG8fGmV--Cgd3EpxWHtHD5vpoIFFIwX0uGQywPnegs";
HttpURLConnection connection = pingHttpUrl(url);
responseCode = connection.getResponseCode();
public HttpURLConnection pingHttpUrl(String url) throws IOException {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76 Safari/537.36");
conn.setConnectTimeout(2000);
conn.setInstanceFollowRedirects(false);
conn.setReadTimeout(10000);
conn.connect();
Thread.sleep(1000);
} catch (Exception e) {
logger.error("Caught exception : {}", e.getMessage());
throw new IOException();
}
return conn;
}
这给出的响应代码为 503。但该网站正在浏览器上正确加载。这可能是什么问题?
问题出在请求的 header 上。我发现这个托管在 cloudflare 上的解决方案需要两个 header 才行,否则你会收到 503
响应:
- User-Agent - 你的header指定了chrome版本76,显然服务器有这有问题。我在这个
User-Agent
值上取得了成功:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36
- cookie - 我发现需要设置 cookie 值
cf_clearance
,并且可能在第一次请求时返回其他 set-cookie
值.此值与 cloudflare 对隐私通行证的支持有关 (https://blog.cloudflare.com/cloudflare-supports-privacy-pass/)。它似乎是一种验证用户是人而不是机器的方法。这反过来对你在这里的努力来说是个坏消息。
我在下面有一个可行的解决方案,但它很难自动化 - 因为它需要您建立一个浏览器 session,并使用代码中设置的 cookie。 cf_clearance cookie 过期后,您将再次访问该站点并在代码中重置 cookie 值。
我还推测请求的 User-Agent header 用于生成所需的 cf_clearance cookie。使劫持 cookie 变得更加困难,因为当 cloudflare 生成 cf_clearance cookie 时,您必须使用用于请求的浏览器的匹配 User-Agent。
我在这里记录了我的调查:
在我的浏览器中访问 URL 时:
并检查服务器给出的响应,事实证明它实际上也在返回 503
:
由于某些我无法理解的原因,浏览器被重定向到下面的 URL。我无法在响应中看到位置 header 被传回,也无法在响应中的任何位置找到此 URL。
我与 Postman 核对过,果然 - 我在那里也遇到了 503 错误。据我所知,服务器(或它前面的反向代理)正在检查请求的 headers,并根据它们使请求无效。我胡闹了一点,将 headers 从浏览器请求移到 Postman 中,最后发现它是 cookie
和 User-Agent
headers 的组合允许请求被送达。
User-Agent
header 不允许有指定的 chrome 版本,我这里使用的是 83 版本。
cookkie
header 是我第一次在浏览器中访问该站点时浏览器将填充的内容。所以在你的代码中处理起来有点困难。我试图用 connection.getHeaderField("set-cookie")
在代码中获取它,但那个 cookie 似乎并没有削减它。
但是!当从我的浏览器中获取 cookie
并在代码中手动设置它以及 User-Agent
:
时,我能够使代码工作
public HttpURLConnection pingHttpUrl(String url) throws IOException {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
// This one does not work for the reason of the chrome version apparently
// conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76 Safari/537.36");
conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36");
conn.addRequestProperty("cookie", "<cookie value from the browser, from the header on a successful request>");
conn.setConnectTimeout(2000);
conn.setInstanceFollowRedirects(false);
conn.setReadTimeout(10000);
conn.connect();
Thread.sleep(1000);
} catch (Exception e) {
System.out.println(String.format("Caught exception : %s", e.getMessage()));
throw new IOException();
}
return conn;
}
我后来发现是来自 cookie 中 cf_clearance
键的 cookie 值造成了差异。
url = "https://www.lmcu.org/?__cf_chl_jschl_tk__=9c114404052361017d9cfe1247981e24813649c7-1592389426-0-AfP07ha5TxZHf64q5tb5nJf9BJguC4U553-OJzJWivTqfgwYLqUODkXj-XsOjZTwpC71ROxHWx4Xhdp2S0LgAVlKgXpy7KWOex7lkoGBm8mNpBsCeJapdYNWty-X2oHE6gp_TtMfH0dcBabvWr_mXV1djsVR_IGlYJA-wCuZpPTGOozyzN9TFwjMPxU-3o6BIUxTh6DDcHmJ_Bw48EYKGpq6n57bVdeLezEs9PduataW1JUcF4GqLE2EHiUxWGubtS8YgcxkkGin4zitHXENMbFi1kMhxI77LsORzKyhkAD1OkG8fGmV--Cgd3EpxWHtHD5vpoIFFIwX0uGQywPnegs";
HttpURLConnection connection = pingHttpUrl(url);
responseCode = connection.getResponseCode();
public HttpURLConnection pingHttpUrl(String url) throws IOException {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76 Safari/537.36");
conn.setConnectTimeout(2000);
conn.setInstanceFollowRedirects(false);
conn.setReadTimeout(10000);
conn.connect();
Thread.sleep(1000);
} catch (Exception e) {
logger.error("Caught exception : {}", e.getMessage());
throw new IOException();
}
return conn;
}
这给出的响应代码为 503。但该网站正在浏览器上正确加载。这可能是什么问题?
问题出在请求的 header 上。我发现这个托管在 cloudflare 上的解决方案需要两个 header 才行,否则你会收到 503
响应:
- User-Agent - 你的header指定了chrome版本76,显然服务器有这有问题。我在这个
User-Agent
值上取得了成功:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36
- cookie - 我发现需要设置 cookie 值
cf_clearance
,并且可能在第一次请求时返回其他set-cookie
值.此值与 cloudflare 对隐私通行证的支持有关 (https://blog.cloudflare.com/cloudflare-supports-privacy-pass/)。它似乎是一种验证用户是人而不是机器的方法。这反过来对你在这里的努力来说是个坏消息。
我在下面有一个可行的解决方案,但它很难自动化 - 因为它需要您建立一个浏览器 session,并使用代码中设置的 cookie。 cf_clearance cookie 过期后,您将再次访问该站点并在代码中重置 cookie 值。
我还推测请求的 User-Agent header 用于生成所需的 cf_clearance cookie。使劫持 cookie 变得更加困难,因为当 cloudflare 生成 cf_clearance cookie 时,您必须使用用于请求的浏览器的匹配 User-Agent。
我在这里记录了我的调查:
在我的浏览器中访问 URL 时:
并检查服务器给出的响应,事实证明它实际上也在返回 503
:
由于某些我无法理解的原因,浏览器被重定向到下面的 URL。我无法在响应中看到位置 header 被传回,也无法在响应中的任何位置找到此 URL。
我与 Postman 核对过,果然 - 我在那里也遇到了 503 错误。据我所知,服务器(或它前面的反向代理)正在检查请求的 headers,并根据它们使请求无效。我胡闹了一点,将 headers 从浏览器请求移到 Postman 中,最后发现它是 cookie
和 User-Agent
headers 的组合允许请求被送达。
User-Agent
header 不允许有指定的 chrome 版本,我这里使用的是 83 版本。
cookkie
header 是我第一次在浏览器中访问该站点时浏览器将填充的内容。所以在你的代码中处理起来有点困难。我试图用 connection.getHeaderField("set-cookie")
在代码中获取它,但那个 cookie 似乎并没有削减它。
但是!当从我的浏览器中获取 cookie
并在代码中手动设置它以及 User-Agent
:
public HttpURLConnection pingHttpUrl(String url) throws IOException {
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
// This one does not work for the reason of the chrome version apparently
// conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76 Safari/537.36");
conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36");
conn.addRequestProperty("cookie", "<cookie value from the browser, from the header on a successful request>");
conn.setConnectTimeout(2000);
conn.setInstanceFollowRedirects(false);
conn.setReadTimeout(10000);
conn.connect();
Thread.sleep(1000);
} catch (Exception e) {
System.out.println(String.format("Caught exception : %s", e.getMessage()));
throw new IOException();
}
return conn;
}
我后来发现是来自 cookie 中 cf_clearance
键的 cookie 值造成了差异。