带有 Android 和自签名服务器证书的 HTTPS GET (SSL) [英] HTTPS GET (SSL) with Android and self-signed server certificate

查看:26
本文介绍了带有 Android 和自签名服务器证书的 HTTPS GET (SSL)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我查看了有关如何在 Android 上通过 HTTPS 从使用自签名证书的服务器检索某些内容的各种帖子.但是,它们似乎都不起作用 - 它们都无法删除

I have looked into various posts about how to retrieve something via HTTPS on Android, from a server that uses a self-signed certificate. However, none of them seem to work - they all fail to remove the

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

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

修改服务器获得可信证书不是一个选项,也不是让服务器证书匹配服务器IP地址的选项.

It is not an option to modify the server to have a trusted certificate, and it is also not an option to make the server certificate match the server's IP address.

请注意,服务器将没有 DNS 名称,它只有一个 IP 地址.GET 请求如下所示:

Note, that the server will not have a DNS name, it will only have an IP-address. The GET request looks something like this:

 https://username:password@anyIPAddress/blabla/index.php?param=1&param2=3

我完全意识到这个解决方案容易受到中间人攻击等.

I am fully aware that this solution is prone to man-in-the-middle attacks etc.

因此,解决方案必须忽略对证书缺乏信任,并忽略主机名不匹配.

So, the solution must ignore the lack of trust in the certificate, and ignore the hostname mismatch.

有没有人知道使用 Java for Android 执行此操作的代码?

Does anybody know the code, that does this, using Java for Android?

stackoverflow.com 上有很多尝试解释这一点,还有很多代码片段,但它们似乎不起作用,据我所知,没有人提供解决这个问题的代码块.想知道是否有人真的解决了这个问题,或者 Android 是否只是阻止了不受信任的证书.

There are plenty of attempts to explain this on stackoverflow.com, and plenty of code snippets, but they don't seem to work, and nobody has provided one block of code that solves this, as far as I can see. It would be interesting to know if somebody really solved this, or if Android simply blocks certificates that are not trusted.

推荐答案

正如您正确指出的,有两个问题:a) 证书不受信任,以及 b) 证书上的名称与主机名.

As you correctly point out, there are two issues: a) the certificate isn't trusted, and b) the name on the certificate doesn't match the hostname.

警告:对于得到此答案的任何其他人,这是一个肮脏、可怕的黑客行为,您不得将其用于任何重要的事情.没有身份验证的 SSL/TLS 比根本没有加密更糟糕 - 读取和修改您的加密"数据对于攻击者来说微不足道,您甚至不会知道它正在发生.

WARNING: for anybody else arriving at this answer, this is a dirty, horrible hack and you must not use it for anything that matters. SSL/TLS without authentication is worse than no encryption at all - reading and modifying your "encrypted" data is trivial for an attacker and you wouldn't even know it was happening.

还和我在一起吗?我怕...

Still with me? I feared so...

a) 通过创建一个自定义的 SSLContext 来解决,它的 TrustManager 接受任何东西:

a) is solved by creating a custom SSLContext whose TrustManager accepts anything:

SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[] {
  new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] chain, String authType) {}
    public void checkServerTrusted(X509Certificate[] chain, String authType) {}
    public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[]{}; }
  }
}, null);
HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());

和 b) 通过创建一个 HostnameVerifier 允许连接继续进行,即使证书与主机名不匹配:

and b) by creating a HostnameVerifier which allows the connection to proceed even though the cert doesn't match the hostname:

HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
  public boolean verify(String hostname, SSLSession session) {
    return true;
  }
});

两者都必须在代码的开头发生,然后才能开始使用 HttpsURLConnections 等.这适用于 Android 和常规 JRE.享受.

Both must happen right at the beginning of your code, before you start messing around with HttpsURLConnections and so on. This works both in Android and the regular JRE. Enjoy.

这篇关于带有 Android 和自签名服务器证书的 HTTPS GET (SSL)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆