HttpClient 双向认证

功能背景

最近我们项目很多依赖API纷纷上Azure,通过Azure的Application Gateway 服务进行负载均衡处理切采用双向认证。因此我们就需要考虑证书的出示与信任问题,捣鼓了好久,在我差点儿要吐的情况下……还好成功解决了。

角色介绍

  1. 服务器: Azure Gateway
  2. 客户端: HttpClient

因为是我们请求Azure Gateway 服务从而请求对应API,所以其就是Server端,相对应的我们就是Client端。

服务器端证书获取

直接在浏览器中访问Gateway URL ,即可获取服务器端证书。详细步骤参考我的文章网站证书获取

Gateway 信任客户端证书

好了,到此我们已经有了服务器端的证书,我们可以信任服务器端证书,那么我们还需要准备我们的证书给Gateway信任,这样彼此信任方为双向认证嘛。^ -^

OpenSSL对d证书文件处理

到目前为止,我们与Gateway彼此信任,就可以通信了。 但是如果要使用HttpClient还需要一些处理。这里我们使用OpenSSL(关于OpenSSL有时间我另写一篇介绍)对证书进行处理。

证书文件生成JKS文件

在OpenSSL中使用下面的命令

Server端证书处理

keytool -import -alias csdncert -keystore trustkeystore.jks -file D:/csdn.cer -storepass changeit

Client端证书处理

Client端证书有一点比较特殊,我们需要使用我们的私钥。

openssl pkcs12 -export -name myservercert -in myserver.cer –inkey myserver.key -out myserver.p12

证书文件生成P12文件

在OpenSSL中使用下面的命令

Server端证书处理

keytool -importkeystore -destkeystore trustkeystore.jks -srckeystore trustkeystore.p12 -srcstoretype pkcs12 -alias trustkeystore

Client端证书处理

Client端证书有一点比较特殊,我们需要使用我们的私钥。

keytool -importkeystore -destkeystore myserver.jks -srckeystore myserver.p12 -srcstoretype pkcs12 -alias myserver

HttpClient双向认证(Mutual Authentication )实现

 public static String doPostJsonWithMutualSSL(String url, String params,String certSystemName) throws Exception{

        RequestConfig config = RequestConfig.custom().setConnectTimeout(3000)
                .setSocketTimeout(3000).build();
        SSLContext sslContext = buildSSLContextForWAS();
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslContext, new String[] { "TLSv1.2", "TLSv1.1", "TLSv1" }, null,
                SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        CloseableHttpClient client = HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory)
                .setDefaultRequestConfig(config).build();
        HttpPost httpPost = new HttpPost(url);
        //httpPost.setHeaders(headers);
        httpPost.setHeader("Content-Type", "application/json; charset=utf-8");
        httpPost.setHeader("Accept", "application/json");
        httpPost.setEntity(new StringEntity(params, Charset
                .forName("UTF-8")));
        System.out.println("Access Endpoint: "+ url);
        System.out.println("Request Parameters : "+ params.toString());

        HttpResponse response = client.execute(httpPost);
        HttpEntity responseEntity = response.getEntity();
        String result = EntityUtils.toString(responseEntity, "UTF-8"); // 接口转码

        int responseCode = response.getStatusLine().getStatusCode();
        System.out.println("Response Code: "+responseCode);
        System.out.println("Content:-\n"+result);

        return result;
    }
  private static SSLContext buildSSLContextForSystem(){


        FileInputStream identityKeyStoreFile = null;
        FileInputStream trustKeyStoreFile = null;
        SSLContext sslContext = null;
        KeyManagerFactory keyManagerFactory = null;

        try {
            KeyStore identityKeyStore = KeyStore.getInstance("jks");
            identityKeyStoreFile = new FileInputStream("D:\\myserver.jks");
            identityKeyStore.load(identityKeyStoreFile, "changeit".toCharArray());

            KeyStore trustKeyStore = KeyStore.getInstance("jks");
            trustKeyStoreFile = new FileInputStream("D:\\trustkeystore.jks");
            trustKeyStore.load(trustKeyStoreFile, "changeit".toCharArray());


            sslContext = SSLContexts.custom()
                    // load identity keystore
                    .loadKeyMaterial(identityKeyStore, "changeit".toCharArray(), new PrivateKeyStrategy() {
                        @Override
                        public String chooseAlias(Map<String, PrivateKeyDetails> aliases, java.net.Socket socket) {

                            return "csdncert"; //truststore中client证书别名
                        }
                    })
                    // load trust keystore
                    .loadTrustMaterial(trustKeyStore, null)
                    // all trust
                    // .loadTrustMaterial(null, (chain, authType) -> true)
                    .build();
        } catch (Exception ex) {
            System.out.println("build sslContext error:"+ ex);
        } finally {
            try {
                if (identityKeyStoreFile != null) {
                    identityKeyStoreFile.close();
                }
                if (trustKeyStoreFile != null) {
                    trustKeyStoreFile.close();
                }
            } catch (Exception fe) {
                System.out.println("Filestream close error: "+fe);
            }
        }
        return sslContext;
    }

WebSphere中的特殊处理

在WebSphere中对应的keystore为p12文件,具体路径可以查看SSL certificate and key management > Key stores and certificates
在这里插入图片描述

Gateway server端证书

服务器端证书需要导入DefaultTrustStore,如果是Cluster请导入CellDefaultTrustStore中。
在这里插入图片描述

客户端证书

对于客户端证书我们可以导入到任意truststore中,我是将其导入到SSL certificate and key management > Key stores and certificates > NodeDefaultTrustStore > Personal certificates

需要私钥以及client证书生成p12文件,参考上面的client端证书生成p12
在这里插入图片描述
在这里插入图片描述
这里的Alias很重要,上面代码中,loadKeyMaterial中chooseAlias返回的就是这个名称。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HttpClient是一个常用的HTTP客户端工具,用于发送HTTP请求和接收HTTP响应。在进行OAuth认证时,可以使用HttpClient来实现。 首先,需要导入HttpClient的相关包,并创建一个HttpClient实例。可以使用以下代码创建一个默认的HttpClient实例: ``` CloseableHttpClient httpClient = HttpClients.createDefault(); ``` 接下来,需要构建OAuth认证请求。OAuth认证通常涉及授权码的获取、令牌的申请和刷新等步骤。可以使用HttpClient的HttpPost或HttpGet类来构建相应的请求。例如,使用HttpPost构建一个获取授权码的请求: ``` HttpPost request = new HttpPost("https://oauth.example.com/authorize"); request.setHeader("Content-Type", "application/x-www-form-urlencoded"); request.addParameter("client_id", "your_client_id"); request.addParameter("redirect_uri", "your_redirect_uri"); request.addParameter("response_type", "code"); ``` 然后,发送认证请求并接收响应。可以使用HttpClient的execute方法发送请求并接收响应。例如: ``` CloseableHttpResponse response = httpClient.execute(request); ``` 接收到响应后,可以从响应中获取认证相关的信息。例如,可以从响应的实体中获取认证授权码: ``` HttpEntity entity = response.getEntity(); String authCode = EntityUtils.toString(entity); ``` 接下来的步骤根据具体的OAuth流程会有所不同,可以根据实际需求进行令牌的申请、刷新等操作。 需要注意的是,在进行OAuth认证时,可能会涉及到授权头信息等安全相关的操作。可以通过HttpClient的方法设置请求头信息来确保安全性。 总之,使用HttpClient进行OAuth认证需要创建HttpClient实例、构建认证请求、发送请求并接收响应,然后根据具体的OAuth流程进行相应的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值