單向驗證:
生成證書:
keytool -genkey -alias zhy_server -keyalg RSA -keystore zhy_server.jks -validity 3600 -storepass 123456 -ext san=ip:192.168.1.113(你本地的ip地址)
tomcat配置:
<Connector SSLEnabled="true" acceptCount="100" clientAuth="false"
disableUploadTimeout="true" enableLookups="true" keystoreFile="C:/Users/Administrator/zhy_server.jks" keystorePass="123456" maxSpareThreads="75"
maxThreads="200" minSpareThreads="5" port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS"
/>
雙向驗證:
生成證書:
客戶端證書:
keytool -genkey -alias zhy_client -keyalg RSA -keystore zhy_client.jks -validity 3600 -storepass 123456 -ext san=ip:192.168.1.113
keytool -export -alias zhy_client -file zhy_client.cer -keystore zhy_client.jks -storepass 123456
將公鑰放進jks文件中再配置到tomcat,
keytool -import -alias zhy_client -file zhy_client.cer -keystore zhy_client_for_sever.jks
tomcat配置:
<Connector SSLEnabled="true" acceptCount="100"
disableUploadTimeout="true" enableLookups="true" keystoreFile="C:/Users/Administrator/zhy_server.jks" keystorePass="123456" maxSpareThreads="75"
maxThreads="200" minSpareThreads="5" port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS"
clientAuth="true"
truststoreFile="C:/Users/Administrator/zhy_client_for_sever.jks"
/>
android客戶端公鑰變成字符串,使用命令:
keytool -printcert -rfc -file zhy_server.cer
HttpsUrlConnection使用
1、直連
Android系統校驗服務端數字證書的合法性,用可信CA簽發的數字證書的網站纔可以正常訪問,私有CA簽發的數字證書的網站無法訪問。
示例:
URL url = new URL("https://www.alipay.com/");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
InputStream input = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
result.append(line);
}
2、自己生成的證書
單向:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(in);
in.close();
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, null);
keystore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keystore);
X509TrustManager trustManager = null;
trustManager = new MyTrustManager(chooseTrustManager(tmf.getTrustManagers()));
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[]{trustManager}, new SecureRandom());
URL url = new URL(urlString);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream input = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
result.append(line);
}
其中MyTrustManager先會用系統信任的證書列表去校驗服務器的證書,如果不是CA簽發的,再用預埋的服務器端公鑰證書(上面的in輸入流代表的證書)處理。
雙向:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream in = activity.getAssets().open("zhy_server.cer");
Certificate ca = cf.generateCertificate(in);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null, null);
keystore.setCertificateEntry("ca", ca);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keystore);
/*雙向驗證*/
KeyStore clientKeyStore = KeyStore.getInstance("bks");
//Java平臺默認識別jks格式的證書文件,但是android平臺只識別bks格式的證書文件。用Portecle進行轉化
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, "123456".toCharArray());
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
URL url = new URL("https://10.5.20.34:8443/");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream input = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
result.append(line);
}
Fiddler查看
1、用預埋的證書校驗服務器,也查看不到響應數據
2、沒做校驗、信任所有的話,能看到響應數據
參考資料:
Android安全開發之安全使用HTTPS
Android Https相關完全解析 當OkHttp遇到Https
使用HTTPS與SSL
源碼:
https://yunpan.cn/cvtqXAKJwn44S (提取碼:25fc)