无需下载证书Java和HTTPS URL连接(Java and HTTPS url connecti

2019-06-18 14:20发布

此代码连接到一个HTTPS站点,我假设我没有验证证书。 但是,为什么不让我必须在本地安装证书的网站? 我不应该必须在本地安装证书,并加载该程序或将其下载封面的背后? 是远程站点的客户端之间的通信传输加密还是?

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.security.cert.X509Certificate;

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

public class TestSSL {

    public static void main(String[] args) throws Exception {
        // Create a trust manager that does not validate certificate chains
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {
            }
            public void checkServerTrusted(X509Certificate[] certs, String authType) {
            }
        } };
        // Install the all-trusting trust manager
        final SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        // Create all-trusting host name verifier
        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // Install the all-trusting host verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

        URL url = new URL("https://www.google.com");
        URLConnection con = url.openConnection();
        final Reader reader = new InputStreamReader(con.getInputStream());
        final BufferedReader br = new BufferedReader(reader);        
        String line = "";
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }        
        br.close();
    } // End of main 
} // End of the class //

Answer 1:

为什么你没有加载本地证书的原因是,您明确选择不验证证书,与信任所有证书此信任管理器。

交通仍然会被加密,但你打开到人在这方面的中间人攻击的连接:你与别人沟通秘密,你只是不知道它是否是你所期望的服务器,或可能的攻击者。

如果您的服务器证书来自一个著名的CA,与JRE捆绑CA证书的默认包的一部分(通常是cacerts文件,看JSSE参考指南),你可以使用默认的信任管理器,你不必这里设置任何东西。

如果你有一个特定的证书(自签名或从您自己的CA),你可以使用默认的信任管理器或者是一个具有特定信任初始化,但你必须明确地导入证书的信任存储(独立后验证),如在此答案 。 您还可能有兴趣在这个答案 。



Answer 2:

但是,为什么不让我必须在本地安装证书的网站?

那么您正在使用的代码是被设计为接受证书没有任何做任何检查。 这是不好的做法...但如果这是你想做的事,那么(显然)没有必要安装你的代码是明确忽略证书。

我不应该必须在本地安装证书,并加载该程序或将其下载封面的背后?

没有,没有。 往上看。

是远程站点的客户端之间的通信传输加密还是?

是的。 然而,问题是,既然你已经告诉它没有做任何检查,以信任服务器的证书,你不知道如果你谈论到真实服务器,或其他一些网站被冒充真正的服务器。 这是否是一个问题,视情况而定。


如果我们使用的浏览器为例,通常是浏览器不要求用户明确地安装访问的每个网站的SSL证书。

该浏览器已预装了一组受信任的根证书。 大多数时候,当你访问一个“https”开头的网站时,浏览器可以验证网站的证书(最终通过证书链)的那些信任证书的一个保证。 如果浏览器不会在链条的开端,是一个值得信赖的证书识别证书(或者,如果证书过期或无效/不合适的),那么它会显示一个警告。

Java的工作方式相同。 JVM的密钥库一组可信的证书,和相同的过程来检查证书是由受信任的证书保证。

请问java的HTTPS客户端API支持某种类型的机制,可以自动下载证书的信息?

号允许应用程序从随机的地方下载证书,并安装它们(如可信任)系统中的密钥库将是一个安全漏洞。



Answer 3:

这里建议使用最新X509ExtendedTrustManager而不是X509证书: java.security.cert.CertificateException:证书不符合算法的限制

    package javaapplication8;

    import java.io.InputStream;
    import java.net.Socket;
    import java.net.URL;
    import java.net.URLConnection;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLEngine;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509ExtendedTrustManager;

    /**
     *
     * @author hoshantm
     */
    public class JavaApplication8 {

        /**
         * @param args the command line arguments
         * @throws java.lang.Exception
         */
        public static void main(String[] args) throws Exception {
            /*
             *  fix for
             *    Exception in thread "main" javax.net.ssl.SSLHandshakeException:
             *       sun.security.validator.ValidatorException:
             *           PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
             *               unable to find valid certification path to requested target
             */
            TrustManager[] trustAllCerts = new TrustManager[]{
                new X509ExtendedTrustManager() {
                    @Override
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    @Override
                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }

                    @Override
                    public void checkClientTrusted(X509Certificate[] xcs, String string, Socket socket) throws CertificateException {

                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] xcs, String string, Socket socket) throws CertificateException {

                    }

                    @Override
                    public void checkClientTrusted(X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException {

                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] xcs, String string, SSLEngine ssle) throws CertificateException {

                    }

                }
            };

            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            // Create all-trusting host name verifier
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };
            // Install the all-trusting host verifier
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
            /*
             * end of the fix
             */

            URL url = new URL("https://10.52.182.224/cgi-bin/dynamic/config/panel.bmp");
            URLConnection con = url.openConnection();
            //Reader reader = new ImageStreamReader(con.getInputStream());

            InputStream is = new URL(url.toString()).openStream();

            // Whatever you may want to do next

        }

    }


Answer 4:

无需下载证书Java和HTTPS URL连接

如果你真的想避免下载服务器的证书,然后使用匿名协议喜欢匿名的Diffie-Hellman(ADH)。 服务器证书不与ADH和朋友发送。

您可以选择与匿名协议setEnabledCipherSuites 。 你可以看到可用的密码套件的列表getEnabledCipherSuites

相关阅读:这就是为什么你要叫SSL_get_peer_certificate OpenSSL中。 你会得到一个X509_V_OK与匿名协议,这就是你如何检查,看看是否在交流中使用的证书。

但正如布鲁诺和Stephed C中规定的,它是一个坏主意,以避免支票或使用匿名协议。


另一种选择是使用TLS-PSK或TLS-SRP。 他们并不需要服务器证书两种。 (但我不认为你可以使用它们)。

冲突是,你需要预先提供的系统,因为TLS-PSK是普雷斯共享秘密和TLS-SRP是安全远程密码 。 该认证是相互的,而不是唯一的服务器。

在这种情况下,相互认证是由双方都知道的共享秘密,同时预置密码到一个酒店所提供; 或一个(或两个)不和信道建立失败。 每一方都证明了这个秘密的知识是“互惠”的一部分。

最后,TLS-PSK或TLS-SRP不要在Web应用程序中使用HTTP做愚蠢的事情,比如咳嗽了用户的密码等(或通过HTTPS)。 这就是为什么我说的每一方都证明了这个秘密的知识......



Answer 5:

一个简单的,但不是纯Java解决方案,是掏出来curl从Java,它使您的要求是怎么做的完全控制。 如果你只是在做这个简单的东西的时候,这可以让你忽略有时证书错误,使用此方法。 这个例子说明如何使针对具有有效或无效证书安全服务器的请求,通过在cookie中,并使用获得的输出curl从Java。

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

public class MyTestClass
{
  public static void main(String[] args) 
  {
    String url = "https://www.google.com";
    String sessionId = "faf419e0-45a5-47b3-96d1-8c62b2a3b558";

    // Curl options are:
    // -k: ignore certificate errors
    // -L: follow redirects
    // -s: non verbose
    // -H: add a http header

    String[] command = { "curl", "-k", "-L", "-s", "-H", "Cookie: MYSESSIONCOOKIENAME=" + sessionId + ";", "-H", "Accept:*/*", url };
    String output = executeShellCmd(command, "/tmp", true, true);
    System.out.println(output);
  }

  public String executeShellCmd(String[] command, String workingFolder, boolean wantsOutput, boolean wantsErrors)
  {
    try
    {
      ProcessBuilder pb = new ProcessBuilder(command);
      File wf = new File(workingFolder);
      pb.directory(wf);

      Process proc = pb.start();
      BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
      BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

      StringBuffer sb = new StringBuffer();
      String newLine = System.getProperty("line.separator");
      String s;

      // read stdout from the command
      if (wantsOutput)
      {
        while ((s = stdInput.readLine()) != null)
        {
          sb.append(s);
          sb.append(newLine);
        }
      }

      // read any errors from the attempted command
      if (wantsErrors)
      {
        while ((s = stdError.readLine()) != null)
        {
          sb.append(s);
          sb.append(newLine);
        }
      }

      String result = sb.toString();

      return result;
    }
    catch (IOException e)
    {
      throw new RuntimeException("Problem occurred:", e);
    }
  }


}


Answer 6:

如果你正在使用任何支付网关打任何URL只是发送一条消息,然后我用网页视图按照它: 如何可以加载HTTPS URL没有在Android的WebView中使用SSL

并网页视图在您的活动能见度消失了。 你需要做什么:只是加载网页视图..这样的:

 webViewForSms.setWebViewClient(new SSLTolerentWebViewClient());
                webViewForSms.loadUrl(" https://bulksms.com/" +
                        "?username=test&password=test@123&messageType=text&mobile="+
                        mobileEditText.getText().toString()+"&senderId=ATZEHC&message=Your%20OTP%20for%20A2Z%20registration%20is%20124");

简单。

从这个链接SSLTolerentWebViewClient:你会得到这样怎么能加载HTTPS URL没有在Android的WebView中使用SSL



文章来源: Java and HTTPS url connection without downloading certificate
标签: java ssl https