处理https双向认证的一次体验

处理https双向认证的一次体验

最近参与了一次poc测试的开发,项目大致是应用管理平台的开发,设计应用部署、管理、监控等,其中底层是调用的是阿里方面的接口,每一个请求都需要通过https验证。当时阿里方面提供的文档就是一堆curl命令
例如:获取现有应用列表的curl命令

curl https://22.5.247.186:18300/projects --key /home/rtadm/api/key.pem --cacert /home/rtadm/api/ca.pem --cert /home/rtadm/api/cert.pem

通过上面这个curl命令,我们能获取阿里方面返回的json格式的应用列表信息,然后对数据进行解析,得到自己想要的数据。

curl命令是如此这般,那Java命令该如何实现呢?

从上面的curl命令可以看出,除了get方法的请求路径外,后边还跟了一堆参数,那是验证的证书,证书的位置是我当前使用的Linux机器上的某个位置。

Java处理过程

下载证书

证书是由阿里提供的,他们的机制是不同集群、不同平台(Linux、windows)的证书都不一样,从指定管理页面下载证书文件后,解压得到三个文件ca.pemcert.pemkey.pem

处理认证过程

public class PojectService {

    //证书名称(不同环境、不同集群证书不一样)
    public static final String DEFAULT_CA_CERT_NAME = "ca.pem";
    public static final String DEFAULT_CLIENT_CERT_NAME = "cert.pem";
    public static final String DEFAULT_CLIENT_KEY_NAME = "key.pem";
    //本地证书路径
    public static final String CERT_PATH = "C:\\Users\\Administrator\\Downloads\\certFiles";

    //证书密码
    private static final char[] KEY_STORE_PASSWORD = "aaa!!vv!!one!".toCharArray();

    public static void main(String[] args) {
        try {
            PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
            CloseableHttpClient client = new DefaultHttpClient(cm);
            SSLContextBuilder sslContextBuilder = SSLContexts.custom().useProtocol("TLSv1.2");

            File caCertFile = new File(CERT_PATH, DEFAULT_CA_CERT_NAME);
            File clientCerFile = new File(CERT_PATH, DEFAULT_CLIENT_CERT_NAME);
            File clientKeyFile = new File(CERT_PATH, DEFAULT_CLIENT_KEY_NAME);
            //受信任证书链
            final CertificateFactory cf = CertificateFactory.getInstance("X.509");
            //构建证书
            final Certificate caCert = cf.generateCertificate(new FileInputStream(caCertFile));
            final Certificate clientCert = cf.generateCertificate(new FileInputStream(clientCerFile));
            //秘钥
            final PEMKeyPair clientKeyPair = (PEMKeyPair) new PEMParser(
                    new BufferedReader(new FileReader(clientKeyFile))).readObject();
            //根据给定的编码密钥创建一个新的 PKCS8EncodedKeySpec
            final PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(clientKeyPair.getPrivateKeyInfo().getEncoded());
            // 实例化KeyFactory对象,并指定RSA算法
            final KeyFactory kf = KeyFactory.getInstance("RSA");
            // 获得PrivateKey对象
            final PrivateKey clientKey = kf.generatePrivate(spec);

             //使用默认证书  获取对象
            final KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            //去掉系统默认证书  
            trustStore.load(null, null);
             //设置自己的证书  
            trustStore.setEntry("ca", new KeyStore.TrustedCertificateEntry(caCert), null);

            final KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null, null);
            keyStore.setCertificateEntry("client", caCert);
            keyStore.setKeyEntry("key", clientKey, KEY_STORE_PASSWORD, new Certificate[] { clientCert });

            sslContextBuilder.loadTrustMaterial(trustStore).loadKeyMaterial(keyStore, KEY_STORE_PASSWORD);
            SSLContext sslContext = sslContextBuilder.build();

            SSLSocketFactory sf = new SSLSocketFactory(sslContext);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            Scheme scheme = new Scheme("https", sf, 18300);
            client.getConnectionManager().getSchemeRegistry().register(scheme);
            //get方式请求
            HttpGet httpGet = new HttpGet("https://107.145.131.29:1300/projects/");
            //执行get请求
            HttpResponse httpResponse = client.execute(httpGet);

            System.out.println("Result is: ");
            //获取相应结果
            String result = EntityUtils.toString(httpResponse.getEntity());

        } catch (Exception e) {
            System.out.println("Error is: ");
            System.out.println(e);
        }
    }
}

其实上面那些代码也不是很明白,第一次使用,细节以后慢慢研究

在调用接口的时候,无论是get、post、delete请求都需要认证,认证的方式是一样的。
curl命令的post请求

curl https://22.5.247.186:18300/containers/容器ID/stop  --key /home/rtadm/api/key.pem --cacert /home/rtadm/api/ca.pem --cert /home/rtadm/api/cert.pem

把上面的httpGet换成

HttpPost post = new HttpPost("https://106.15.131.29:18300/contaniners/vesselName/stop");

curl的delete命令

curl -X delete https://22.5.247.186:18300/project/APPNAME --key /home/rtadm/api/key.pem --cacert /home/rtadm/api/ca.pem --cert /home/rtadm/api/cert.pem

把上面的httpGet换成

HttpDelete delete = new HttpDelete("https://106.15.131.29:18300/projects/applyName");

因为涉及保密问题,开发环境是没有外网的,开发机器也是对方的机器,资料不允许外传,所以上面的代码是手抄笔录的,还有点不完善,权当一次笔记了。


附录:涉及的jar下载地址:http://download.csdn.net/download/leisure_life/10001214

你可能感兴趣的:(https,jar包下载)