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

2022-09-01 07:13:02

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

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

不能选择将服务器修改为具有受信任的证书,也不能选择使服务器证书与服务器的 IP 地址匹配。

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

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

我完全知道这个解决方案很容易受到中间人攻击等。

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

有没有人知道代码,使用Java for Android?

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


答案 1

正如您正确指出的那样,存在两个问题:a) 证书不受信任,以及 b) 证书上的名称与主机名不匹配。

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

还和我在一起吗?我害怕所以...

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

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

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

两者都必须在代码开始时发生,然后再开始搞砸HttpsURLConnections等等。这适用于Android和常规JRE。享受。


答案 2

我制作了一个使用自签名或信任所有证书的应用。源代码在这里,可以免费使用:P

只需使用HttpManager并使用信任所有一个创建SSL工厂。在此处找到示例代码。