【问题标题】:javax.net.ssl.SSLException: hostname in certificate didn't match in Androidjavax.net.ssl.SSLException:证书中的主机名在 Android 中不匹配
【发布时间】:2014-11-29 19:40:59
【问题描述】:

我正在更新 android 应用程序的 Web 服务 URL,我们使用的是 https 协议。我看到我当前的 https URL 正在工作,但现在我们正在迁移到新域,然后它就会产生问题。

我已经检查了 stackoverflow 上的许多线程,例如 javax.net.ssl.SSLException: hostname in certificate didn't match android,但没有找到任何好的答案,主要是回答绕过此安全性或全部允许。

javax.net.ssl.SSLException:证书中的主机名不匹配:

//HttpGet getMethod = new HttpGet(String.format(httpURL));
HttpGet getMethod = new HttpGet(httpURL);
DefaultHttpClient client = new DefaultHttpClient();
ResponseHandler<String> responseHandler = new BasicResponseHandler();
HttpParams params = client.getParams();
params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 60000);
params.setParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
client.setParams(params);
responseBody = client.execute(getMethod, responseHandler);
responseBody = responseBody.trim();

提前致谢。

【问题讨论】:

  • 您是否在浏览器中尝试了相同的 url,您是否收到任何证书错误??
  • @Panther 没有错误,它正在浏览器中运行

标签: android web-services ssl https


【解决方案1】:

似乎最好的解决方案是使用 HttpsUrlConnection 而不是 HttpGet。

URL url = new Url(httpURL);
HttpURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setReadTimeout(60000);
urlConnection.setConnectTimeout(60000);
urlConnection.setRequestMethod("GET");
urlConnection.setDoInput(true);

urlConnection.connect();

然后使用 InputStream 获取响应体。

InputStream inputStream = urlConnection.getInputStream();

【讨论】:

    【解决方案2】:

    如果它在浏览器中运行但在应用程序中无法运行,则可能是缺少 SNI 支持的问题,请参阅Why does android get the wrong ssl certificate? (two domains, one server)

    【讨论】:

    • 是的,它在浏览器中运行,而不是在应用程序中。对于这个 ssl 连接,我们是否还必须在应用程序中保留一些证书?
    • 不,你必须使用支持 SNI 的东西,或者你必须有一个单独的 HTTPS 服务器 IP 地址,这样你就不需要使用 SNI。有关详细信息,请参阅链接的问题。
    【解决方案3】:

    感谢Make HTTPS / HTTP Request in Android

    添加一个 Java 类 CustomSSLSocketFactory.java

     import java.io.IOException;
     import java.net.Socket;
     import java.net.UnknownHostException;
     import java.security.KeyManagementException;
     import java.security.KeyStore;
     import java.security.KeyStoreException;
     import java.security.NoSuchAlgorithmException;
     import java.security.UnrecoverableKeyException;
     import java.security.cert.CertificateException;
     import java.security.cert.X509Certificate;
     import javax.net.ssl.SSLContext;
     import javax.net.ssl.TrustManager;
     import javax.net.ssl.X509TrustManager;
     import org.apache.http.conn.ssl.SSLSocketFactory;
    
     public class CustomSSLSocketFactory extends SSLSocketFactory{
    SSLContext sslContext = SSLContext.getInstance("TLS");
    /**
     * Generate Certificate for ssl connection
     * @param truststore
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     * @throws KeyStoreException
     * @throws UnrecoverableKeyException
     */
    public CustomSSLSocketFactory(KeyStore truststore)
            throws NoSuchAlgorithmException, KeyManagementException,
            KeyStoreException, UnrecoverableKeyException {
        super(truststore);
        TrustManager tm = new X509TrustManager(){
            @Override
            public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                    throws CertificateException {
            }
            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                                           String authType) throws CertificateException {
            }
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        sslContext.init(null, new TrustManager[] {tm}, null);
    }
    
    @Override
    public Socket createSocket(Socket socket, String host, int port,
                               boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port,
                autoClose);
    }
    
    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
     }
    

    在你的代码中

        String cloud_url="https://www.google.com";
        HttpClient client = new DefaultHttpClient();
            if(cloud_url.toLowerCase().contains("https://")){
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(null, null);
                SSLSocketFactory sf = new CustomSSLSocketFactory(trustStore);
                sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    
                HttpParams params = new BasicHttpParams();
                SchemeRegistry registry = new SchemeRegistry();
                registry.register(new Scheme("https", sf, 443));
    
                ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
                client= new DefaultHttpClient(ccm, params);
            }
    
    
            HttpGet request= new HttpGet( );
            request.setURI(new URI( cloud_url));
            HttpResponse response = client.execute(request);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-18
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      相关资源
      最近更新 更多