Android Https自簽名證書問題!


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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM