2011-05-18 144 views
45

我正在使用Jersey Client库对运行在jboss上的其他服务运行测试。 我已经使用自签名证书在服务器(在本地主机上运行)上设置了https。忽略使用Jersey客户端的自签名ssl证书

然而,每当我跑我的测试与HTTPS URL我收到以下错误:

com.sun.jersey.api.client.ClientHandlerException: 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 
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:131) 
    at com.sun.jersey.api.client.Client.handle(Client.java:629) 
    at com.sun.jersey.oauth.client.OAuthClientFilter.handle(OAuthClientFilter.java:137) 
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:601) 
    at com.sun.jersey.api.client.WebResource.access$200(WebResource.java:74) 
    at com.sun.jersey.api.client.WebResource$Builder.get(WebResource.java:459) 
    at test.helper.Helper.sendSignedRequest(Helper.java:174) 
    ... And so on 

我知道这是因为我的自签名的证书是不是在Java密钥库。有没有什么办法可以让Client不检查ssl证书的有效性,只是不管用吗?

这段代码只能运行在测试服务器上,所以我不想在每次设置新的测试服务器时都加入新的可信任证书。

下面是其进行调用的代码:

OAuthParameters params = new OAuthParameters(); 

// baseline OAuth parameters for access to resource 
params.signatureMethod(props.getProperty("signature_method")); 
params.consumerKey(props.getProperty("consumer_key")); 
params.setToken(props.getProperty("token")); 
params.setVersion("1.0"); 
params.nonce(); 

// OAuth secrets to access resource 
OAuthSecrets secrets = new OAuthSecrets(); 
secrets.consumerSecret(props.getProperty("consumer_secret")); 
secrets.setTokenSecret(props.getProperty("token_secret")); 

// Jersey client to make REST calls to token services 
Client client = Client.create(); 

// OAuth test server resource 
WebResource resource = client.resource(props.getProperty("url")); 

// if parameters and secrets remain static, filter cab be added to each web resource 
OAuthClientFilter filter = new OAuthClientFilter(client.getProviders(), params, secrets); 

// filter added at the web resource level 
resource.addFilter(filter); 
WebResource.Builder wbr = resource.getRequestBuilder().accept(props.getProperty("accept")); 

return wbr.get(ClientResponse.class); 

任何帮助将不胜感激。

回答

73

经过一番搜索,并通过一些旧的计算器问题拖网我发现在先前被问到的问题这样的问题的解决方案:

下面的代码我结束了使用。

// Create a trust manager that does not validate certificate chains 
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){ 
    public X509Certificate[] getAcceptedIssuers(){return null;} 
    public void checkClientTrusted(X509Certificate[] certs, String authType){} 
    public void checkServerTrusted(X509Certificate[] certs, String authType){} 
}}; 

// Install the all-trusting trust manager 
try { 
    SSLContext sc = SSLContext.getInstance("TLS"); 
    sc.init(null, trustAllCerts, new SecureRandom()); 
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
} catch (Exception e) { 
    ; 
} 
+0

克里斯,你有与Java 7的兼容版本?在你的代码中,你根本没有提供KeyStore,你是否使用-D指定了一个使用SSL属性给虚拟机的密钥库? – Uri 2013-12-19 12:45:16

+0

我没有指定KeyStore。我使用了上面的代码,没有任何其他虚拟机的争论。如果我相信代码的工作原理是因为它不检查它是否由可信签名人签名,它只会检查它是否格式正确。 – 2014-01-24 19:05:26

+6

我不得不更换'公共X509证书[] getAcceptedIssuers(){返回null;}'和'公共X509证书[] getAcceptedIssuers(){返回新的X509证书[0];}',使其工作。 – 2014-05-19 14:04:01

10

我有同样的问题ADN不希望这是全局设置,所以我用同样的TrustManager和的SSLContext代码上面,我只是改变了客户有特殊属性,可以创建

ClientConfig config = new DefaultClientConfig(); 
config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties(
    new HostnameVerifier() { 
     @Override 
     public boolean verify(String s, SSLSession sslSession) { 
      // whatever your matching policy states 
     } 
    } 
)); 
Client client = Client.create(config); 
+0

此代码不能编译:找不到符号“sc”。 – 2013-07-08 21:54:30

+0

删除ARG,让HTTPSProperites使用此构造https://jersey.java.net/nonav/apidocs/1.12/jersey/com/sun/jersey/client/urlconnection/HTTPSProperties.html#HTTPSProperties(javax.net.ssl.HostnameVerifier ) – 2013-07-09 14:00:17

-2

用这段代码工作。可能是其对Java 1.7

TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { 

     @Override 
     public X509Certificate[] getAcceptedIssuers() { 
      // TODO Auto-generated method stub 
      return null; 
     } 

     @Override 
     public void checkServerTrusted(X509Certificate[] arg0, String arg1) 
       throws CertificateException { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void checkClientTrusted(X509Certificate[] arg0, String arg1) 
       throws CertificateException { 
      // TODO Auto-generated method stub 

     } 
    }}; 

    // Install the all-trusting trust manager 
    try { 
     SSLContext sc = SSLContext.getInstance("TLS"); 
     sc.init(null, trustAllCerts, new SecureRandom()); 
     HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
    } catch (Exception e) { 
     ; 
    } 
+0

这个答案与Chris Salij的答案相同,除了它更详细,并且在几个月后回答。 – 2013-09-25 11:16:52

8

This code will only ever be run against test servers so I don't want to go to the hassle of adding new trusted certs each time we set up a new test server.

这是什么样的代码最终会找到自己的方式在生产中(如果不从你的,别人谁在阅读这个问题将复制并粘贴不安全的信任管理器已经在他们的应用中被建议)。当你有最后期限时,忘记删除这类代码是很容易的,因为它不会成为问题。

如果您担心每次有测试服务器时都必须添加新证书,请创建您自己的小CA,使用该CA颁发测试服务器的所有证书并将此CA证书导入您的客户端信任存储。 (即使你没有在本地环境中处理在线证书撤销等事情,这当然比使用允许任何事情通过的信任管理器更好。)

有工具可以帮助你做到这一点,例如TinyCAXCA

8

由于我是新来的StackOverflow,并有较小的声誉别人的答案发表评论,我把克里斯Salij一些修正,它为我工作建议的解决方案。

  SSLContext ctx = null; 
      TrustManager[] trustAllCerts = new X509TrustManager[]{new X509TrustManager(){ 
       public X509Certificate[] getAcceptedIssuers(){return null;} 
       public void checkClientTrusted(X509Certificate[] certs, String authType){} 
       public void checkServerTrusted(X509Certificate[] certs, String authType){} 
      }}; 
      try { 
       ctx = SSLContext.getInstance("SSL"); 
       ctx.init(null, trustAllCerts, null); 
      } catch (NoSuchAlgorithmException | KeyManagementException e) { 
       LOGGER.info("Error loading ssl context {}", e.getMessage()); 
      } 

      SSLContext.setDefault(ctx); 
+0

您可以请张贴您的进口? – thermz 2015-12-07 10:26:05

3

只需在导入中添加相同的代码即可。还包含编译所需的未实现代码。我最初无法找到为此代码导入的内容。还要为X509Certificate添加正确的软件包。得到这个带有试验和错误的工作:

import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
import javax.security.cert.CertificateException; 
import javax.security.cert.X509Certificate; 
import javax.ws.rs.core.MultivaluedMap; 

TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { 

    public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
     java.security.cert.X509Certificate[] chck = null; 
     ; 
     return chck; 
    } 

    public void checkServerTrusted(X509Certificate[] arg0, String arg1) 
      throws CertificateException { 
     // TODO Auto-generated method stub 

    } 

    public void checkClientTrusted(X509Certificate[] arg0, String arg1) 
      throws CertificateException { 

    } 

    public void checkClientTrusted(
      java.security.cert.X509Certificate[] arg0, String arg1) 
        throws java.security.cert.CertificateException { 
     // TODO Auto-generated method stub 

    } 

    public void checkServerTrusted(
      java.security.cert.X509Certificate[] arg0, String arg1) 
        throws java.security.cert.CertificateException { 
     // TODO Auto-generated method stub 

    } 
} }; 

// Install the all-trusting trust manager 
try { 
    SSLContext sc = SSLContext.getInstance("TLS"); 
    sc.init(null, trustAllCerts, new SecureRandom()); 
    HttpsURLConnection 
    .setDefaultSSLSocketFactory(sc.getSocketFactory()); 
} catch (Exception e) { 
    ; 
} 
+0

你只需要@Override java.security.cert。*的东西。 – alfonx 2015-09-22 10:57:36

34

泽西岛2 *(测试2.7)和Java 8:

import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 

public static Client ignoreSSLClient() throws Exception { 

    SSLContext sslcontext = SSLContext.getInstance("TLS"); 

    sslcontext.init(null, new TrustManager[]{new X509TrustManager() { 
     public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} 
     public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} 
     public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } 
    }}, new java.security.SecureRandom()); 

    return ClientBuilder.newBuilder() 
         .sslContext(sslcontext) 
         .hostnameVerifier((s1, s2) -> true) 
         .build(); 
} 
+3

哪里是进口包? java或javax? – Dejell 2015-06-30 14:54:38

+2

import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; – masi 2017-01-27 17:47:13

+0

非常感谢你.....谢谢SO – user373201 2017-09-12 19:11:24

0

对于新泽西1.X

TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() { 

     public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {} 

     public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {} 

     public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
      // or you can return null too 
      return new java.security.cert.X509Certificate[0]; 
     } 
    }}; 


    SSLContext sc = SSLContext.getInstance("TLS"); 
    sc.init(null, trustAllCerts, new SecureRandom()); 
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { 
     public boolean verify(String string, SSLSession sslSession) { 
      return true; 
     } 
    }); 
+1

你也不能返回null。看到Javadoc。 – EJP 2016-12-29 09:13:28

+0

请测试,你会看到结果! – grep 2016-12-29 09:19:09

+0

阅读类似答案http://stackoverflow.com/a/27708307/2590960 – grep 2016-12-29 09:19:44

0

使用lambda表达式对于Jersey 2.x

ClientBuilder.newBuilder() 
      .hostnameVerifier((HostnameVerifier) (h, s) -> { 
       return true; 
      }).build(); 
+1

这将仅禁用主机名验证,而不是证书验证。 – masi 2017-01-27 18:00:09

1

对于Jersey 2.x上没有人lambda表达式,使用:

import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import javax.net.ssl.HostnameVerifier; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 
import javax.ws.rs.client.Client; 
import javax.ws.rs.client.ClientBuilder; 

public static Client getUnsecureClient() throws Exception 
{ 
    SSLContext sslcontext = SSLContext.getInstance("TLS"); 
    sslcontext.init(null, new TrustManager[]{new X509TrustManager() 
    { 
      public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{} 
      public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{} 
      public X509Certificate[] getAcceptedIssuers() 
      { 
       return new X509Certificate[0]; 
      } 

    }}, new java.security.SecureRandom()); 


    HostnameVerifier allowAll = new HostnameVerifier() 
    { 
     @Override 
     public boolean verify(String hostname, SSLSession session) { 
      return true; 
     } 
    }; 

    return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(allowAll).build(); 
} 

测试与球衣的客户端2.11 JRE 1.7

相关问题