Resolve the hostname in Java code and use it.

huangapple go评论68阅读模式
英文:

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.&lt;init&gt;(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(&quot;https://&quot; + serverIP + &quot;:&quot; + server_port + &quot;/json&quot;);
InputStream inStream = null;
try {
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
urlConnection.setRequestProperty(&quot;Content-Type&quot;, &quot;application/json&quot;);
urlConnection.setHostnameVerifier(hostnameVerifier);
inStream = urlConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
} catch (Exception e) {
Log.e(TAG, &quot;error fetching data from server&quot;, e);
} finally {
if (inStream != null) {
inStream.close();
}
}
} catch (Exception e) {
Log.e(TAG, &quot;error initializing SkipVerificationn thread&quot;, e);
}
}
}

This works when using HttpsURLConnection class. For other implementation, please refer to comment to question by @Elliott Frisch.

huangapple
  • 本文由 发表于 2023年5月17日 17:19:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76270467.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定