在一个应用中,如何针对不同的外部客户系统,使用不同的数字证书?

问题:

在项目中要向不同的外部应用通过https连接访问webservice,
但是Java中用System.setProperty("javax.net.ssl.keyStore",...), 多个证书无法同时设置,会有冲突,请问这个该怎么处理


解决:

使用 KeyStoreManager 和 TrustManager 就可以了

实际上就是通过 KeyStoreManager, TrustManager 创建 SSLContext 对象,再通过 SSLContext 对象创建 SSLSocketFactory 对象,并将 SSLSocketFactory 对象赋给 HttpsURLConnection 对象。
KeyStoreManager 管理着双向认证中的客户端证书库
TrustManager 管理着双向认证中服务端证书信任库,相当于浏览器中我知道该证书非 CA 签发,但我需要继续操作。 


import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;

public class Test {

    public static void main(String[] args) throws Exception {

        // System.setProperty("javax.net.debug", "all");

        URL url = new URL("https://www.xxxx.com");

        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

        connection.setSSLSocketFactory(getSSLSocketFactory());

        InputStream in = connection.getInputStream();
        byte[] bys = new byte[8192];
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (int p = 0; (p = in.read(bys)) != -1;) {
            baos.write(bys, 0, p);
        }
        String str = new String(baos.toByteArray());
        System.out.println(str);
    }

    private static SSLSocketFactory getSSLSocketFactory() {
        MyKeyManager keyManager = new MyKeyManager(KeyStoreType.PKCS12, "d:/key.p12", "123456".toCharArray());
        MyTrustManager trustManager = new MyTrustManager("d:/trust.keystore", "123456".toCharArray());
        MySSLContext context = new MySSLContext("TLS", keyManager, trustManager);
        return context.getSSLContext().getSocketFactory();
    }
}

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;

public class MySSLContext {

    private String protocol;
    private MyKeyManager keyManager;
    private MyTrustManager trustManager;

    public MySSLContext(String protocol, MyKeyManager keyManager, MyTrustManager trustManager) {
        this.protocol = protocol;
        this.keyManager = keyManager;
        this.trustManager = trustManager;
    }

    public MySSLContext(String protocol, MyTrustManager trustManager) {
        this(protocol, null, trustManager);
    }

    public MySSLContext(String protocol, MyKeyManager keyManager) {
        this(protocol, keyManager, null);
    }

    public SSLContext getSSLContext() {
        try {
            SSLContext context = SSLContext.getInstance(protocol);
            context.init(getKeyManagers(), getTrustManagers(), null);
            return context;
        } catch (Exception e) {
            throw new IllegalStateException("error, protocol: " + protocol, e);
        }
    }

    private KeyManager[] getKeyManagers() {
        if (keyManager == null) {
            return null;
        }
        return keyManager.getKeyManagers();
    }

    private TrustManager[] getTrustManagers() {
        if (trustManager == null) {
            return null;
        }
        return trustManager.getTrustManagers();
    }
}

import java.security.KeyStore;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;

public class MyKeyManager {

    private KeyStore ks;
    private char[] password;

    public MyKeyManager(String keyStore, char[] password) {
        this(KeyStoreType.JKS, keyStore, password);
    }

    public MyKeyManager(KeyStoreType type, String keyStore, char[] password) {
        this.password = password;
        this.ks = MyKeyStoreUtil.loadKeyStore(type, keyStore, password);
    }

    public KeyManager[] getKeyManagers() {
        try {
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, password);
            return kmf.getKeyManagers();
        } catch (Exception e) {
            throw new KeyStoreRuntimeException("cannot get KeyManagers", e);
        }
    }
}

import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class MyTrustManager {

    private KeyStore ks;

    public MyTrustManager(String keyStore, char[] password) {
        this(KeyStoreType.JKS, keyStore, password);
    }

    public MyTrustManager(KeyStoreType type, String keyStore, char[] password) {
        this.ks = MyKeyStoreUtil.loadKeyStore(type, keyStore, password);
    }

    public TrustManager[] getTrustManagers() {
        return new TrustManager[]{ new ClientTrustManager() };
    }

    private class ClientTrustManager implements X509TrustManager {
        private X509TrustManager sunJSSEX509TrustManager;

        public ClientTrustManager() {
            loadTrust();
        }

        private void loadTrust() {
            try {
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                tmf.init(ks);
                TrustManager tms[] = tmf.getTrustManagers();
                for (int i = 0; i < tms.length; i++) {
                    if (tms[i] instanceof X509TrustManager) {
                        sunJSSEX509TrustManager = (X509TrustManager) tms[i];
                        return;
                    }
                }
            } catch (Exception e) {
                throw new KeyStoreRuntimeException(e);
            }
        }

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            sunJSSEX509TrustManager.checkClientTrusted(chain, authType);
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return sunJSSEX509TrustManager.getAcceptedIssuers();
        }
    }
}

import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;

public class MyKeyStoreUtil {

    private MyKeyStoreUtil() {
    }

    public static KeyStore loadKeyStore(KeyStoreType type, String keyStore, char[] password) {
        if (type == null) {
            type = KeyStoreType.JKS;
        }
        InputStream in = null;
        try {
            try {
                KeyStore ks = type.getKeyStore();
                in = new FileInputStream(keyStore);
                ks.load(in, password);
                return ks;
            } finally {
                if (in != null) {
                    in.close();
                }
            }
        } catch (Exception e) {
            throw new KeyStoreRuntimeException("type: " + type +
                    ", keyStore: " + keyStore, e);
        }
    }

    public static enum KeyStoreType {
        JKS {
            @Override
            public KeyStore getKeyStore() throws KeyStoreException {
                return getKeyStore("JKS");
            }
        },

        PKCS12 {
            @Override
            public KeyStore getKeyStore() throws KeyStoreException {
                return getKeyStore("PKCS12");
            }
        };

        public abstract KeyStore getKeyStore() throws KeyStoreException ;

        private static KeyStore getKeyStore(String type) throws KeyStoreException {
            return KeyStore.getInstance(type);
        }
    }

    public static class KeyStoreRuntimeException extends RuntimeException {

        private static final long serialVersionUID = 1L;

        public KeyStoreRuntimeException(String message, Throwable cause) {
            super(message, cause);
        }

        public KeyStoreRuntimeException(Throwable cause) {
            super(cause);
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值