雙向認證可以提高安全性 單向認證的HTTPS是可以被抓包的 雙向認證別人沒有你客戶端證書和密碼的情況下是無法抓包的 服務端檢測到證書無效會拒絕連接
首先 取得證書機構頒發的證書文件 這裏以騰訊雲的免費1年SSL證書爲例
這裏我們先部署Nginx的 需要Nginx目錄裏面的兩個文件 和根目錄的csr文件,先把他複製出來到一個文件夾,文件重命名一下方便敲命令。
首先cmd進入文件夾 輸入命令生成服務端的cer文件
openssl x509 -req -days 36500 -sha1 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.cer
至此服務端的證書都不用動了
接下來是生成客戶端用的證書用於被服務端信任(需要使用服務端的cer簽發客戶端的證書才能被信任)
openssl genrsa -out client.key 2048
openssl req -new -out client.csr -key client.key
兩個命令生成客戶端的主要證書文件 其中生成csr(第二條命令)需要輸入各種信息 隨便填 不填一直回車也行無所謂 生成完畢的2個客戶端證書⤵️
接下來就是重點了
使用服務端的cer key csr請求生成客戶端的cer文件(如果需要新的或者更多的客戶端證書 一樣用服務端的簽發客戶端的證書就行)
openssl x509 -req -days 36500 -sha1 -extensions v3_req -CA ca.cer -CAkey ca.key -CAserial ca.srl -CAcreateserial -in client.csr -out client.cer
生成兩個新文件如下圖 注意 ca.srl是剛剛的命令生成的
生成完畢就算完了。
最後使用客戶端證書 比如我要在Java程序裏使用證書 我要吧客戶端的證書合成一個p12格式的證書 生成時輸入密碼 最好複雜一些 因爲是給客戶端用的
openssl pkcs12 -export -clcerts -inkey client.key -in client.cer -out client.p12
生成完畢就可以在程序中使用證書去請求服務端了
下面給出Nginx的配置和效果
保存配置重新加載Nginx配置文件然後請求我們的服務器就可以看到我們的請求已經被拒絕了
我們要訪問怎麼辦呢 這裏使用OKHTTP來請求我們的服務器看看
狀態碼400 證書錯誤
接下來添加我們的客戶端證書到請求中(我這裏的demo客戶端不校驗服務器的證書 懶得寫 正常要寫上的 這種資料網上很多就不講了)
給出代碼
KeyStore clientKeyStore = KeyStore.getInstance("PKCS12");
clientKeyStore.load(new FileInputStream(new File("/Users/Smile/ssl/client.p12")), "123456".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(clientKeyStore, "123456".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
X509TrustManager x509TrustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
};
sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[]{x509TrustManager}, null);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslContext.getSocketFactory(), x509TrustManager);
Response execute = builder.build()
.newCall(new Request.Builder()
.get()
.url("https://www.dexfun.com")
.build())
.execute();
System.out.println(execute.code());
System.out.println(execute.body().string());
運行代碼 已經可以看到下圖 狀態碼200 Welcome to nginx! 請求成功(如果要給Android客戶端使用 需要把證書轉換成bks格式的證書)
接下來測試抓包
抓包工具已經配置過工具自帶的root證書也無法抓到我的雙向認證
而單向認證的HTTPS就能抓包成功如下圖
接下來是Tomcat配置雙向認證
先生成客戶端證書
keytool -genkeypair -alias client -keyalg RSA -validity 3650 -keypass 123456 -storepass 123456 -keystore client.jks
然後導出客戶端證書
keytool -export -alias client -file client.cer -keystore client.jks -storepass 123456
接下來是從頒發的Tomcat證書導出
keytool -export -alias 你的域名(和證書對應 www.dexfun.com) -file server.cer -keystore server.jks -storepass 證書密碼(文件夾裏面有個txt文本文檔裏面有 頒發的)
重點 交換證書
keytool -import -v -alias server -file server.cer -keystore truststore.jks -storepass 123456
#吧客戶端的證書導入到服務端(讓服務端信任這個客戶端的證書 這裏和Nginx配置證書不太 如果要多個客戶端證書 可能要在導入到server.keystore文件中 我沒測試 這裏我就不多嗶嗶了)
keytool -import -v -alias client -file client.cer -keystore server.keystore -storepass 123456
然後修改server.xml文件,配置8443端口
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="${catalina.base}/conf/server.keystore" keystorePass="123456"
truststoreFile="${catalina.base}/conf/server.keystore" truststorePass="123456"/>
keystoreFile:指定服務器密鑰庫,我放在配置文件同目錄 僅供參考。
- keystorePass:密鑰庫生成時的密碼
- truststoreFile:受信任密鑰庫,和密鑰庫相同即可
- truststorePass:受信任密鑰庫密碼
將client.jks和truststore.jks分別轉換成client.bks和truststore.bks,然後放到android客戶端的assert目錄下 然後正常使用就行
OK👌 全劇終emmm