简体   繁体   English

带有 Android 和自签名服务器证书的 HTTPS GET (SSL)

[英]HTTPS GET (SSL) with Android and self-signed server certificate

I have looked into various posts about how to retrieve something via HTTPS on Android, from a server that uses a self-signed certificate.我查看了有关如何通过 Android 上的HTTPS从使用自签名证书的服务器检索某些内容的各种帖子。 However, none of them seem to work - they all fail to remove the但是,它们似乎都不起作用 - 它们都无法删除

javax.net.ssl.SSLException: Not trusted server certificate message. javax.net.ssl.SSLException:不受信任的服务器证书消息。

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.修改服务器以获得可信证书不是一个选项,也不是使服务器证书与服务器的 IP 地址匹配的选项。

Note, that the server will not have a DNS name, it will only have an IP-address.请注意,服务器将没有 DNS 名称,它只有一个 IP 地址。 The GET request looks something like this: GET 请求如下所示:

 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.因此,解决方案必须忽略对证书缺乏信任,并忽略主机名不匹配。

Does anybody know the code, that does this, using Java for Android?有没有人知道使用 Java for 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.stackoverflow.com上有很多尝试来解释这个问题,还有很多代码片段,但它们似乎不起作用,据我所知,没有人提供解决这个问题的代码块。 It would be interesting to know if somebody really solved this, or if Android simply blocks certificates that are not trusted.知道是否有人真的解决了这个问题,或者 Android 是否只是阻止了不受信任的证书,这将会很有趣。

I made an app that uses self-signed or trust all certs.我制作了一个使用自签名或信任所有证书的应用程序。 The source is here and free to use :P来源在这里并且可以免费使用:P

Just use the HttpManager and create the SSL factory using the trust all one.只需使用 HttpManager 并使用全部信任创建 SSL 工厂。 Sample code found here .示例代码在这里找到。

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.正如您正确指出的那样,有两个问题:a) 证书不受信任,b) 证书上的名称与主机名不匹配。

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 .没有身份验证的 SSL/TLS 比根本没有加密更糟糕 - 读取和修改您的“加密”数据对于攻击者来说是微不足道的,您甚至不会知道它正在发生

Still with me?还和我在一起吗? I feared so...我好怕...

a) is solved by creating a custom SSLContext whose TrustManager accepts anything: a) 通过创建一个自定义的 SSLContext 来解决,它的 TrustManager 接受任何东西:

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());

and b) by creating a HostnameVerifier which allows the connection to proceed even though the cert doesn't match the hostname:和 b) 通过创建一个 HostnameVerifier 允许连接继续,即使证书与主机名不匹配:

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

Both must happen right at the beginning of your code, before you start messing around with HttpsURLConnections and so on.两者都必须发生在代码的开头,然后才开始处理 HttpsURLConnections 等等。 This works both in Android and the regular JRE.这适用于 Android 和常规 JRE。 Enjoy.享受。

如果您使用的是 HttpsURLConnection,则尝试在connect()之前对其调用setHostnameVerifier ,并将其传递给HostnameVerifier ,无论其真实性如何,它都会接受。

If you have an access to the devices you can add the certificate to a keystore.如果您有权访问设备,则可以将证书添加到密钥库。 See more informations here . 在此处查看更多信息

On the other hand you can use this method, but I think it's kind of ugly.另一方面,您可以使用这种方法,但我认为它有点丑陋。


Resources :资源:

On the same topic :在同一主题上:

If you ask me, do it the secure way.如果您问我,请以安全的方式进行。

Found a good tutorial http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/ and it's really not that difficult to implement.找到了一个很好的教程http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/并且它真的不难实现。

Also the tutorial recommended by Maciek is very good. Maciek 推荐的教程也很好。

I tested it, and it works in my app without problems.我测试了它,它在我的应用程序中运行没有问题。

我在 4 个月前制作了一个使用自签名证书的应用程序,这里是我希望它有帮助的代码: https : //bitbucket.org/momo0002/tlsdemo.git

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM