package com.iraid.test;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

/**
 * 使用 jdk自带ssl包 进行 https通讯双向认证。
 * @author wangfeihu
 *
 */
public class HttpsTest {
	public static void main(String[] args) throws Exception {
		testHttpsWithCert();
	}

	/**
	 * post 请求,带双证书验证
	 */
	public static void testHttpsWithCert() {
		// 授信证书库
		String trustStore = "D:\\workspaces\\test\\https-native\\src\\cacerts.jks";
		String trustStorePass = "changeit";

		// 私钥证书
		String keyStore = "D:\\workspaces\\test\\https-native\\src\\www.demo.com.p12";
		String keyStorePass = "052537159932766";

		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";

		try {
			TrustManager[] tms = getTrustManagers(trustStore, trustStorePass);

			KeyManager[] kms = getKeyManagers(keyStore, keyStorePass);

			SSLContext sslContext = SSLContext.getInstance("SSL");
			// 如果服务器不要求私钥证书,kms 可以不填
			sslContext.init(kms, tms, new java.security.SecureRandom());

			SSLSocketFactory ssf = sslContext.getSocketFactory();

			// 服务链接
			URL url = new URL(
					"https://www.demo.com/rest/UidApiService/authCardWithoutOTP");
			// 请求参数
			String params = "{\"merchantCode\": \"www.demo.com\","
					+ "\"sessionId\": \"10000011\","
					+ "\"userName\": \"jack\","
					+ "\"idNumber\": \"432652515\","
					+ "\"cardNo\": \"561231321\"," + "\"phoneNo\": \"\"}";

			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
			conn.setSSLSocketFactory(ssf);

			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0");
			
			// content-type 按具体需要进行设置
			conn.setRequestProperty("content-type", "application/json");
			
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);

			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(params);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(
					new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
			System.out.println(result);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 加载信任证书库
	 * 
	 * @param trustStore
	 * @param trustStorePass
	 * @return
	 * @throws IOException
	 */
	private static TrustManager[] getTrustManagers(String trustStore,
			String trustStorePass) throws IOException {
		try {
			String alg = TrustManagerFactory.getDefaultAlgorithm();
			TrustManagerFactory factory = TrustManagerFactory.getInstance(alg);
			InputStream fp = new FileInputStream(trustStore);
			KeyStore ks = KeyStore.getInstance("JKS");
			ks.load(fp, trustStorePass.toCharArray());
			fp.close();
			factory.init(ks);
			TrustManager[] tms = factory.getTrustManagers();
			System.out.println(tms);
			return tms;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (CertificateException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 加载私钥证书
	 * 
	 * @param keyStore
	 * @param keyStorePass
	 * @return
	 * @throws IOException
	 */
	private static KeyManager[] getKeyManagers(String keyStore,
			String keyStorePass) throws IOException {
		try {
			String alg = KeyManagerFactory.getDefaultAlgorithm();
			KeyManagerFactory factory = KeyManagerFactory.getInstance(alg);
			InputStream fp = new FileInputStream(keyStore);
			KeyStore ks = KeyStore.getInstance("PKCS12");
			ks.load(fp, keyStorePass.toCharArray());
			fp.close();
			factory.init(ks, keyStorePass.toCharArray());
			KeyManager[] keyms = factory.getKeyManagers();
			System.out.println(keyms);
			return keyms;
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (UnrecoverableKeyException e) {
			e.printStackTrace();
		}
		return null;
	}

}