HTTPS的单向与双向认证

HTTPS的请求相比http请求,增加了证书认证步骤:

HTTPS的单向与双向认证_第1张图片

 

单向认证中,需要客户端导入服务端证书即可。

使用keytool即可:

keytool -import  -alias 别名 -keystore cacerts -file 证书文件 -trustcacerts

keytool的使用参数大致列举如下:

-genkey #创建一个默认文件 .keystore,还会产生一个mykey的别名;这个.keystore 里面包含公钥、私钥和证书;
#注:不要用genseckey 选项 会包ERROR:
#keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect
-alias # 对我们生成的.keystore 进行指认别名;如果没有默认是mykey
-keypass # 指定别名条目的密码【私密的密码】
-keyalg # 指定密钥的算法 RSA/DSA 默认(没有这个选项)是DSA
-keysize # 指定密钥的长度;默认是1024
-validity # 密钥的有效时间 单位是天: 10950 = 365 * 30 30年;默认是90天
-keystore # 指定genkey生成的keystore 的名字;【文件可以是绝对路径】
-storepass# 指定keystore 的密码
-dname "CN=CSM,OU=TB,O=AB,L=HZ,ST=ZJ,C=CH" #CN 名字 ,OU 组织单位,O 组织名称 L 城市 ST 省份 C 国

 

双向认证较为复杂,大致流程如上图所示,需要准备四个文件,分别为client的keystore和truststore,server的keystore和truststore。

需要双方将对方的证书都授权到各自的truststore中,使用keystore中的key(密钥)进行访问。

对于客户端:

1.生成密钥Key

openssl genrsa -des3 -out client.key 1024

2.生成证书(此步骤可以根据key生成CA证书,如Symantec)

openssl req -new -key client.key -out client.csr

3.根据key和证书生成pcs12文件

openssl pkcs12 -export -in file name> -inkey file name> -name yourname -out yourname.p12

4. 根据pcs12文件生成jks(keystore)

keytool -importkeystore -deststorepass  destkeypass  -destkeystore your.jks -srckeystore yourname.p12 -srcstoretype PKCS12 -srcstorepass  -alias youralias

5.对于Java客户端,调用代码如下:

SSL类:

public SSLClient() throws Exception{  
        super();  
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        FileInputStream instream =
                new FileInputStream(new File(KEYSTORE_FILE));
                try {
                        keyStore.load(instream,KEYSTORE_PASSWORD.toCharArray());
                } finally {
                             instream.close();
                }
                // Trust own CA and allself-signed certs
                SSLContext ctx= SSLContexts.custom()
                .loadKeyMaterial(keyStore,KEYSTORE_PASSWORD.toCharArray())
                .build();
                
        KeyManager[] kms = null;  
        //Key Store  
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");   
        keyManagerFactory.init(keyStore, KEYSTORE_PASSWORD.toCharArray());   
        kms = keyManagerFactory.getKeyManagers();  
        
        ctx = SSLContext.getInstance("TLSv1.2");
        SSLContext.setDefault(ctx);
        
        X509TrustManager tm = new X509TrustManager() {  
                @Override  
                public void checkClientTrusted(X509Certificate[] chain,  
                        String authType) throws CertificateException {  
                }  
                @Override  
                public void checkServerTrusted(X509Certificate[] chain,  
                        String authType) throws CertificateException {  
                }  
                @Override  
                public X509Certificate[] getAcceptedIssuers() {  
                    return null;  
                }  
        };  
        ctx.init(kms, new TrustManager[]{tm}, null);  
        SSLSocketFactory ssf = new SSLSocketFactory(ctx,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  
        
        ClientConnectionManager ccm = this.getConnectionManager();  
        SchemeRegistry sr = ccm.getSchemeRegistry();  
        sr.register(new Scheme("https", 443, ssf));  

https请求类:

public static String doPost(String url,String params,Mapheaders,String charset){  
        HttpClient httpClient = null;  
        HttpPost httpPost = null;  
        String result = null;  
        try{  
            httpClient = new SSLClient();  
            httpPost = new HttpPost(url);  
            if (headers != null) {  
                Set keys = headers.keySet();  
                for (Iterator i = keys.iterator(); i.hasNext();) {  
                    String key = (String) i.next();  
                    httpPost.addHeader(key, headers.get(key));  
                      
                }  
            }  

            //设置参数  
//            List list = new ArrayList();  
//            Iterator iterator = map.entrySet().iterator();  
//            while(iterator.hasNext()){  
//                Entry elem = (Entry) iterator.next();  
//                list.add(new BasicNameValuePair(elem.getKey(),elem.getValue()));  
//            }  
//            if(list.size() > 0){  
//                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,charset);  
//                httpPost.setEntity(entity);  
//            }  
            StringEntity entity = new StringEntity(params, "UTF-8"); 
            httpPost.setEntity(entity);
            HttpResponse response = httpClient.execute(httpPost);  
            if(response != null){  
                HttpEntity resEntity = response.getEntity();  
                if(resEntity != null){  
                    result = EntityUtils.toString(resEntity,charset);  
                }  
            }  
        }catch(Exception ex){  
            ex.printStackTrace();  
        }  
        return result; 

调用post方法即可进行https请求。

另外附上两个常用keytool指令:

查询证书内容:

keytool -list -v -keystore debug.keystore 

删除指定别名证书:

keytool -delete -alias *** -keystore yourkeystore

 

转载于:https://www.cnblogs.com/connorRen/p/7448171.html

你可能感兴趣的:(HTTPS的单向与双向认证)