Android自簽名證書問題
服務器給了一個自簽名證書,ios那邊可以使用,Android不能使用! 坑,自己搭服務器簽名驗證!,想看問題原因,直接移步最后!
生成自簽名證書
//生成 rao.key,后面位數可以指定 需要設置密碼,需要記住后面驗證需要輸入
openssl genrsa -idea -out rao.key 1024
// 生成證書請求 csr 文件,輸入key密碼,依次輸入組織名稱等信息 其中 Common Name 為域名或者ip,最后輸入的密碼為修改csr文件需要配置的
openssl req -new -key rao.key -out rao.csr
// 基於上面的文件生成證書,有效期一年
openssl x509 -req -days 365 -in rao.csr -signkey rao.key -out rao.crt
nginx配置https證書
//示例
server {
...
listen 443;
server_name www.rao.com;
ssl on;
#證書文件路徑
ssl_certificate /etc/nginx/ssl_key/applelife.crt;
#key文件路勁
ssl_certificate_key /etc/nginx/ssl_key/applelife.key;
...
location / {
...
}
}
其他命令
//停止 需要輸入設置的key密碼
nginx -s stop -c /etc/nginx/nginx.conf
//啟動
nginx -c /etc/nginx/nginx.conf
//檢查語法
nignx -tc /etc/nginx/nginx.cof
//查看端口是否啟用
netstat -luntp |grep 443
Android https代碼
可以參考google官方代碼 https://developer.android.com/training/articles/security-ssl
SSLContext provideSSLContext(Application app) {
try {
//加載需要信任的證書,crt格式和cer格式都可以,在windows中可以互轉
//InputStream serverCer = app.getAssets().open("server.crt");
InputStream serverCer = app.getResources().openRawResource(R.raw.rao);
//InputStream fiddlerCer = app.getAssets().open("fiddlerroot.cer");
//InputStream fiddlerCer=app.getResources().openRawResource(R.raw.fiddlerRoot);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
//如果要信任多個證書,就會存在多個serverCer,那么要分別加載到keyStore中
//別名可以隨便命名,但不能重復
keyStore.setCertificateEntry("server", certificateFactory.generateCertificate(serverCer));
// keyStore.setCertificateEntry("fiddler", certificateFactory.generateCertificate(fiddlerCer));
try {
serverCer.close();
//fiddlerCer.close();
} catch (IOException e) {
e.printStackTrace();
}
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.
getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//初始化keystore
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
return sslContext;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
...
builder.sslSocketFactory(sslContext.getSocketFactory());
...
問題異常
// 連接異常
HTTP FAILED: javax.net.ssl.SSLPeerUnverifiedException: Hostname 183.230.dd.156 not verified:
查找資料 在生成 .csr 的時候填入的很多信息中,包含了一個叫做 Common Name(CN)的 field,以前這個 CN 可以直接填寫 server name 或者 IP,但之后規定了需要使用 Subject Alternative Name(SAN) 來指定 server name, IP
參考地址 https://tools.ietf.org/html/rfc2818#section-3.1
證書添加 subjectAltName
以現有證書添加 subjectAltName
// 命令
openssl x509 -req -extfile <(printf "subjectAltName=IP:localhost,DNS:www.xxx.com") -days 365 -in rao.csr -CA rao.crt -CAkey rao.key -CAcreateserial -out rao1.crt
至此 Android https問題得到解決
參考:https://www.jianshu.com/p/a56b2234da1a
參考 :https://moxo.io/blog/2017/08/01/problem-missing-subjectaltname-while-makeing-self-signed-cert/