无法使用自签名证书实现与服务器的SSL连接

时间:2015-06-08 08:04:01

标签: android ssl https ssl-certificate x509certificate

我正在尝试向应用服务器发送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());

有没有人知道如何解决它?

1 个答案:

答案 0 :(得分:0)

这就是我设置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类。

希望它会对你有所帮助:)。