关于调用第三方接口,证书的认证问题

关于证书验证,网上许多文章可能会有很大区别,有些属于自签证书,这个没在实战中使用过,所以文章只说明一些特殊接口的证书问题。

文章只以我自己项目举例,不通用所有情况。

文章证书来源

由于我负责的接口,是需要先向第三方接口提供方提交证书,进行报备,然后使用提交的证书,进行证书认证,如果你的问题是自签证书,可能本文章的思路无法帮助到你,文章我会贴出部分源码

证书说明

由客户提供的证书(证书格式为PEM文件),同时提供了一个.key的私钥文件

PEM文件内容为

-----BEGIN CERTIFICATE-----

加密后的数据

-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----

加密后的数据

-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----

加密后的数据

-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----

加密后的数据

-----END CERTIFICATE-----

其实是四个证书组合成的一个证书,分别是Internal Root CA,apigateway,BlueCerts,OnDemand Issuing可能描述的不太准确,这个是我在第三方接口说明获取到的信息,可以不用纠结这个,因为证书生成跟你没关系

KEY文件内容为

----BEGIN RSA PRIVATE KEY-----

加密后的数据

-----END RSA PRIVATE KEY-----

网上许多参考文献,其实对这个说明很模棱两可,有些说需要格式转换,但是我在使用过程中,并没有进行格式转换

组合证书

到这一步,可能会难倒很多人,因为网上各种说法,真的很容易让人混乱,我大概整理了一下我的思路

关于证书

PEM文件:采用 PEM 编码格式的 X.509 证书的文件扩展名;

DER文件:采用 DER 编码格式的 X.509 证书的文件扩展名;

CRT文件:UNIX 系统,可能是 PEM 编码,也可能是 DER 编码,大多数情况下都是采用 PEM 编码;

CER文件:Windows 系统,可能是 PEM 编码,也可能是 DER 编码,大多数情况下都是采用 DER 编码

他们都是使用X.509的证书文件,只是编码格式有区别,这个需要搞清楚,不要搞混了,都是可以相互转换的,具体转换命令自行百度

key文件

key文件有很多种格式,key文件是私钥,可能是.key.pem或者其他,其实跟上面证书意思差不多,都是编码格式,这里客户提供给我们的文件是.key的后缀文件

-----BEGIN PRIVATE KEY-----

-----END PRIVATE KEY-----

-----BEGIN RSA PRIVATE KEY-----

-----END RSA PRIVATE KEY-----

证书 + key组合最终用于认证的文件

最终的文件为PKCS#12文件,他有两种后缀,一种为pfx和p12,两种区别不大

使用下列命令

将PEM证书文件和私钥转换为PKCS#12(.pfx .p12)

openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt

-out文件,我理解为一个组合文件,证书 + 私钥,可以为.pfx文件,p12文件

-inkey文件,表示私钥,一般为带有key后缀或者,.key.pem等,如果没有带有key后缀,可以查看文件,参看上面

-in文件,表示证书,参考证书说明,可以是.crt .cer .pem .der

上面OpenSSL命令还有另一个版本,但是我实际应用中,没有用到(我没有深入了解原理,只是开发中使用到了)

openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt

这里的-certfile文件 CACert.crt文件,其实我不太懂,他具体是用来干嘛的

执行上面的命令以后,会提示你输入密码,我设置了密码(这个不设密码我没有试过)

下面是我遇到的坑,仅供参考

  1. 我设置的密码很长,因为是密码是第三方提供的接口账号的密码,在Windows操作窗口使用OpenSSL执行转换命令后,生成的文件会有问题(具体问题未知,可能是我没有配置环境变量),不是无法生成,而是生成的文件有问题,所以我在公司服务器Linux上进行转换的文件

关于代码应用

先说代码的坑,之前网上各种找案例,最后发现,好像与自己的需求不太匹配。

/*
clientConfig是我定义的配置信息,包括需要访问的地址,搭配证书使用的参数等
*/
private HttpResponse merchantQARegisterSend(String param, String fileUrl, ClientConfig clientConfig) {
        HttpResponse response = null;
        try (FileInputStream inStream = new FileInputStream(fileUrl)) {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(inStream, clientConfig.getClientSecret().toCharArray());
            SSLContext sslcontext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, clientConfig.getClientSecret().toCharArray()).build();

            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext, new String[]{"TLSv1", "TLSv1.2"}, null,
                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            org.apache.http.client.config.RequestConfig defaultRequestConfig = org.apache.http.client.config.RequestConfig.custom()
                    .setSocketTimeout(5000)
                    .setConnectTimeout(5000)
                    .setConnectionRequestTimeout(5000)
                    .setStaleConnectionCheckEnabled(true)
                    .build();

            CloseableHttpClient httpclient = HttpClients.custom().setDefaultRequestConfig(defaultRequestConfig)
                    .setSSLSocketFactory(sslsf)
                    .build();

            HttpPost post = new HttpPost(clientConfig.getUrl());

            org.apache.http.client.config.RequestConfig requestConfig = org.apache.http.client.config.RequestConfig.custom()
                    .setConnectTimeout(90 * 1000)
                    .setSocketTimeout(90 * 1000)
                    .build();

            post.setConfig(requestConfig);
            properties.put("KEY", clientConfig.getKey());
            StringEntity entity = new StringEntity(param, "utf-8");
            entity.setContentType("application/json");
            post.setEntity(entity);

            Properties properties = new Properties();

            PropertiesConfigurationProvider configurationProvider = new PropertiesConfigurationProvider();
            configurationProvider.setProperties(properties);

            AuthProvider authProvider = HmacAuthBuilder.getBuilder()
                    .setConfiguration(configurationProvider)
                    .build();
            //转换成map,写入请求的header中
            Map<String, String> headers = authProvider.generateAuthHeaders(param, clientConfig.getUrl(), "POST");
            for (Map.Entry<String, String> header : headers.entrySet()) {
                post.setHeader(header.getKey(), header.getValue());
            }

            response = httpclient.execute(post);
        } catch (Exception e) {
            
        }
        return response;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值