英文:
Resolve the hostname in Java code and use it
问题
我正在通过我的Java代码连接到一个服务。让我们将服务的FQDN或主机名称为:abc.xyz.com
。
我的Java实现返回了异常:
java.net.UnknownHostException: dfour6gtsg5a.streaming.us-phoenix-1.oci.oraclecloud.com
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:567)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
at java.base/java.net.Socket.connect(Socket.java:633)
at java.base/sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:304)
at java.base/sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:174)
at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183)
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:532)
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:637)
at java.base/sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:266)
at java.base/sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:380)
现在,当我在/etc/hosts
中包含服务的FQDN和IPAddress条目如下:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
...
100.70.125.57 abc.xyz.com
相同的Java实现正常工作,因为服务的FQDN正确解析为IP地址。
如果我尝试使用IPAddress运行Java实现,我会收到以下错误:
javax.net.ssl.SSLHandshakeException: No subject alternative names matching IP address 100.70.125.57 found
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
在生产环境中,我将无法访问/etc/hosts
以进行编辑。如何在我的Java实现内将服务的FQDN解析为IPAddress呢?
英文:
I am connecting to a service through my Java code. Let's call FQDN or hostname of service as: abc.xyz.com
.
My Java implementation returns exception:
java.net.UnknownHostException: dfour6gtsg5a.streaming.us-phoenix-1.oci.oraclecloud.com
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:567)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
at java.base/java.net.Socket.connect(Socket.java:633)
at java.base/sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:304)
at java.base/sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:174)
at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183)
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:532)
at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:637)
at java.base/sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:266)
at java.base/sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:380)
at
Now, when I include entry of FQDN of service and IPAddress in /etc/hosts
as below:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
...
100.70.125.57 abc.xyz.com
Same Java implementation works correctly as service FQDN get resolved to IP address correctly.
If I try to run Java implementation with IPAddress, I get below error:
javax.net.ssl.SSLHandshakeException: No subject alternative names matching IP address 100.70.125.57 found
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
In production environment, I will not have access to /etc/hosts
for editing.
How can I resolve the Service FQDN to the IPAddress inside my Java implementation?
答案1
得分: 0
以下是翻译好的部分:
最简单的方法是为HttpsURLConnection.setHostnameVerifier()
提供值true
。
您需要重写方法public boolean verify(String hostname, SSLSession session)
以始终返回true
。
以下是示例代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.Exception;
import java.net.URL;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
public class SkipVerification implements Runnable {
private static final String TAG = SkipVerification.class.toString();
private String server_port;
private String serverIP;
public SkipVerification(String serverIP, String server_port){
this.serverIP = serverIP;
this.server_port = server_port;
}
public void run() {
try {
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
URL url = new URL("https://" + serverIP + ":" + server_port + "/json");
InputStream inStream = null;
try {
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setHostnameVerifier(hostnameVerifier);
inStream = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
} catch (Exception e) {
Log.e(TAG, "从服务器获取数据时出错", e);
} finally {
if (inStream != null) {
inStream.close();
}
}
} catch (Exception e) {
Log.e(TAG, "初始化SkipVerificationn线程时出错", e);
}
}
}
这适用于使用HttpsURLConnection
类时。对于其他实现,请参考**@Elliott Frisch**的评论提问。
英文:
The simplest way I found is to provide value true
to HttpsURLConnection.setHostnameVerifier()
You need to override the method public boolean verify(String hostname, SSLSession session)
for returning true
everytime.
Below is an example:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.Exception;
import java.net.URL;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
public class SkipVerification implements Runnable {
private static final String TAG = SkipVerification.class.toString();
private String server_port;
private String serverIP;
public SkipVerification(String serverIP, String server_port){
this.serverIP = serverIP;
this.server_port = server_port;
}
public void run() {
try {
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
URL url = new URL("https://" + serverIP + ":" + server_port + "/json");
InputStream inStream = null;
try {
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setHostnameVerifier(hostnameVerifier);
inStream = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
} catch (Exception e) {
Log.e(TAG, "error fetching data from server", e);
} finally {
if (inStream != null) {
inStream.close();
}
}
} catch (Exception e) {
Log.e(TAG, "error initializing SkipVerificationn thread", e);
}
}
}
This works when using HttpsURLConnection
class. For other implementation, please refer to comment to question by @Elliott Frisch.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论