SSL双向验证--keytool实现自签名证书

 

一、服务端

1. 生成密钥库 --- kserver.keystore 是给服务端用的,其中保存着自己的私钥

keytool -genkey -alias serverkey -keystore ./kserver.keystore -dname CN=test-server,OU=CTF,O=CTF1,L=SHH,ST=SHH,C=CN -validity 36500 -keysize 1024 -keyalg RSA -storepass 123456 -v

2. 导出密钥证书kserver.cer --- 根据私钥,导出服务端证书

keytool -export -alias serverkey -keystore ./kserver.keystore  -file ./kserver.cer -storepass 123456

3. 生成服务端信任密钥库 (可以与密钥库使用同一个)

keytool -genkey -alias servertrustkey -keystore ./kservertrust.keystore -dname CN=test-server-trust,OU=CTF,O=CTF1,L=SHH,ST=SHH,C=CN -validity 36500 -keysize 1024 -keyalg RSA -storepass 123456trust -v

4. 将证书导入客户端信任库(客户端信任库在后续创建)

keytool -import -alias serverkey -file kserver.cer -keystore kclienttrust.keystore

5. 查看证书内容

keytool -list -v -keystore kserver.keystore -storepass 123456

keytool -list -v -keystore kservertrust.keystore -storepass 123456trust

 

二、客户端

1. 生成密钥库 --- kclient.keystore 是给服务端用的,其中保存着自己的私钥

 keytool -genkey -alias clientkey -keystore ./kclient.keystore -dname CN=test-client,OU=CTF,O=CTF1,L=SHH,ST=SHH,C=CN -validity 36500 -keysize 1024 -keyalg RSA -storepass 123456 -v

2. 导出密钥证书 kclient.cer --- 根据私钥,导出服务端证书

keytool -export -alias clientkey -keystore ./kclient.keystore  -file ./kclient.cer -storepass 123456

3. 生成客户端信任密钥库

keytool -genkey -alias clienttrustkey -keystore ./kclienttrust.keystore -dname CN=test-client-trust,OU=CTF,O=CTF1,L=SHH,ST=SHH,C=CN -validity 36500 -keysize 1024 -keyalg RSA -storepass 123456trust -v

此时得到如下6个文件:

 

4. 将证书导入服务端信任库  

keytool -import -alias clientkey -file kclient.cer -keystore kservertrust.keystore

5. 查看证书内容

keytool -list -v -keystore kclient.keystore -storepass 123456

keytool -list -v -keystore kclienttrust.keystore -storepass 123456trust

注:后续代码中会用到:

服务端(tomcat/weblogic):kserver.keystore、kservertrust.keystore

客户端(程序):kclient.keystore、kclienttrust.keystore

 

三、服务器配置

1.  Tomcat 服务器配置

Tomcat安装目录/conf/server.xml  中添加,其中clientAuth=true代表开启双向验证   

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"

               maxThreads="150" scheme="https" secure="true"

               clientAuth="true" sslProtocol="TLS"

               keystoreFile="/home/https/kserver.keystore" keystorePass="123456"

               truststoreFile="/home/https/kserver.keystore" truststorePass="123456"/>

2. Weblogic服务器配置

  

 

最后激活重新部署。

 

四、自签名证书

自签名证书:对于每一个要链接的服务器,都要保存一个证书的验证副本,而且一旦服务器更换证书,所有客户端就需要重新部署这些副本。要解决这一问题可以使用openssl,或者使用第三方信任机构颁发的证书。

 

五、HttpsUtil工具类 - 客户端

 

/**
 * 使用httpclient4.x.x实现https双向验证
 */
public class Https4client {

    public static void main(String[] args) throws Exception {
        HttpClient httpclient = getHttpClient();
        HttpEntity entity=null;
        //1.get测试
//        HttpGet get = new HttpGet("https://自己服务器IP:端口/test/doget");
//        HttpResponse rsp = httpclient.execute(get);

        //2.post测试
        HttpPost post = new HttpPost("https://自己服务器IP:端口/test/dopost");
        StringEntity stringEntity = new StringEntity("test post method!", Charset.forName("UTF-8"));
        post.setEntity(stringEntity);
        HttpResponse rsp = httpclient.execute(post);

        entity =  rsp.getEntity();
        //用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串,防止服务器返回的数据带有中文,所以在转换的时候将字符集指定成utf-8就可以了
        String result= EntityUtils.toString(entity, "UTF-8");
        System.out.println("-------------------------result:"+result+"-------------");
        if(rsp.getStatusLine().getStatusCode()==200){
            System.out.println(rsp.getStatusLine().getStatusCode()+"-----------success------------------");
        }else{
            System.out.println(rsp.getStatusLine().getStatusCode()+"------------------fail-----------");
        }

    }



    public static HttpClient getHttpClient() throws Exception{
        //设置http参数
        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "UTF-8");
        HttpProtocolParams.setUseExpectContinue(params, true);

        HttpConnectionParams.setConnectionTimeout(params, 5000);//连接超时
        HttpConnectionParams.setSoTimeout(params, 5000);//请求超时

        SchemeRegistry schReg = new SchemeRegistry();
        schReg.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));

        SSLSocketFactory sf = getBidirectionalSSL();
        schReg.register(new Scheme("https", 443, sf));

        PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(
                schReg);
        pccm.setMaxTotal(100); // 客户端总并行链接最大数
        pccm.setDefaultMaxPerRoute(20); // 发送到指定主机的最大连接数
        DefaultHttpClient httpclient = new DefaultHttpClient(pccm, params);

//        //设置代理 DNS
//        HttpHost proxy = new HttpHost("10.112.24.30", 8019);
//        httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

        return httpclient;
    }

    /**
     * 双向ssl 设置客户端证书
     * @return
     */
    public static SSLSocketFactory getBidirectionalSSL() throws Exception {

        //客户端证书库,上面生成的kclient.keystore
        File certFile = new File(GetConfigUtil.getProjectConfig("ssl.client.keystore"));
        KeyStore ks = null;
        try {
            ks = KeyStore.getInstance("JKS");
        } catch (KeyStoreException e) {
            throw new Exception(e);
        }
        //密钥库密码 123456
        String password = "";
        try {
            password = GetConfigUtil.getProjectConfig("client.store.file.password");
            ks.load(new FileInputStream(certFile), password.toCharArray());
        } catch (NoSuchAlgorithmException e) {
            throw new Exception(e);
        } catch (CertificateException e) {
            throw new Exception(e);
        } catch (FileNotFoundException e) {
            throw new Exception(e);
        } catch (IOException e) {
            throw new Exception(e);
        }
        KeyManagerFactory kmf = null;
        try {
            kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        } catch (NoSuchAlgorithmException e) {
            throw new Exception(e);
        }
        try {
            kmf.init(ks, password.toCharArray());
        } catch (UnrecoverableKeyException e) {
            throw new Exception(e);
        } catch (KeyStoreException e) {
            throw new Exception(e);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception(e);
        }

        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("TLS");
        } catch (NoSuchAlgorithmException e) {
            throw new Exception(e);
        }

        try {
            sslContext.init(kmf.getKeyManagers(), getTrustManager(), null);
        } catch (KeyManagementException e) {
            throw new Exception(e);
        } catch (Exception e) {
            throw new Exception(e);
        }
        SSLSocketFactory factory = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        return factory;
    }

    /**
     * 双向SSL 认证服务器的证书
     * @return
     * @throws Exception
     */
    public static TrustManager[] getTrustManager() throws Exception{

        TrustManager[] trustManager=null;
        String password = "";
        //上面生成的kclienttrust.keystore
        String publicKey = GetConfigUtil.getProjectConfig("ssl.clienttrust.keystore");

        if(null ==publicKey ||"".equals(publicKey)){
            throw new RuntimeException("信任库证书未配置");
        }else{
            //第三方机构服务器的公钥证书
            File publicFile = new File(publicKey);
            KeyStore pks = KeyStore.getInstance("JKS");
            password = GetConfigUtil.getProjectConfig("client.trust.file.password");
            pks.load(new FileInputStream(publicFile), password.toCharArray());
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            tmf.init(pks);
            trustManager = tmf.getTrustManagers();
        }

        return trustManager;
    }

}

GetConfigUtil我就不贴了吧,还是要自己动动脑子的,不能彻底无脑CV流~~

算了我还是分享出来吧

项目地址:https://gitee.com/defense-of-the-anciant2/market-purchase

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值