我正在使用Jersey Client库对运行在jboss上的休息服务运行测试。我使用自签名证书在服务器上运行https(在localhost上运行)。
但是每当我使用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);
任何帮助将不胜感激。
经过一些旧的stackoverflow问题的搜索和搜索后,我在之前提出的SO问题中找到了一个解决方案:
这是我最终使用的代码。
// 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) {
;
}
我注意到,当将Apache http客户端配置与池管理器一起使用时,接受的答案不起作用。
在这种情况下,似乎ClientConfig.sslContext
和ClientConfig.hostnameVerifier
setter被默默地忽略了。因此,如果您使用apache客户端http客户端配置连接池,您应该能够使用以下代码来忽略ssl验证:
ClientConfig clientConfig = new ClientConfig();
// ... configure your clientConfig
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
}, null);
} catch (NoSuchAlgorithmException e) {
//logger.debug("Ignoring 'NoSuchAlgorithmException' while ignoring ssl certificate validation.");
} catch (KeyManagementException e) {
//logger.debug("Ignoring 'KeyManagementException' while ignoring ssl certificate validation.");
}
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", new SSLConnectionSocketFactory(sslContext, new AbstractVerifier() {
@Override
public void verify(String host, String[] cns, String[] subjectAlts) {
}
}))
.build();
connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
clientConfig.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
return ClientBuilder.newClient(clientConfig);
好的,我只想添加我的类,因为将来可能会有一些想要连接到Netbackup服务器(或类似的东西)的dev,并且在忽略SSL证书的情况下从Java做一些事情。这对我有用,我们使用Windows活动目录来验证Netbackup服务器。
public static void main(String[] args) throws Exception {
SSLContext sslcontext = null;
try {
sslcontext = SSLContext.getInstance("TLS");
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
try {
sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
@Override
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}}, new java.security.SecureRandom());
} catch (KeyManagementException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
//HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().credentials(username, password).build();
ClientConfig clientConfig = new ClientConfig();
//clientConfig.register(feature);
Client client = ClientBuilder.newBuilder().withConfig(clientConfig)
.sslContext(sslcontext)
.hostnameVerifier((s1, s2) -> true)
.build();
//String the_url = "https://the_server:1556/netbackup/security/cacert";
String the_token;
{
String the_url = "https://the_server:1556/netbackup/login";
WebTarget webTarget = client.target(the_url);
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
String jsonString = new JSONObject()
.put("domainType", "NT")
.put("domainName", "XX")
.put("userName", "the username")
.put("password", "the password").toString();
System.out.println(jsonString);
Response response = invocationBuilder.post(Entity.json(jsonString));
String data = response.readEntity(String.class);
JSONObject jo = new JSONObject(data);
the_token = jo.getString("token");
System.out.println("token is:" + the_token);
}
{
String the_url = "https://the_server:1556/netbackup/admin/jobs/1122012"; //job id 1122012 is an example
WebTarget webTarget = client.target(the_url);
Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON).header(HttpHeaders.AUTHORIZATION, the_token).header(HttpHeaders.ACCEPT, "application/vnd.netbackup+json;version=1.0");
Response response = invocationBuilder.get();
System.out.println("response status:" + response.getStatus());
String data = response.readEntity(String.class);
//JSONObject jo = new JSONObject(data);
System.out.println(data);
}
}
我知道它可以被认为是偏离主题的,但我敢打赌试图连接到Netbackup服务器的开发者可能会在这里结束。顺便说一句,非常感谢这个问题的所有答案!我正在谈论的规范是here和their code samples(目前)缺少Java示例。
***这当然不安全,因为我们忽略了证书!
用这个代码为我工作。可能是它的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) {
;
}
对于Jersey 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();
}
我有同样的问题,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);
由于我是stackoverflow的新手并且对其他人的答案发表评论的声誉较低,因此我将Chris 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);
对于没有lambda的Jersey 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-client 2.11进行测试。
只需在导入中添加相同的代码即可。还包含编译所需的未实现代码。我最初很难找到为此代码导入的内容。还为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
对于Jersey 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;
}
});