【问题标题】:Getting 503 error with HttpUrlConnection but site loading on browser使用 HttpUrlConnection 出现 503 错误,但在浏览器上加载网站
【发布时间】:2020-10-07 05:36:58
【问题描述】:
     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 的响应代码。但该网站正在浏览器上正确加载。这可能是什么问题?

【问题讨论】:

    标签: java httpresponse httpurlconnection


    【解决方案1】:

    问题在于请求的标头。我发现这个托管在 cloudflare 上的解决方案需要两个标头才能如此,否则您将收到 503 响应:

    • User-Agent - 您的标头指定了 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/) 的支持有关。它似乎是一种验证用户是人而不是机器的方法。这反过来对您在这里的工作来说是个坏消息。

    我在下面有一个可行的解决方案,但它很难自动化 - 因为它需要您建立一个浏览器会话,并使用代码中设置的 cookie。 cf_clearance cookie 到期后,您将再次访问该站点并重置代码中的 cookie 值。

    我还推测请求的 User-Agent 标头用于生成所需的 cf_clearance cookie。使劫持 cookie 变得更加困难,因为当 cloudflare 生成 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

    并检查服务器给出的响应,结果发现它实际上也返回了 503

    由于某些我无法理解的原因,浏览器被重定向到以下 URL。我看不到位置标头在响应中被传回,或者在响应中的任何地方都找不到此 URL。

    https://www.lmcu.org/?cf_chl_jschl_tk=fe835fdc1e7e2f5b2857ab5eb4be84e67d0e8c42-1592506549-0-AQ3E1piNGHg7O7lxgRyItR1U5BzB52q7GmCHe_HPJBsUHv8RcZCgqLPPtyngPmDjvy7pZDprPNK6ihKVEgQ7HqmbDSPXZ1aHPkBDs9re49u_Q_jI04etmtK7E0GIdxhKWCd-p4TR7b_b0JdnwzJOF6z4XaJQOgNU8kazJr5Mo96zxQpUlsKWPSumEmSfynkGeMDgkM-O1mN59LKp0p4kt-2O2IIFrlc8289ZbCSO6JghtvDsLsFDA3VxLV3Irn2W3KQ8sHg_TdwB-0g0WX9J-WTwedVYzj2a7uNtH377ZIritTXKqRw1qeQ6mkpxQ0h_OVMIl8XUiEC0Zj1KP50tUK8

    我检查了 Postman,果然 - 我也收到了 503 错误。据我所知,服务器(或它前面的反向代理)正在检查请求的标头,并根据它们使请求无效。我胡闹了一下,将浏览器请求中的标头移动到 Postman 中,最后发现是 cookieUser-Agent 标头的组合允许服务请求。

    User-Agent 标头不允许有指定的 chrome 版本,我在这里使用 83 版。 cookkie 标头是我第一次访问浏览器中的站点时浏览器将填充的内容。所以在你的代码中处理起来有点困难。我尝试使用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 值造成了差异。

    【讨论】:

    • 此解决方案是否有任何概括,因为我需要获取大量站点的响应代码,而此更改可能会影响其他站点的响应代码。或者这也适用于已经提供 200 个状态代码的其他网站?我基本上想知道是否有任何概括或任何其他方式来解决它而不影响其他站点的状态代码。
    猜你喜欢
    • 2017-12-22
    • 1970-01-01
    • 1970-01-01
    • 2016-03-28
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 2015-01-22
    相关资源
    最近更新 更多