2

Is there a way to get images from a https url with Java?

What I am trying so far:

URL url = new URL("https://ns6.host.md:8443/sitepreview/http/zugo.md/media/images/thumb/23812__yu400x250.jpg");

System.out.println("Image: " + ImageIO.read(url));

But, I am getting:

Exception in thread "main" javax.imageio.IIOException: Can't get input stream from URL!
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No 
Caused by: java.security.cert.CertificateException: No name matching ns6.host.md found

How can I go through that? I have more than 6k images on that url that I have to fetch.

Denees
  • 9,100
  • 13
  • 47
  • 76
  • 1
    It seems to me, that you need to have a valid certificate for your host. Right now you are using Parallels' default certificate, which is not valid for your hostname. Thus you get a `CertificateException`. – GiantTree May 13 '15 at 20:33

2 Answers2

1

There are two problems. You can use your browser to access the site, and see the errors.

  1. The server certificate is self-signed, not trusted by Java. you can add it to the trust store.

  2. The server certificate does not match the host name "ns6.host.md", and you need a HostnameVerifier that ignores it.

The other answer says the same thing, and it provides code, which unfortunately uses some private APIs.

Example how to solve it in bayou HttpClient, if anyone is interested: https://gist.github.com/zhong-j-yu/22af353e2c5a5aed5857

public static void main(String[] args) throws Exception
{
    HttpClient client = new HttpClientConf()
        .sslContext(new SslConf().trustAll().createContext()) // trust self-signed certs
        .sslEngineConf(engine -> disableHostNameVerification(engine))
        .trafficDump(System.out::print)
        .newClient();
    // typically, app creates one client and use it for all requests

    String url = "https://ns6.host.md:8443/sitepreview/http/zugo.md/media/images/thumb/23812__yu400x250.jpg";
    HttpResponse response = client.doGet(url).sync();
    ByteBuffer bb = response.bodyBytes(Integer.MAX_VALUE).sync();

    InputStream is = new ByteArrayInputStream(bb.array(), bb.arrayOffset()+bb.position(), bb.remaining());
    BufferedImage image = ImageIO.read(is);

}

static void disableHostNameVerification(SSLEngine engine)
{
    SSLParameters sslParameters = engine.getSSLParameters();
    {
        // by default, it's set to "HTTPS", and the server certificate must match the request host.
        // disable it for this example, since the server certificate is ill constructed.
        sslParameters.setEndpointIdentificationAlgorithm(null);
    }
    engine.setSSLParameters(sslParameters);
}
ZhongYu
  • 19,446
  • 5
  • 33
  • 61
  • So, can you help me with an example of this? :) – Denees May 14 '15 at 06:25
  • 1
    @Denees I know how to do it with bayou HttpClient, if you are interested. see https://gist.github.com/zhong-j-yu/22af353e2c5a5aed5857 – ZhongYu May 14 '15 at 12:30
  • 1
    @Denees - don't hesitate to ask me any question. it's risky to use a new library (mine); but the plus side is that you'll get the author's full attention:) – ZhongYu May 14 '15 at 14:45
0

You have a SSL problem which you have to solve first, before you fetch the Image. It says that didn't find any trusted host with the name ns6.host.md in your trusted store in JAVA_HOME/jre/lib/security. You could add to your TrustStore the public key of that host or just ignore SSL errors if that's the case:

HttpsURLConnection.setDefaultHostnameVerifier(getUnsecureHostNameVerifier());

try {
        SSLContext e = SSLContext.getInstance("TLS");
        e.init(new KeyManager[0], new TrustManager[]{new DefaultTrustManager()}, new SecureRandom());
        SSLContext.setDefault(e);
        HttpsURLConnection.setDefaultSSLSocketFactory(e.getSocketFactory());
    } catch (Exception var1) {
        throw new Exception("SSL Error", var1);
    }

 public static class DefaultTrustManager implements X509TrustManager {
    public DefaultTrustManager() {
    }

    public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
    }

    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}