Fetching data from HttpURLConnection as text throw

2019-06-06 01:00发布

问题:

Java Version 1.8.0_121 , I see a solution for Java 9 only

Description:

My goal is to get informations about SourceForge Projects , such as the total downloads of a Project . SourceForge has an API for that called SourceForge Downloads Stats API .

So i created a simple program see the result as raw text , i don't necessary need it as JSON .

For example i am gettings information about Apache OpenOffice downloads and many more -> Link , you can try it to see

But i can't fetch the data using Java cause of the error below . I have tested the code with other websites and it works well , but for this one i don't know why .

Java Code:

import java.net.*;
import java.io.*;

public class URLReader {
    public static void main(String[] args) throws Exception {

        //Create HttpURLConnection 
        HttpURLConnection httpcon = (HttpURLConnection) new URL(
                "https://sourceforge.net/projects/openofficeorg.mirror/files/stats/json?start_date=2014-10-29&end_date=2014-11-04").openConnection();
        //In case it might to the trick...
        httpcon.addRequestProperty("User-Agent", "Mozilla/5.0");
        //Read the inputstream
        BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream()));

        //Print everything
        String inputLine;
        while ( ( inputLine = in.readLine() ) != null)
            System.out.println(inputLine);
        in.close();
    }
}

Error:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal a
lert: handshake_failure
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:13
75)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Abstra
ctDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnectio
n.java:1546)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection
.java:1474)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLCon
nectionImpl.java:254)
    at aaTester.URLReader.main(URLReader.java:13)

Finally

A solution on the above will be greatly appreciated .

Trying using Andy's answer produces the same error.

回答1:

Turning the comment from @GOXR3PLUS into an answer:

Upgrading to at least Java 8u161 (or Java 9) makes the SSLHandshakeException go away for downloads from SourceForge.



回答2:

You cannot require that the end-user have the policies installed, but there are programmatic ways around the enforcement of the policy. Disclaimer: this is not recommended and may have TOS and ITAR implications.

This code executed in a static block before the TLS negotiation should allow the JVM to use AES-256 cipher suites.

if (Cipher.getMaxAllowedKeyLength("AES") < 256) {
  try {
    Field field = Class.forName("javax.crypto.JceSecurity").
    getDeclaredField("isRestricted");
    field.setAccessible(true);
    field.set(null, java.lang.Boolean.FALSE);
  } catch (Exception e) {
    fail("Could not override JCE cryptography strength policy setting");
    fail(e.getMessage());
  }
}


回答3:

The below is only for getting the downloads which i actually needed. So this is not the complete answer.

Here is a tricky way to get the Total downloads using the svg image that SourceForge is providing for downloads :

To get the downloads per week/day/year you can just change a little bit the code to remove the innapropriate text.

Check the text that is returned from the BufferedReaded as i did for total downloads.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;


public class URLReader {
    public static void main(String[] args) throws Exception {

        //System.out.println(Cipher.getMaxAllowedKeyLength("AES"));

        //Create HttpURLConnection  
        HttpURLConnection httpcon = (HttpURLConnection) new URL("https://img.shields.io/sourceforge/dt/xr3player.svg").openConnection();
        httpcon.addRequestProperty("User-Agent", "Mozilla/5.0");
        BufferedReader in = new BufferedReader(new InputStreamReader(httpcon.getInputStream()));

        //Read line by line
        String line = "" , inputLine;
        while ( ( inputLine = in.readLine() ) != null) {
            line += "\n" + inputLine;
            System.out.println(inputLine);
        }
        in.close();

        //Get SourceForge Downloads 
        System.out.println("Total Downlads: "+line.split("<text x=\"98.5\" y=\"14\">")[1].split("/total")[0]);
    }

}


标签: java json ssl