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;
}
}
}