gpt4 book ai didi

java - 为单个连接禁用 SSLHandshakeException

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:58:11 26 4
gpt4 key购买 nike

我正在寻找类似于 this answer 的解决方案,但更安全。我想禁用证书验证,但仅针对单个请求(这就是我所需要的)。所以它应该做以下一项或多项

  • 完成一个请求后返回安全状态
  • 仅对给定的 URL 禁用验证
  • (也许)只为一个线程使用不安全的设置

附录

当我要求更安全的解决方案时,我真的很想知道与原始问题(分数 +46)相比,这个问题(分数 -2)有什么问题。有人可以解释一下吗?

解释我为什么需要这个:有一个有效的服务器证书,通常,它会被使用。但我需要向 localhost 发送一个请求,它也必须在开发人员机器上运行。它必须是 https,因为不支持 http

最佳答案

解决方案

此实用程序类基于提供的示例。使用“宽松”的 SSLContext 预配置接受所有证书的 TrustManager。如果您的本地主机 ssl 证书颁发给不同的 CN,还需要一个主机名 validator

使用 HttpsURLConnection.setSocketFactoryHttpsURLConnection.setHostnameVerifier 将其应用于需要“宽松”ssl 验证的每个连接。默认行为不会改变

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class RelaxedSSLContext {
// Create a trust manager that does not validate certificate chains like
public static TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) {
//No need to implement.
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) {
//No need to implement.
}
}
};

//hostname verifier. All hosts valid
public static HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};

//hostname verifier. Only localhost and 127.0.0.1 valid
public static HostnameVerifier localhostValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return "localhost".equals(hostname) || "127.0.0.1".equals(hostname);
}
};


public static SSLContext getInstance() throws KeyManagementException, NoSuchAlgorithmException{
return getInstance("SSL");
}

//get a 'Relaxed' SSLContext with no trust store (all certificates are valids)
public static SSLContext getInstance(String protocol) throws KeyManagementException, NoSuchAlgorithmException{
SSLContext sc = SSLContext.getInstance(protocol);
sc.init(null, trustAllCerts, new java.security.SecureRandom());
return sc;
}
}

这样使用

HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(RelaxedSSLContext.getInstance().getSocketFactory());
conn.setHostnameVerifier(RelaxedSSLContext.localhostValid);

示例 1(默认)

url = "https://www.google.cop/finance";
conn = url.openConnection();
conn.connect();
int statusCode = conn.getResponseCode(); // 200

示例 2(错误的主机名)

url = "https://216.58.210.164/finance";
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(RelaxedSSLContext.allHostsValid);
conn.connect();
int statusCode = conn.getResponseCode(); //200
// ERROR 'No subject alternative names matching IP address 216.58.210.164 found' without hostnameVerifier

示例 3(链不在默认信任库中)

url = "https://www.aragon.es";
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(RelaxedSSLContext.getInstance().getSocketFactory());
conn.connect();
int statusCode = conn.getResponseCode(); //200
// ERROR 'unable to find valid certification path to requested target' without relaxedSocketFactory

上下文

我认为您的问题切题、有用且表达得当。在某些情况下,应用高安全性上下文是合适的,或者更确切地说,不是必需的。纯 HTTP 仍在使用中......

让我们分析一下您的上下文。所需的是通过 HTTPS 访问本地主机而不信任服务器身份。这意味着您要接受服务器提供的任何证书。这种情况下的安全问题是 MITM 附加(中间人)。来自(维基百科)

Attacker secretly relays and possibly alters the communication betweentwo parties who believe they are directly communicating with eachother.

但是否有可能是 MITM 攻击与本地主机的不受信任的 https 连接

参见 https://security.stackexchange.com/questions/8145/does-https-prevent-man-in-the-middle-attacks-by-proxy-server/8309#8309

首先,在 https 中,服务器必须向客户端提供服务器证书。客户端验证证书的公钥并检查是否与本地信任库匹配。通过网络管理员的协作,可以嗅探网络并设置代理来拦截连接。但是恶意代理没有匹配的私钥,因此代理服务器可能会尝试伪造证书并提供自己的公钥。证书不会出现在客户端 trustore 上,因此连接将被拒绝。但是如果去掉truststore验证,理论上是可以进行攻击的。

但是,MITM 是否可能限制与本地主机的连接?

参见 https://security.stackexchange.com/questions/61399/are-mitm-attacks-possible-on-http-loopbacks

在一般情况下这是不可能的,但是具有机器根访问权限的攻击者可以更改 DNS 并将请求重定向到恶意代理。即使使用 127.0.0.1,如果应用程序有配置连接端口的方法也是可能的。

偏执的解决方案可能是硬编码服务器连接 url、端口甚至 trustore。但是你说的是开发环境中的 localhost,所以我想我们可以放松一点

关于java - 为单个连接禁用 SSLHandshakeException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37724901/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com