Https登录并下载文件

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

  

posted @ 2019-09-11 15:55  jack_zc  阅读(2763)  评论(0编辑  收藏  举报