Resolve the hostname in Java code and use it.

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

Resolve the hostname in Java code and use it

问题

我正在通过我的Java代码连接到一个服务。让我们将服务的FQDN或主机名称为:abc.xyz.com

我的Java实现返回了异常:

  1. java.net.UnknownHostException: dfour6gtsg5a.streaming.us-phoenix-1.oci.oraclecloud.com
  2. at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:567)
  3. at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
  4. at java.base/java.net.Socket.connect(Socket.java:633)
  5. at java.base/sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:304)
  6. at java.base/sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:174)
  7. at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183)
  8. at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:532)
  9. at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:637)
  10. at java.base/sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:266)
  11. at java.base/sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:380)

现在,当我在/etc/hosts中包含服务的FQDN和IPAddress条目如下:

  1. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  2. ...
  3. 100.70.125.57 abc.xyz.com

相同的Java实现正常工作,因为服务的FQDN正确解析为IP地址。

如果我尝试使用IPAddress运行Java实现,我会收到以下错误:

  1. javax.net.ssl.SSLHandshakeException: No subject alternative names matching IP address 100.70.125.57 found
  2. at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
  3. at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
  4. at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
  5. at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
  6. at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
  7. at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
  8. at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
  9. 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:

  1. java.net.UnknownHostException: dfour6gtsg5a.streaming.us-phoenix-1.oci.oraclecloud.com
  2. at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:567)
  3. at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
  4. at java.base/java.net.Socket.connect(Socket.java:633)
  5. at java.base/sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:304)
  6. at java.base/sun.security.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:174)
  7. at java.base/sun.net.NetworkClient.doConnect(NetworkClient.java:183)
  8. at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:532)
  9. at java.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:637)
  10. at java.base/sun.net.www.protocol.https.HttpsClient.&lt;init&gt;(HttpsClient.java:266)
  11. at java.base/sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:380)
  12. at

Now, when I include entry of FQDN of service and IPAddress in /etc/hosts as below:

  1. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  2. ...
  3. 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:

  1. javax.net.ssl.SSLHandshakeException: No subject alternative names matching IP address 100.70.125.57 found
  2. at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
  3. at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:371)
  4. at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:314)
  5. at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:309)
  6. at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:654)
  7. at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:473)
  8. at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:369)
  9. 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

以下是示例代码:

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.InputStreamReader;
  5. import java.lang.Exception;
  6. import java.net.URL;
  7. import javax.net.ssl.HostnameVerifier;
  8. import javax.net.ssl.HttpsURLConnection;
  9. import javax.net.ssl.SSLSession;
  10. public class SkipVerification implements Runnable {
  11. private static final String TAG = SkipVerification.class.toString();
  12. private String server_port;
  13. private String serverIP;
  14. public SkipVerification(String serverIP, String server_port){
  15. this.serverIP = serverIP;
  16. this.server_port = server_port;
  17. }
  18. public void run() {
  19. try {
  20. HostnameVerifier hostnameVerifier = new HostnameVerifier() {
  21. @Override
  22. public boolean verify(String hostname, SSLSession session) {
  23. return true;
  24. }
  25. };
  26. URL url = new URL("https://" + serverIP + ":" + server_port + "/json");
  27. InputStream inStream = null;
  28. try {
  29. HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
  30. urlConnection.setRequestProperty("Content-Type", "application/json");
  31. urlConnection.setHostnameVerifier(hostnameVerifier);
  32. inStream = urlConnection.getInputStream();
  33. BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
  34. } catch (Exception e) {
  35. Log.e(TAG, "从服务器获取数据时出错", e);
  36. } finally {
  37. if (inStream != null) {
  38. inStream.close();
  39. }
  40. }
  41. } catch (Exception e) {
  42. Log.e(TAG, "初始化SkipVerificationn线程时出错", e);
  43. }
  44. }
  45. }

这适用于使用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:

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.InputStreamReader;
  5. import java.lang.Exception;
  6. import java.net.URL;
  7. import javax.net.ssl.HostnameVerifier;
  8. import javax.net.ssl.HttpsURLConnection;
  9. import javax.net.ssl.SSLSession;
  10. public class SkipVerification implements Runnable {
  11. private static final String TAG = SkipVerification.class.toString();
  12. private String server_port;
  13. private String serverIP;
  14. public SkipVerification(String serverIP, String server_port){
  15. this.serverIP = serverIP;
  16. this.server_port = server_port;
  17. }
  18. public void run() {
  19. try {
  20. HostnameVerifier hostnameVerifier = new HostnameVerifier() {
  21. @Override
  22. public boolean verify(String hostname, SSLSession session) {
  23. return true;
  24. }
  25. };
  26. URL url = new URL(&quot;https://&quot; + serverIP + &quot;:&quot; + server_port + &quot;/json&quot;);
  27. InputStream inStream = null;
  28. try {
  29. HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();
  30. urlConnection.setRequestProperty(&quot;Content-Type&quot;, &quot;application/json&quot;);
  31. urlConnection.setHostnameVerifier(hostnameVerifier);
  32. inStream = urlConnection.getInputStream();
  33. BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
  34. } catch (Exception e) {
  35. Log.e(TAG, &quot;error fetching data from server&quot;, e);
  36. } finally {
  37. if (inStream != null) {
  38. inStream.close();
  39. }
  40. }
  41. } catch (Exception e) {
  42. Log.e(TAG, &quot;error initializing SkipVerificationn thread&quot;, e);
  43. }
  44. }
  45. }

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:

确定