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