Java 带有 Android 和自签名服务器证书的 HTTPS GET (SSL)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3761737/
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
HTTPS GET (SSL) with Android and self-signed server certificate
提问by Lars D
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
我查看了有关如何通过HTTPS
Android 从使用自签名证书的服务器检索某些内容的各种帖子。但是,它们似乎都不起作用 - 它们都无法删除
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. The GET request looks something like this:
请注意,服务器将没有 DNS 名称,它只有一个 IP 地址。GET 请求如下所示:
https://username:password@anyIPAddress/blabla/index.php?param=1¶m2=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. It would be interesting to know if somebody really solved this, or if Android simply blocks certificates that are not trusted.
在stackoverflow.com上有很多尝试来解释这个问题,还有很多代码片段,但它们似乎不起作用,据我所知,没有人提供解决这个问题的代码块。知道是否有人真的解决了这个问题,或者 Android 是否只是阻止了不受信任的证书,这将会很有趣。
回答by Yuliy
If you're using an HttpsURLConnection, then try calling setHostnameVerifier
on it before connect()
, and passing it a HostnameVerifier
that just accepts regardless of veracity.
如果您使用的是 HttpsURLConnection,请尝试setHostnameVerifier
在 之前调用它connect()
,并将其传递给HostnameVerifier
无论真实性如何都接受的。
回答by Colin Hebert
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 thismethod, but I think it's kind of ugly.
另一方面,您可以使用这种方法,但我认为它有点丑陋。
Resources :
资源 :
On the same topic :
在同一主题上:
回答by Moss
I made an app that uses self-signed or trust all certs. The source is here: http://code.google.com/p/meneameandroid/source/browse/#svn/trunk/src/com/dcg/authand free to use :P
我制作了一个使用自签名或信任所有证书的应用程序。来源在这里:http: //code.google.com/p/meneameandroid/source/browse/#svn/trunk/src/com/dcg/auth和免费使用:P
Just use the HttpManager and create the SSL factory using the trust all one: http://code.google.com/p/meneameandroid/source/browse/trunk/src/com/dcg/util/HttpManager.java
只需使用 HttpManager 并使用信任创建 SSL 工厂:http: //code.google.com/p/meneameandroid/source/browse/trunk/src/com/dcg/util/HttpManager.java
EDIT: Links updated
编辑:链接已更新
回答by Maciek Sawicki
You can do it quiet securely: http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
您可以安全地做到安静:http: //blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html
回答by saxos
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.
我测试了它,它在我的应用程序中运行没有问题。
回答by SimonJ
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 notuse it for anything that matters. SSL/TLS without authentication is worse than no encryption at all - reading and modifying your "encrypted" data is trivialfor 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. This works both in Android and the regular JRE. Enjoy.
两者都必须发生在代码的开头,然后才开始处理 HttpsURLConnections 等等。这适用于 Android 和常规 JRE。享受。
回答by moji
I made an app that uses self-signed certificate 4 month ago here is the code i hope it helps: https://bitbucket.org/momo0002/tlsdemo.git
我在 4 个月前制作了一个使用自签名证书的应用程序,这里是我希望它有帮助的代码:https: //bitbucket.org/momo0002/tlsdemo.git