使用Jersey客户端忽略自签名SSL证书

我使用Jersey Client库来运行在jboss上运行的rest服务的testing。 我已经在服务器(在本地主机上运行)上使用自签名证书设置好了https。

但是,每当我运行我的testing与httpsurl,我得到以下错误:

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证书的有效性,只是不pipe用吗?

这个代码将只能运行在testing服务器上,所以我不想在每次我们build立一个新的testing服务器的时候去添加新的可信任的证书。

这是打电话的代码:

 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); 

任何帮助将不胜感激。

经过一些search和拖网通过一些旧的stackoverflow的问题,我已经find了一个在以前问SO的问题的解决scheme:

  • 问题: 通过HTTPS / SSL的Java客户端证书
  • 通过HTTPS / SSL回答Java客户端证书

这是我最终使用的代码。

 // 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) { ; } 

泽西2. *(testing2.7)和Java 8:

  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(); } 

我有同样的问题,并不希望这是全局设置,所以我使用了上述相同的TrustManager和SSLContext代码,我只是改变了客户端创build具有特殊属性

  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); 

这个代码将只能运行在testing服务器上,所以我不想在每次我们build立一个新的testing服务器的时候去添加新的可信任的证书。

这是最终会在生产中find它的方式(如果不是从你那里读取这个问题的其他人会复制和粘贴已经build议到他们的应用程序的不安全的信任pipe理器)。 在截止date之前忘记删除这类代码是很容易的,因为它不会成为问题。

如果您担心每次有testing服务器时都必须添加新证书,请创build您自己的小CA,使用该CA为testing服务器颁发所有证书,并将此CA证书导入您的客户端信任库。 (即使你没有在本地环境中处理在线证书吊销之类的事情,这当然比使用让任何事情通过的信任pipe理器更好。

有工具可以帮助你做到这一点,例如TinyCA或XCA 。

由于我是一个新的stackoverflow和较低的声誉评论别人的答案,我把解决schemebuild议由克里斯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); 

只需添加相同的代码与导入。 还包含编译所需的未实现代码。 我最初无法find为此代码导入的内容。 还要为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) { ; } 

泽西2. *:

 Client client = ClientBuilder.newBuilder() .hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }).build(); 

– > https://jersey.java.net/documentation/latest/migration.html

对于泽西岛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; } }); 

对Jersey 2.x使用lambdas

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

对于没有lambdas的泽西岛2.x的任何人,使用这个:

 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(); } 

JRE 1.7上使用jersey客户端2.11进行testing。

用这个代码为我工作。 可能是它的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) { ; }