HttpClient如何访问需要提交客户端证书的SSL服务

HttpClient 如何访问需要提交客户端证书的SSL 服务
1.1 问题背景
自从*** 一期工程上了CA认证网关之后, 在访问受CA认证网关保
护的应用子系统时,必须提交客户端证书。那么问题来了,如果是人
工(通过IE 浏览器)访问子系统自然没问题,访问时会提示选择证
书,输入PIN 码等等,照做即可。但是如果是应用程序去访问呢?例
如,A子系统提供了外部接口程序, 由于受到CA认证网关的“保护”,
外部程序如何访问A子系统的接口呢?
1.2 问题分析
应用程序自然没法像人工一样,借助浏览器访问应用子系统。此
时外部应用程序如果直接通过HttpGet 或HttpPost 去访问应用子系
统的接口时,会抛异常。
由于上了CA认证网关之后, 实现的是应用系统访问的双向身份认
证,即:客户端须验证服务端的身份, 服务端也须验证客户端的身份。
为了实现双向身份认证, 客户端须安装服务端提供的服务端证书, 并
且客户端在访问服务端时须提交客户端证书。只有这样才能实现应用
系统的正常访问。对于人工访问是如此, 对于应用程序访问亦是如此。
令人庆幸的是, Apache HttpClient 提供了基于双向认证机制访
问SSL服务的支持。HttpClient 通过自定义一个携带证书的SSL连
接,实现对需双向认证的服务的访问。
1.3 解决方案
1.3.1 准备工作
结合当前案例的实际情况,有一些准备工作要做:
1、制作客户端带私钥的软证书, 并转化成JKS格式。操作步骤如
下:
1)、在用户管理中心注册用户,并推送到证书注册中心;
2)、登录证书注册中心,首先更新用户信息,把证书类型修改为
“RSA个人单向证书”(默认是“ RSA个人双向证书”);
3)、制作证书,在“签发个人证书”时, “证书设备”选择第二个
选项( 即: Microsoft Enhanced Cryptographic Provider v1.0 )
4)、导出证书:证书制作完成后就可以在IE 的Internet 选项-
内容- 证书列表中看到,然后选中该证书,点击导出。导出过程中注
意选择“是,导出私钥( Y)”,如图所示:
然后下一步,输入私钥( 123456):
最后导出一个.pfx 格式的个人证书:
5)、把pfx 格式证书转换为JKS格式( pfx 格式的证书无法直接
引用,需要转换成keystore 格式, JKS就是keystore 格式之一)。
至于如何转换,百度一下,你就知道。
2、把服务端证书(证书链)导入trust.keystore 中备用。
在本案例中,服务端证书(证书链)包括ROOT.cer和CA.cer 。
这两个证书须导入trust.keystore 。用JDK自带的keytool 工具实
现导入:
keytool -import -alias Root -file d:/Root.cer -keystore
“d:/trust.keystore” -storepass 123456
keytool -import -alias CA -file d:/CA.cer -keystore “d:/trust.keystore”
-storepass 123456
3、在网关上添加用户,并授予角色。
针对刚刚制作的证书, 所关联的用户需在网关上手动录入, 并添
加到相应的角色中。只有这样,才能通过CA认证网关的系统级权限
验证。操作步骤不再赘述。
1.3.2 访问应用子系统
Apache HttpClient 实现携带证书访问SSL服务的基本原理是:
首先加载私钥证书到一个KeyStore 中,并把服务端可信任证书加载
到一个Trusted KeyStore 中;然后用这两个KeyStore 构造一个
SSLContext 对象,最终实例化一个CloseableHttpClient 对象,并
通过CloseableHttpClient 去访问SSL服务。
源码:
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache. http .util.EntityUtils;
/**

  • This example demonstrates how to create secure connections with a custom
    SSL context.
    */
    public class MyClientCustomSSL {
    private final static String TEST_URL =
    https://125.35.24.152:446/sfda/HelloWorldServlet” ;
    private final static String KEYSTORE_FILE = “d:/00000190.jks” ;
    private final static String TRUSTSTORE_FILE = “d:/trust.keystore” ;
    private final static String KEYSTORE_PASSWORD = “123456” ;
    public final static void main(String[] args) throws Exception {
    //load the CA CERT(private key):
    KeyStore keyStore =
    KeyStore. getInstance (KeyStore. getDefaultType ());
    FileInputStream instream =
    new FileInputStream( new File( KEYSTORE_FILE ));
    try {
    keyStore.load(instream, KEYSTORE_PASSWORD.toCharArray());
    } finally {
    instream.close();
    }
    //load the trusted certs :
    KeyStore trustStore =
    KeyStore. getInstance (KeyStore. getDefaultType ());
    FileInputStream instream1 =
    new FileInputStream( new File( TRUSTSTORE_FILE ));
    try {
    trustStore.load(instream1, KEYSTORE_PASSWORD.toCharArray());
    } finally {
    instream1.close();
    }
    // Trust own CA and all self-signed certs
    SSLContext sslcontext = SSLContexts. custom ()
    .loadKeyMaterial(keyStore, KEYSTORE_PASSWORD.toCharArray())
    .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
    .build();
    // Allow TLSv1 protocol only
    SSLConnectionSocketFactory sslsf =
    new SSLConnectionSocketFactory(sslcontext,
    new String[] { “TLSv1” },
    null ,
    SSLConnectionSocketFactory. BROWSER_COMPATIBLE_HOSTNAME_VERIFIER );
    CloseableHttpClient httpclient = HttpClients. custom ()
    .setSSLSocketFactory(sslsf)
    .build();
    try {
    HttpGet httpget = new HttpGet( TEST_URL );
    System. out .println( “Executing Request:” +
    httpget.getRequestLine());
    CloseableHttpResponse response = httpclient.execute(httpget);
    try {
    HttpEntity entity = response.getEntity();
    System. out .println( “-------------------------------------” );
    System. out .println(response.getStatusLine());
    System. out .println(EntityUtils. toString (entity));
    EntityUtils. consume (entity);
    } finally {
    response.close();
    }
    } finally {
    httpclient.close();
    }
    }
    }
    1.4 附录
    1.4.1 HttpClient4.3 官方下载
    http://hc.apache.org/httpcomponents-client-4.3.x/download
    .html
    1.4.2 官方示例ClientCustomSSL 下载
    http://hc.apache.org/httpcomponents-client-4.3.x/httpclie
    nt/examples/org/apache/http/examples/client/ClientCustomSSL
    .java
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值