SSL/TLS双向认证实现(JAVA、TOMCAT)

双向认证,客户端和服务端都会互相认证,即双发之间要证书交换

证书生成

需服务端和客户端都生成证书,并进行证书交换(通常是服务端将server.cer发送给客户端,客户端将client.cer发送给服务端,然后各自导入自己的信任证书库)
服务端:
1. 生成jks格式服务器端的keystore文件,keypass与storepass需一致,因tomcat server.xml中仅一处keystorePass
keytool -genkey -alias server -keystore D:\skeystore.jks -keypass 123456 -storepass 123456 -keyalg RSA -keysize 512 -validity 3650 -v -dname “CN={hostname},O=company,OU=company, L=city,ST=province”
注:{hostname}取服务器的hostname值
2. 从keystore中导出别名为server的服务端证书
keytool -export -alias server -keystore D:\skeystore.jks -storepass 123456 -file D:\server.cer
3. 将server.cer导入客户端的信任证书库truststore.jks
keytool -import -alias trustServer -file D:\server.cer -keystore D:\ctruststore.jks -storepass 123456
客户端:
4. 生成jks格式客户端的keystore文件,keypass与storepass需一致
keytool -genkey -alias client -keystore ckeystore.jks -keypass 123456 -storepass 123456 -keyalg RSA -keysize 512 -validity 3650 -v -dname “CN=someone,O=company,OU=company, L=city,ST=province”
5. 从keystore中导出别名为client的客户端证书
keytool -export -alias client -keystore ckeystore.jks -storepass 123456 -file client.cer
6. 将client.cer导入服务端的信任证书库struststore.jks
keytool -import -alias trustClient -file client.cer -keystore struststore.jks -storepass 123456

注:该实现所用到的服务端证书库:skeystore.jks,struststore.jks;客户端证书库:ckeystore.jks,ctruststore.jks

配置tomcat环境中的server.xml

将证书文件skeystore.jks,struststore.jks拷贝至tomcat的conf目录下

  <Connector port="8443" protocol="HTTP/1.1" 
        SSLEnabled="true" clientAuth="true" sslProtocol="TLS" 
        maxThreads="150" scheme="https" secure="true"
        keystoreFile="conf/skeystore.jks" keystorePass="123456"  
        truststoreFile="conf/struststore.jks" truststorePass="123456" />

服务端、客户端

服务端web.xml

<security-constraint>  
    <web-resource-collection>  
        <web-resource-name>ssl</web-resource-name>  
        <url-pattern>/*</url-pattern>  //强制所有请求走https
   </web-resource-collection>  
   <user-data-constraint>  
       <transport-guarantee>CONFIDENTIAL</transport-guarantee>  
   </user-data-constraint>
</security-constraint>

客户端代码(需要引入jar文件httpcore-4.0.1.jar,httpclient-4.0.1.jar,httpmime-4.0.1.jar)

package com.ssl.http;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 *  带证书认证请求处理
 * @author blue_coat
 * @date 2015-7-26
 */
public class HttpClientWithCA {
    public CertificateStore store = new CertificateStore ();
    store.keyFile = "D:\ckeystore.jks";
    store.keyPass = "123456";
    store.trustFile = "D:\ctruststore.jks";
    store.trustPass = "123456";

    public final static void main(String[] args) throws Exception {
        String result = oneAuthSSL("https://localhost:8443/ssl", "", store);
        ......
    }

    /**
     * 双向认证接口
     */
    public String doubleAuthSSL(String url, String data, CertificateStore store) throws Exception {
        String result = null;
        DefaultHttpClient httpclient = new DefaultHttpClient();
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        FileInputStream keyStoreIn = new FileInputStream(new File(store.keyFile));  
        FileInputStream trustStoreIn = new FileInputStream(new File(store.trustFile));
        try {
            keyStore.load(keyStoreIn, store.keyPass.toCharArray());
            trustStore.load(trustStoreIn, store.trustPass.toCharArray());
        } finally {
            keyStoreIn.close();
            trustStoreIn.close();
        }
        SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore, store.keyPass, trustStore);
        Scheme sch = new Scheme("https", socketFactory, 8443);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);
        HttpGet httpget = new HttpGet(url);
        System.out.println("executing: " + httpget.getRequestLine()); 
        HttpResponse response = httpclient.execute(httpget);
        HttpEntity entity = response.getEntity();
        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        if (entity != null) {
            System.out.println("Response Content-length: " + entity.getContentLength());
            result = EntityUtils.toString(entity);
            entity.consumeContent();
        }
        // 关闭连接,腾出内存空间
        httpclient.getConnectionManager().shutdown();
        return result;
    }

    /**
     * 双向认证证书信息
     */
    public class CertificateStore {
        /**
         * 客户端证书库
         */
        public String keyFile= "";
        /**
         * 客户端证书密码
         */
        public String keyPass= "";
        /**
         * 服务器证书信任证书库
         */
        public String trustFile= "";
        /**
         * 服务器证书信任证书库密码
         */
        public String trustPass= "";
    }
}

运行后调用成功,打印信息如下:

executing: GET https://localhost:8443/ssl HTTP/1.1
----------------------------------------
HTTP/1.1 200 OK
Response content length: 8432
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值