【问题标题】:Cannot implement SSL connection to server using self-signed certificate无法使用自签名证书实现与服务器的 SSL 连接
【发布时间】:2015-08-22 14:44:35
【问题描述】:

我正在尝试向应用程序服务器发送 HTTP 请求,并使用 SSL 进行保护。我有一个来自服务器团队的自签名 X.509 证书。我按照documentation 的教程进行操作,但仍然得到了SSLHandshakeExceptionjava.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

我正在使用此代码:

CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");

AssetManager assManager = ShoppingHelperApp.getContext().getAssets();
InputStream is = assManager.open("keystore2.crt");
InputStream caInput = new BufferedInputStream(is);
Certificate ca = cf.generateCertificate(caInput);
caInput.close();

String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);

String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

context = SSLContext.getInstance("TLS");
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(context.getSocketFactory());

有人知道如何解决吗?

【问题讨论】:

    标签: android ssl https ssl-certificate x509certificate


    【解决方案1】:

    这就是我设置OkHttpClient的方式:

    OkHttpClient client = new OkHttpClient();
            try {
                KeyStore keyStore = SSLUtils.getKeyStore(applicationContext);
                SSLContext sslContext = SSLContext.getInstance("SSL");
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustManagerFactory.init(keyStore);
                sslContext.init(null,trustManagerFactory.getTrustManagers(), new SecureRandom());
                client.setSslSocketFactory(sslContext.getSocketFactory());
            } catch (Exception e) {
                Log.d("AppName", "cannot create http client", e);
            }
    

    SSLUtils类:

    import android.content.Context;
    import android.content.res.AssetManager;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.InputStream;
    import java.security.KeyStore;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    
    public class SSLUtils {
    
        private static final Logger LOG = LoggerFactory.getLogger(SSLUtils.class.getSimpleName());
    
        public static KeyStore getKeyStore(Context context) {
            KeyStore keyStore = null;
            try {
                AssetManager assetManager = context.getAssets();
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                InputStream caInput = assetManager.open("cert.pem");
                Certificate ca;
                try {
                    ca = cf.generateCertificate(caInput);
                    LOG.debug("ca={}", ((X509Certificate) ca).getSubjectDN());
                } finally {
                    caInput.close();
                }
    
                String keyStoreType = KeyStore.getDefaultType();
                keyStore = KeyStore.getInstance(keyStoreType);
                keyStore.load(null, null);
                keyStore.setCertificateEntry("ca", ca);
            } catch (Exception e) {
                LOG.error("Error during getting keystore", e);
            }
            return keyStore;
        }
    }
    

    将您的cert.pem 文件放在assets 目录中。
    我使用slf4android 进行日志记录,但您当然可以使用标准的Log 类。

    希望对你有帮助:)

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-10
    • 2023-03-15
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    相关资源
    最近更新 更多