package com.test; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.Authenticator; import java.net.PasswordAuthentication; import java.net.URL; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.X509TrustManager; /** * 通過Https登錄並下載文件。<br> * 1.必須是https方式連接。<br> * 2.解決Basic認證,即登錄框的用戶名密碼填寫操作。 * * @author Concurrency 2012-12-19 */ public class HttpsDownload { public static void main(String[] args) { // Https new HttpsDownload().downloadFile("https://xxx.bin", "D:/test/xxx.bin"); } /** * * @param httpsURL * httpsURL * @param tempFile * temp file path */ private void downloadFile(String httpsURL, String tempFile) { HttpsURLConnection httpsCon = null; FileOutputStream fos = null; InputStream is = null; final int BUFFER_SIZE = 1024; try { // 為Basic認證加上用戶名和密碼並支持https Authenticator.setDefault(new AddBasicPasswordAndSSL()); // 打開URL通道 URL url = new URL(httpsURL); httpsCon = (HttpsURLConnection) url.openConnection(); // 開始網絡連接 httpsCon.setConnectTimeout(2000); httpsCon.connect(); // 讀寫的緩存 byte[] buffer = new byte[BUFFER_SIZE]; int size = 0; is = httpsCon.getInputStream(); fos = new FileOutputStream(tempFile); // 開始讀寫文件 while ((size = is.read(buffer)) != -1) { fos.write(buffer, 0, size); fos.flush(); } } catch (Exception e) { //Exception handle } finally { close(is, fos, httpsCon); System.out.println("end"); } } private void close(InputStream is, OutputStream os, HttpsURLConnection connection) { try { if (is != null) { is.close(); } if (os != null) { os.close(); } if (connection != null) { connection.disconnect(); } } catch (Exception e) { // nanimosinai } } /** * 通過繼承Authenticator類為Basic認證加上用戶名密碼 . 另外用於支持HttpsURLConnection連接 * */ private class AddBasicPasswordAndSSL extends Authenticator { private final String username = "admin"; private final String password = "&TtwQitB2"; AddBasicPasswordAndSSL() throws KeyManagementException, NoSuchAlgorithmException { MyX509TrustManager xtm = new MyX509TrustManager(); MyHostnameVerifier hnv = new MyHostnameVerifier(); SSLContext sslContext = null; sslContext = SSLContext.getInstance("TLS"); // 或SSL X509TrustManager[] xtmArray = new X509TrustManager[] { xtm }; sslContext.init(null, xtmArray, new java.security.SecureRandom()); if (sslContext != null) { HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); } HttpsURLConnection.setDefaultHostnameVerifier(hnv); } // 為Basic認證加上用戶名和密碼 @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password.toCharArray()); } } /** * 重寫X509TrustManager的方法,用於支持https連接。但是並未對服務器的證書作驗證,它就會信任任何證書。 * */ private class MyX509TrustManager implements X509TrustManager { /* * 該方法檢查客戶端的證書,若不信任該證書則拋出異常。 */ @Override public void checkClientTrusted(X509Certificate[] chain, String authType) { } /* * 該方法檢查服務器的證書,若不信任該證書同樣拋出異常。通過自己實現該方法,可以使之信任我們指定的任何證書。在實現該方法時, * 也可以簡單的不做任何處理, 即一個空的函數體,由於不會拋出異常,它就會信任任何證書。 */ @Override public void checkServerTrusted(X509Certificate[] chain, String authType) { } /* * 返回受信任的X509證書數組。 */ @Override public X509Certificate[] getAcceptedIssuers() { return null; } } /** * hostname verification * */ private class MyHostnameVerifier implements HostnameVerifier { @Override public boolean verify(String hostname, SSLSession session) { return true; } } }