Java HTTPS连接安卓

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/995514/
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-08-11 22:00:29  来源:igfitidea点击:

Https Connection Android

javaandroidssl

提问by Sam97305421562

I am doing a https post and I'm getting an exception of ssl exception Not trusted server certificate. If i do normal http it is working perfectly fine. Do I have to accept the server certificate somehow?

我正在做一个 https 帖子,我收到了 ssl 异常不受信任的服务器证书的异常。如果我做正常的 http,它工作得很好。我是否必须以某种方式接受服务器证书?

采纳答案by Nate

I'm making a guess, but if you want an actual handshake to occur, you have to let android know of your certificate. If you want to just accept no matter what, then use this pseudo-code to get what you need with the Apache HTTP Client:

我在猜测,但是如果您希望发生实际的握手,则必须让 android 知道您的证书。如果你无论如何都想接受,那么使用这个伪代码来获得你需要的 Apache HTTP 客户端:

SchemeRegistry schemeRegistry = new SchemeRegistry ();

schemeRegistry.register (new Scheme ("http",
    PlainSocketFactory.getSocketFactory (), 80));
schemeRegistry.register (new Scheme ("https",
    new CustomSSLSocketFactory (), 443));

ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager (
    params, schemeRegistry);


return new DefaultHttpClient (cm, params);

CustomSSLSocketFactory:

自定义SSLSocketFactory:

public class CustomSSLSocketFactory extends org.apache.http.conn.ssl.SSLSocketFactory
{
private SSLSocketFactory FACTORY = HttpsURLConnection.getDefaultSSLSocketFactory ();

public CustomSSLSocketFactory ()
    {
    super(null);
    try
        {
        SSLContext context = SSLContext.getInstance ("TLS");
        TrustManager[] tm = new TrustManager[] { new FullX509TrustManager () };
        context.init (null, tm, new SecureRandom ());

        FACTORY = context.getSocketFactory ();
        }
    catch (Exception e)
        {
        e.printStackTrace();
        }
    }

public Socket createSocket() throws IOException
{
    return FACTORY.createSocket();
}

 // TODO: add other methods like createSocket() and getDefaultCipherSuites().
 // Hint: they all just make a call to member FACTORY 
}

FullX509TrustManager is a class that implements javax.net.ssl.X509TrustManager, yet none of the methods actually perform any work, get a sample here.

FullX509TrustManager 是一个实现 javax.net.ssl.X509TrustManager 的类,但实际上没有一个方法执行任何工作,请在此处获取示例。

Good Luck!

祝你好运!

回答by Matti Lyra

I don't know about the Android specifics for ssl certificates, but it would make sense that Android won't accept a self signed ssl certificate off the bat. I found this post from android forums which seems to be addressing the same issue: http://androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html

我不知道 ssl 证书的 Android 细节,但 Android 不会立即接受自签名 ssl 证书是有道理的。我从 android 论坛上找到了这篇文章,它似乎解决了同样的问题:http: //androidforums.com/android-applications/950-imap-self-signed-ssl-certificates.html

回答by Ulrich Scheller

This is what I am doing. It simply doesn't check the certificate anymore.

这就是我正在做的。它只是不再检查证书。

// always verify the host - dont check for certificate
final static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

/**
 * Trust every server - dont check for any certificate
 */
private static void trustAllHosts() {
    // Create a trust manager that does not validate certificate chains
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }

        public void checkClientTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
        }

        public void checkServerTrusted(X509Certificate[] chain,
                String authType) throws CertificateException {
        }
    } };

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection
                .setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

and

    HttpURLConnection http = null;

    if (url.getProtocol().toLowerCase().equals("https")) {
        trustAllHosts();
        HttpsURLConnection https = (HttpsURLConnection) url.openConnection();
        https.setHostnameVerifier(DO_NOT_VERIFY);
        http = https;
    } else {
        http = (HttpURLConnection) url.openConnection();
    }

回答by bajohns

While trying to answer this question I found a better tutorial. With it you don't have to compromise the certificate check.

在尝试回答这个问题时,我找到了一个更好的教程。有了它,您不必妥协证书检查。

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

*I did not write this but thanks to Bob Lee for the work

*这不是我写的,但感谢 Bob Lee 的工作

回答by saxos

You can also look at my blog article, very similar to crazybobs.

你也可以看看我的博客文章,和crazybob很像。

This solution also doesn't compromise certificate checking and explains how to add the trusted certs in your own keystore.

此解决方案也不会影响证书检查,并解释了如何在您自己的密钥库中添加受信任的证书。

http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/

http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/

回答by Adrian Spinei

None of these worked for me (aggravated by the Thawte bugas well). Eventually I got it fixed with Self-signed SSL acceptance on Androidand Custom SSL handling stopped working on Android 2.2 FroYo

这些都不适合我(也因Thawte 错误而加剧)。最后,我把它固定在Android上的自签名SSL验收自定义SSL处理不辍上的Android 2.2 Froyo

回答by alumat

This is a known problem with Android 2.x. I was struggling with this problem for a week until I came across the following question, which not only gives a good background of the problem but also provides a working and effective solution devoid of any security holes.

这是 Android 2.x 的一个已知问题。我在这个问题上挣扎了一个星期,直到我遇到了以下问题,这不仅提供了问题的良好背景,而且还提供了一个没有任何安全漏洞的有效解决方案。

'No peer certificate' error in Android 2.3 but NOT in 4

Android 2.3 中的“无对等证书”错误,但 4 中没有

回答by Syed Ghulam Akbar

For some reason the solution mentioned for httpClient above didn't worked for me. At the end I was able to make it work by correctly overriding the method when implementing the custom SSLSocketFactory class.

出于某种原因,上面为 httpClient 提到的解决方案对我不起作用。最后,我能够通过在实现自定义 SSLSocketFactory 类时正确覆盖该方法来使其工作。

@Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) 
                              throws IOException, UnknownHostException 
    {
    return sslFactory.createSocket(socket, host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslFactory.createSocket();
}

This is how it worked perfectly for me. You can see the full custom class and implementing on the following thread: http://blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error/

这就是它对我来说完美的方式。您可以在以下线程中查看完整的自定义类并实现:http: //blog.syedgakbar.com/2012/07/21/android-https-and-not-trusted-server-certificate-error/

回答by Speise

Any of this answers didn't work for me so here is code which trust any certificates.

这些答案中的任何一个对我都不起作用,所以这里是信任任何证书的代码。

import java.io.IOException;

    import java.net.Socket;
    import java.security.KeyManagementException;
    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.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.scheme.PlainSocketFactory;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.conn.ssl.X509HostnameVerifier;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
    import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

    public class HttpsClientBuilder {
        public static DefaultHttpClient getBelieverHttpsClient() {

            DefaultHttpClient client = null;

            SchemeRegistry Current_Scheme = new SchemeRegistry();
            Current_Scheme.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            try {
                Current_Scheme.register(new Scheme("https", new Naive_SSLSocketFactory(), 8443));
            } catch (KeyManagementException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (UnrecoverableKeyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchAlgorithmException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (KeyStoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            HttpParams Current_Params = new BasicHttpParams();
            int timeoutConnection = 8000;
            HttpConnectionParams.setConnectionTimeout(Current_Params, timeoutConnection);
            int timeoutSocket = 10000;
            HttpConnectionParams.setSoTimeout(Current_Params, timeoutSocket);
            ThreadSafeClientConnManager Current_Manager = new ThreadSafeClientConnManager(Current_Params, Current_Scheme);
            client = new DefaultHttpClient(Current_Manager, Current_Params);
            //HttpPost httpPost = new HttpPost(url);
            //client.execute(httpPost);

         return client;
         }

    public static class Naive_SSLSocketFactory extends SSLSocketFactory
    {
        protected SSLContext Cur_SSL_Context = SSLContext.getInstance("TLS");

        public Naive_SSLSocketFactory ()
                throws NoSuchAlgorithmException, KeyManagementException,
                KeyStoreException, UnrecoverableKeyException
        {
            super(null, null, null, null, null, (X509HostnameVerifier)null);
            Cur_SSL_Context.init(null, new TrustManager[] { new X509_Trust_Manager() }, null);
        }

        @Override
        public Socket createSocket(Socket socket, String host, int port,
                boolean autoClose) throws IOException
        {
            return Cur_SSL_Context.getSocketFactory().createSocket(socket, host, port, autoClose);
        }

        @Override
        public Socket createSocket() throws IOException
        {
            return Cur_SSL_Context.getSocketFactory().createSocket();
        }
    }

    private static class X509_Trust_Manager implements X509TrustManager
    {

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

    };
}

回答by Juan Sánchez

If you are using a StartSSL or Thawte certificate, it will fail for Froyo and older versions. You can use a newer version's CAcert repositoryinstead of trusting every certificate.

如果您使用的是 StartSSL 或 Thawte 证书,则 Froyo 和旧版本将失败。您可以使用较新版本的 CAcert 存储库,而不是信任每个证书。