Java SSLSocket客户端认证配置

发布时间:2023-12-27 11:30

在学校Java网络编程的时候,都会接触到Socket,Socket是基于TCP的数据传输方式,但Socket是没有证书认证的,它无法建立带证书认证的连接。还好,Java中提供了带证书认证的SSLsocket。
最近需要做一个客户端认证的需求,我需要在客户端配置自己的证书,然后向服务器发送数据,本文主要用于记录。
\"Java

一、证书类型

SSL证书的格式有很多,有.p12证书,.crt+.key证书,还有.jks证书,网上大多数案例都是基于.jks证书去实现认证,如果你的证书类型是.p12证书或者是crt证书,你可以手动把p12证书转换成jks证书,如果你是crt证书,下面会提供一个crt证书转换成jks证书的方法。

public class KeyStoreUtils {


    public  void generateKeyStore(String privatePath, String certPath, String ksPath, String password) throws Exception {
        KeyStore var17 = KeyStore.getInstance(\"PKCS12\");

        var17.load((InputStream) null, (char[]) null);
        byte[] bytes = null;
        PrivateKey key = getPrivateKeyFromPem(privatePath);
        Certificate certificate = readCert(certPath);      
        var17.setKeyEntry(\"Eric\'s Key\", key, (char[]) null, new Certificate[]{certificate});
        //加载证书链所有证书
        var17.setKeyEntry(\"Eric\'s Key\", key, (char[]) null, certificates);
        FileOutputStream var18 = new FileOutputStream(ksPath);
        var17.store(var18, password.toCharArray());
        var18.flush();
    }
   

    // 获取私匙
    public static PrivateKey getPrivateKeyFromPem(String privateFile) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(new File(privateFile)));
        String s = br.readLine();
        String str = \"\";
        s = br.readLine();
        while (s.charAt(0) != \'-\') {
            str += s + \"\\r\";
            s = br.readLine();
        }
        BASE64Decoder base64decoder = new BASE64Decoder();
        byte[] b = base64decoder.decodeBuffer(str);

        // 生成私匙
        KeyFactory kf = KeyFactory.getInstance(PropertiesReader.getKey(\"cert_encryption\"));
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(b);
        PrivateKey privateKey = kf.generatePrivate(keySpec);
        return privateKey;
    }

    public static Certificate readCert(String certPath) throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance(\"X.509\");
        FileInputStream in1 = new FileInputStream(certPath);

        Collection<? extends Certificate> certificates = cf.generateCertificates(in1);
        Iterator<? extends Certificate> iterator = certificates.iterator();
        Certificate next = iterator.next();
        return next;
    }

   

    public static void main(String[] args) throws Exception{
        KeyStoreUtils keyStoreUtils = new KeyStoreUtils();
        keyStoreUtils.generateKeyStore(\"./certificate/client_dev.key\",\"./certificate/client_dev.crt\",\"./certificate/client_dev.jks\",\"123456\");

    }
}

SSLSocket相关类介绍

SSLContext:SSLContext类可以创建SSLSocket实例,在这个类中配置自己的证书和自己所信任的证书。

KeyManagerFactory:加载自己的证书文件,并且生成KeyManager[]数据,配置到SSLContext。
TrustManagerFactory:加载自己信任的客户端证书,双向认证的时候配置自己信任哪些服务端证书。
KeyStore:加载证书的类。
TrustManager[]:信任的证书信任的Manager数组。
Manager[]:自己的证书的Manager数组。

二、配置双向认证

代码如下,通过KeyStore去加载证书,这里我客户端证书和信任的服务器证书读的同一个,真实情况肯定是两个不一样的证书。

代码:

		SSLContext ctx = SSLContext.getInstance(\"SSL\");
		KeyManagerFactory kmf = KeyManagerFactory.getInstance(\"SunX509\");
  		TrustManagerFactory tmf = TrustManagerFactory.getInstance(\"SunX509\");
 		 KeyStore ks = KeyStore.getInstance(\"JKS\");
     	tks.load(new FileInputStream(\"C://\"), \"password\".toCharArray());
            kmf.init(ks, new char[0]);
            kmf.init(ks, \"passworld\".toCharArray());
            tmf.init(tks);
            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            log.info(\"创建sslsocket连接中。。。。。。\");
            sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(\"121.0.0.1\", 8000);
       

三、取消验证服务器证书

如果只需要配置客户端证书,客户端信任所有服务器方的证书,可以这样配置。
把TrustManager通过如下方式生成,定义一个类继续TrustManager,X509TrustManager类。

TrustManager[] trustAllCerts = new TrustManager[1];
            TrustManager tm = new miTM();
            trustAllCerts[0] = tm;
static class miTM implements TrustManager,X509TrustManager {
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
        public boolean isServerTrusted(X509Certificate[] certs) {
            return true;
        }
        public boolean isClientTrusted(X509Certificate[] certs) {
            return true;
        }
        @Override
        public void checkServerTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
        @Override
        public void checkClientTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
    }
ctx.init(kmf.getKeyManagers(), trustAllCerts, null);

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号