java Android 中的“javax.net.ssl.SSLException:不受信任的服务器证书”异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3055174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 00:07:53  来源:igfitidea点击:

"javax.net.ssl.SSLException: Not trusted server certificate" exception in Android

javaandroid

提问by user342823

I am getting this exception when I am trying to hit HTTPS URL (.Net Webservice) from my Android app:

当我尝试从我的 Android 应用程序访问 HTTPS URL (.Net Webservice) 时出现此异常:

javax.net.ssl.SSLException: Not trusted server certificate

javax.net.ssl.SSLException:不受信任的服务器证书

Here is my code:

这是我的代码:

HttpParams myParams = new BasicHttpParams();
HttpProtocolParams.setVersion(myParams, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(myParams, "utf-8");
myParams.setBooleanParameter("http.protocol.expect-continue", false);


HttpConnectionParams.setConnectionTimeout(myParams, 100000); 
HttpConnectionParams.setSoTimeout(myParams, 100000);

//
KeyStore trusted;
try {  

        trusted = KeyStore.getInstance("pkcs12");
        trusted.load(null, "".toCharArray());
        SSLSocketFactory sslf = new SSLSocketFactory(trusted);
  sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

  SchemeRegistry schemeRegistry = new SchemeRegistry(); 
  schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

  schemeRegistry.register(new Scheme("https", sslf, 443));    
  ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(myParams, schemeRegistry);


  httpClient = new DefaultHttpClient(manager, myParams); 
  } catch (KeyStoreException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (NoSuchAlgorithmException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (CertificateException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (KeyManagementException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (UnrecoverableKeyException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }         
    //

    localContext = new BasicHttpContext();  

    httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109); 

    httpPost = new HttpPost("https://...."); 
    response = null; 

    StringEntity tmp = null;         

    httpPost.setHeader("SOAPAction", "SoapActionURL"); 

    if (contentType != null) { 
        httpPost.setHeader("Content-Type", contentType); 
    } else { 
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded"); 
    } 

    try { 
        tmp = new StringEntity(data,"UTF-8"); 
    } catch (UnsupportedEncodingException e) { 
        Log.e("Your App Name Here", "HttpUtils : UnsupportedEncodingException : "+e); 
    } 

    httpPost.setEntity(tmp); 

    try { 

        response = httpClient.execute(httpPost,localContext); 

        if (response != null) { 
            ret = EntityUtils.toString(response.getEntity()); 
        } 
    } catch (Exception e) { 
        Log.e("Your App Name Here", "HttpUtils: " + e); 
    }  

回答by EpicPandaForce

KeyStore trusted;
try {  

        trusted = KeyStore.getInstance("pkcs12");
        trusted.load(null, "".toCharArray());
        SSLSocketFactory sslf = new SSLSocketFactory(trusted);

You don't have a truststore which stores the certificate of the server you're connecting to, and that server you are connecting to is not trusted. To fix this, you need to make a keystore file using Keytool (I created a BKS keystore and loaded it with SpongyCastle provider) as a truststore.

您没有存储您要连接的服务器的证书的信任库,并且您要连接的服务器不受信任。要解决此问题,您需要使用 Keytool(我创建了一个 BKS 密钥库并使用 SpongyCastle 提供程序加载它)作为信任库来制作一个密钥库文件。

keytool -importcert -file servercert.crt -alias mykey -keystore truststore.jks -storetype BKS -providerpath bcprov-jdk15on-151.jar -provider org.bouncycastle.jce.provider.BouncyCastleProvider

Also, I used a newer version of Apache HttpClient, specifically http://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient-android/4.3.5

另外,我使用了较新版本的 Apache HttpClient,特别是http://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient-android/4.3.5

public KeyStore initializeTrustStore(Context context)
{
    KeyStore keyStore = null;
    try
    {
        keyStore = KeyStore.getInstance("BKS", BouncyCastleProvider.PROVIDER_NAME);
        InputStream inputStream = context.getResources().openRawResource(R.raw.truststore);
        try
        {
            keyStore.load(inputStream, "password".toCharArray());
        }
        finally
        {
            inputStream.close();
        }
    }


    KeyStore trustStore = loadTrustStore(context);
    SSLContext sslcontext = null;
    CloseableHttpClient httpclient = null;

        SSLContextBuilder sslContextBuilder = SSLContexts.custom()
            .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy());
        sslcontext = sslContextBuilder.build();

        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
            sslcontext, new String[] {"TLSv1"}, null,
            SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
        );
        httpclient = HttpClients
            .custom()
            .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
            .setSSLSocketFactory(sslsf).build();
        CloseableHttpResponse response = httpclient.execute(httpUriRequest);
        try
        {
            HttpEntity entity = response.getEntity();
            //do things with response here
            if(entity != null)
            {
                entity.consumeContent();
            }
        }
        finally
        {
            response.close();
        }