android - 接受自签名 SSL 证书-> 在哪里设置默认的 TrustManager

标签 android http ssl ssl-certificate x509certificate

首先我不得不承认,我知道接受所有证书可以被认为是没有安全性的。我们有“真正的”证书,但只在我们的实时系统上。我们测试系统上的证书是自签名的。所以只要我们在开发,我们就必须使用测试服务器,这迫使我禁用证书。

我在 Stackoverflow 和整个网络上看到了很多主题,它们都在尝试做同样的事情: 接受 SSL 证书。然而,这些答案似乎都不适用于我的问题,因为我没有弄乱 HTTPSUrlConnections

如果我正在做一个请求,代码通常看起来像这样(注释以澄清):

//creates an HTTP-Post with an URL
HttpPost post = createBaseHttpPost();
//loads the request Data inside the httpPost
post.setEntity(getHttpPostEntity());
//appends some Headers like user-agend or Request UUIDs
appendHeaders(post);

HttpClient client = new DefaultHttpClient();
//mResponse is a custom Object which is returned 
//from the custom ResponseHandler(mResponseHandler) 
mResponse = client.execute(post, mResponseHandler);
return mResponse;

我读到我应该注入(inject)我自己的 TrustManagerX509HostnameVerivier。我是这样创建它们的:

private static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{
        new X509TrustManager() {

            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[]{};
            }

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

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

    };

    private static X509HostnameVerifier ACCEPT_ALL_HOSTNAMES = 
            new X509HostnameVerifier() {

                public void verify(String host, String[] cns, String[] subjectAlts)
                        throws SSLException {
                }

                public void verify(String host, X509Certificate cert) throws SSLException {
                }

                public void verify(String host, SSLSocket ssl) throws IOException {
                }

                public boolean verify(String host, SSLSession session) {
                    return true;
                }
            };

如果我像这样在我的请求中注入(inject) HostnameVerifier(客户端是上面的 DefaultHttpClient)

SSLSocketFactory ssl = (SSLSocketFactory)client.getConnectionManager().getSchemeRegistry().getScheme("https").getSocketFactory();
ssl.setHostnameVerifier(ACCEPT_ALL_HOSTNAMES);

响应从“主机名 ** 不匹配”变为“错误请求”。我想我必须设置 TrustManager,但我不知道在我的请求中的什么地方设置它,因为我没有使用 HttpsUrlConnections 在我查找它的任何地方都提到过。

最佳答案

不,它不会强制您禁用验证,它会强制您正确实现验证。 不要盲目接受所有证书。不,您的情况没有任何不同,您只需要信任默认情况下 Android 不信任的证书。

您使用的是 HttpClient,因此设置信任管理器的 API 与 HttpsURLConnection 有所不同,但过程相同:

  1. 加载带有可信证书(您服务器的自签名证书)的 keystore 文件
  2. 用它初始化一个KeyStore
  3. 使用 2 中的 KeyStore 创建一个 SocketFactory
  4. 将您的 HTTP 客户端库设置为在创建 SSL 套接字时使用它。

这在 Android 文档中有描述:http://developer.android.com/reference/org/apache/http/conn/ssl/SSLSocketFactory.html

关于该主题的更详细的文章展示了如何创建信任库文件:http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

一些背景信息和示例代码:http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html

这是初始化 HttpClient 所需的代码:

KeyStore localTrustStore = KeyStore.getInstance("BKS");
InputStream in = getResources().openRawResource(R.raw.mytruststore);
localTrustStore.load(in, TRUSTSTORE_PASSWORD.toCharArray());

SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory
                .getSocketFactory(), 80));
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(localTrustStore);
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
HttpParams params = new BasicHttpParams();
ClientConnectionManager cm = 
    new ThreadSafeClientConnManager(params, schemeRegistry);

HttpClient client = new DefaultHttpClient(cm, params); 

此时,您没有理由信任所有证书。如果你这样做,一切都在你身上:)

关于android - 接受自签名 SSL 证书-> 在哪里设置默认的 TrustManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13917984/

相关文章:

java - 如何在 Android 上接收多播消息?

ssl - EV SSL 不显示绿色条

ssl - 在 curl -k 中请求工作,但不在 Postman 中禁用 SSL

java - createNewFile - 打开失败 : ENOENT (No such file or directory)

android - searchview不适用于自定义适配器kotlin

android - 使用 Espresso 在底页中找不到 View

javascript - Paypal 访问控制允许来源

flash - AS3 中有更多 HTTP 动词吗?

javascript - Express.js 中 res.send 和 res.json 的区别

azure - 使用 pfx 文件时,Azure Function App 返回 'The credentials supplied to the package were not recognized'