忽略Java中的SSL验证

前端之家收集整理的这篇文章主要介绍了忽略Java中的SSL验证前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我必须使用无效的SSL证书调用托管在Web服务器上的HTTP服务.在dev中,我使用keytool导入证书,但每个客户端安装证书都不同,所以我不能捆绑它.

前言:我知道跳过SSL验证真的很丑陋.在这种具体情况下,我甚至不需要SSL,系统中的所有其他通信都是通过简单的HTTP.所以我真的不在乎MITM攻击等等.攻击者不需要去破坏SSL,因为数据没有SSL.这是对我无法控制的遗留系统的支持.

我正在使用具有NaiveTrustManager和NaiveHostnameVerifier的SSLSocketFactory的HttpURLConnection.这适用于我尝试的一些自签名服务器,但不在客户的网站上.我得到的错误是:

  1. javax.net.ssl.SSLKeyException: [Security:090477]Certificate chain received from xxxxxxxxxx was not trusted causing SSL handshake failure.
  2. at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireException(Unknown Source)
  3. at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireAlertSent(Unknown Source)
  4. at com.certicom.tls.record.handshake.HandshakeHandler.fireAlert(Unknown Source)
  5. at com.certicom.tls.record.handshake.HandshakeHandler.fireAlert(Unknown Source)
  6. at com.certicom.tls.record.handshake.ClientStateReceivedServerHello.handle(Unknown Source)
  7. at com.certicom.tls.record.handshake.HandshakeHandler.handleHandshakeMessage(Unknown Source)
  8. at com.certicom.tls.record.handshake.HandshakeHandler.handleHandshakeMessages(Unknown Source)
  9. at com.certicom.tls.record.MessageInterpreter.interpretContent(Unknown Source)
  10. at com.certicom.tls.record.MessageInterpreter.decryptMessage(Unknown Source)
  11. at com.certicom.tls.record.ReadHandler.processRecord(Unknown Source)
  12. at com.certicom.tls.record.ReadHandler.readRecord(Unknown Source)
  13. at com.certicom.tls.record.ReadHandler.readUntilHandshakeComplete(Unknown Source)
  14. at com.certicom.tls.interfaceimpl.TLSConnectionImpl.completeHandshake(Unknown Source)
  15. at com.certicom.tls.record.WriteHandler.write(Unknown Source)
  16. at com.certicom.io.OutputSSLIOStreamWrapper.write(Unknown Source)
  17. at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
  18. at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
  19. at java.io.FilterOutputStream.flush(FilterOutputStream.java:123)
  20. at weblogic.net.http.HttpURLConnection.writeRequests(HttpURLConnection.java:154)
  21. at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:358)
  22. at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLConnection.java:37)
  23. at weblogic.net.http.HttpURLConnection.getResponseCode(HttpURLConnection.java:947)
  24. at (my own code)@H_403_7@
  25. 我的SimpleSocketFactory看起来像:

  26. public static final SSLSocketFactory getSocketFactory()
  27. {
  28.     if ( sslSocketFactory == null ) {
  29.         try {
  30.             // get ssl context
  31.             SSLContext sc = SSLContext.getInstance("SSL");
  32.             // Create a trust manager that does not validate certificate chains
  33.             TrustManager[] trustAllCerts = new TrustManager[]{
  34.                 new NaiveTrustManager() {
  35.                     public java.security.cert.X509Certificate[] getAcceptedIssuers() {
  36.                         log.debug("getAcceptedIssuers");
  37.                         return new java.security.cert.X509Certificate[0];
  38.                     }
  39.                     public void checkClientTrusted(
  40.                         java.security.cert.X509Certificate[] certs,String authType) {
  41.                         log.debug("checkClientTrusted");
  42.                     }
  43.                     public void checkServerTrusted(
  44.                         java.security.cert.X509Certificate[] certs,String authType) {
  45.                         log.debug("checkServerTrusted");
  46.                     }
  47.                 }
  48.             };
  49.             sc.init(null,trustAllCerts,new java.security.SecureRandom());
  50.             // EDIT: fixed the following line that was redeclaring SSLSocketFactory sslSocketFactory,returning null every time. Same result though.
  51.             sslSocketFactory = sc.getSocketFactory();
  52.             HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
  53.             // EDIT: The following line has no effect
  54.             //HttpsURLConnection.setDefaultHostnameVerifier(new NaiveHostNameVerifier());
  55.         } catch (KeyManagementException e) {
  56.             log.error ("No SSL algorithm support: " + e.getMessage(),e);
  57.         } catch (NoSuchAlgorithmException e) {
  58.             log.error ("Exception when setting up the Naive key management.",e);
  59.         }
  60.     }
  61.     return sslSocketFactory;
  62. }@H_403_7@ 
  63.  

    NaiveHostnameVerifier有一种方法来限制有效的主机,但它是空的,所以基本上接受任何东西:

  64.   
  65.  
    public class NaiveHostnameVerifier implements HostnameVerifier {
  66.     String[] patterns;
  67.     public NaiveHostnameVerifier () {
  68.         this.patterns=null;
  69.     }
  70.     public NaiveHostnameVerifier (String[] patterns) {
  71.         this.patterns = patterns;
  72.     }
  73.     public boolean verify(String urlHostName,SSLSession session) {
  74.         if (patterns==null || patterns.length==0) {
  75.             return true;
  76.         } else {
  77.             for (String pattern : patterns) {
  78.                 if (urlHostName.matches(pattern)) {
  79.                     return true;
  80.                 }
  81.             }
  82.             return false;
  83.         }
  84.     }
  85. }@H_403_7@ 
  86.  

    用法是这样的:

  87.   
  88.  
    try {
  89.         conn = (HttpURLConnection)url.openConnection();
  90.         if (conn instanceof HttpsURLConnection) {
  91.                 ((HttpsURLConnection)conn).setSSLSocketFactory(SimpleSSLSocketFactory.getSocketFactory());
  92.                 // EDIT: added this line,the HV has to be set on connection,not on the factory.
  93.                 ((HttpsURLConnection)conn).setHostnameVerifier(new NaiveHostnameVerifier());
  94.         }
  95.         conn.setDoInput(true);
  96.         conn.setDoOutput(true);
  97.         conn.setRequestMethod("POST");
  98.         conn.setRequestProperty("Content-type","application/x-www-form-urlencoded");
  99.         conn.connect();
  100.         StringBuffer sbContent = new StringBuffer();
  101.         // (snip)
  102.         DataOutputStream stream = new DataOutputStream(conn.getOutputStream ());
  103.         stream.writeBytes(sbContent.toString());
  104.         stream.flush();
  105.         stream.close();
  106.     } catch (ClassCastException e) {
  107.         log.error("The URL does not seem to point to a HTTP connection");
  108.         return null;
  109.     } catch (IOException e) {
  110.         log.error("Error accessing the requested URL",e);
  111.         return null;
  112.     }@H_403_7@ 
  113.  

    当我正在搜索错误消息时,大多数人只是在他们的商店导入证书,但再次,我不能这样做,因为我不知道哪个证书是.我唯一的选择,如果这不工作是制作一个工具,可以下载证书,并添加一个更简单的方式,隐藏的命令行,但我宁愿让我的Java代码只是忽略无效的证书.

  114.  

    任何想法

解决方法

上面的代码实际上没有错误.这个问题似乎在于Weblogic和这个Certicom TLS模块.当我查看服务器选项时,SSL和Advanced我看到我可以指定一个自定义的HostnameVerifier(SSLMBean.HostnameVerifier),但建议有能力干扰证书验证的唯一元素已被弃用.

我在Weblogic之外尝试了上面的代码,它工作得很好(固定了Postname中的HostnameVerifier).

然后,我试图在this other question中提出由ipolevoy提出的“-DUseSunHttpHandler = true”到Weblogic参数.它开始工作.

话虽如此,在Oracle Service Bus服务器上切换HTTP处理程序似乎有点冒险.几个星期的时间里,可能会有副作用让我再次咬我

我还试图定义我自己的trustStore,并将其指向包含所需密钥的jssecacert. Weblogic也被忽略,因为它有自己的每个服务器的trustStore设置.所以我要求管理员手动导入所需的键或将Weblogic指向我自己的商店.

猜你在找的Java相关文章