项目遇到的实际需求: java从信任所有证书到对server证书进行校验

最近项目上开发了一个rest api,放在了一台linux服务器上,并且这个服务器配置了证书,启用了https连接;在另一台服务器上写了一个功能需要去调用linux机器上的api
项目里面自己封装了一个HttpsClient的类,用来发送https请求,并且在里面重写了TrustManager,方法体都为空,这样就不会对server的证书以及client的证书进行校验,能够顺利的从另一台服务器调用linux上的api。如下:

/**
 * 
 * A default TrustManager which will trust any certificate.
 *
 */
private static class DefaultTrustManager implements X509TrustManager {
	@Override
	public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
	}
	@Override
	public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
	}
	@Override
	public X509Certificate[] getAcceptedIssuers() {
		return null;
	}
}

但是上面的这种方法是不安全的,对server的证书以没有进行校验,就不能确定和自己进行通信的server,到底是不是真正的那个我想要通信的server,有可能是一个中间的,黑客部署的server,这样就会导致数据的安全问题。
于是需要对linux server端的证书进行认证,确认server是不是真正想要的server
解决方案:
linux服务器上,使用openssl生成了一个自签名的ssl证书(如何生成ssl证书),用这个证书来启用linux serverhttps证书,并且将这个证书放到另一台的某个目录,然后另一台系统上的java代码,在发送请求的时候,将证书放到keyStore里面,这样java就能对这个证书进行认证。
下面是ChatGPT给出的示例代码: 读取指定的每一个路径上的证书,放到JKS格式的keyStore里面,然后用这个keyStore初始化TrustManager,最后用TrustManager创建sslcontext

    private SSLContext getSSLContext(JSONArray certificates, String protocol) throws Exception {
        SSLContext sc = null;
        if (certificates != null) {
            String certFileName = null;
            try {
                // Create a temp keystore object to be used to make the HTTPS call
                KeyStore keystore = KeyStore.getInstance("JKS");
                keystore.load(null,null);

                for (int i=0; i < certificates.size(); i++) {
                    certFileName = (String)certificates.get(i);

                    try (BufferedInputStream bis = FileFactory.newBufferedInputStream((String)certificates.get(i))) {
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        Certificate cert = cf.generateCertificate(bis);
                        keystore.setCertificateEntry("cert" + i, cert);
                    }
                }
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                tmf.init(keystore);
                // Create and initialize the SSL context that will be used by the HTTPS connection
                sc = SSLContext.getInstance(protocol);
                sc.init(null, tmf.getTrustManagers(), null);
            } catch(IOException e) {
                throw e;
            } catch(CertificateException e) {
                throw e;
            } catch(KeyStoreException | NoSuchAlgorithmException | KeyManagementException e) {
                throw e;
            }
        }
        return sc;
     }

PS: 其实只需要将root CA和中间CA证书放到keystore里面就行,为什么这里是将linux server上的整个证书都放在了里面?
因为linux server上的证书是自签名的,自签名的证书是没有CA签名的,它自己本身就是自己的root CA,这一点可以通过证书的信息看见,如下图,所以直接将整个自签名的证书放到keystore就行。
在这里插入图片描述

当然更加好的方法是去正规的CA机构申请证书,这样就有了root CA和中间的CA证书,就只需要把root CA和中间的CA放到keystore里面,java就能进行校验,保证通信的安全。

更多关于https的文章,请参考我的https专栏:https://blog.csdn.net/u011069294/category_11083017.html?spm=1001.2014.3001.5482

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值