HTTPS的请求相比http请求,增加了证书认证步骤:
单向认证中,需要客户端导入服务端证书即可。
使用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 -infile name> -inkey file name> -name yourname -out yourname.p12
4. 根据pcs12文件生成jks(keystore)
keytool -importkeystore -deststorepassdestkeypass -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 // 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;) iterator.next();
调用post方法即可进行https请求。
另外附上两个常用keytool指令:
查询证书内容:
keytool -list -v -keystore debug.keystore
删除指定别名证书:
keytool -delete -alias *** -keystore yourkeystore