Игнорировать самоподписанный сертификат ssl с помощью 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);
Любая помощь будет принята с благодарностью.
Ответы
Ответ 1
После некоторого поиска и опрокидывания некоторых старых вопросов 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) {
;
}
Ответ 2
Для Джерси 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
У меня была такая же проблема, и я не хотел, чтобы это было настроено глобально, поэтому я использовал тот же код 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);
Ответ 4
Этот код будет запускаться только на тестовых серверах, поэтому я не хочу чтобы перейти к сложностям добавления новых доверенных сертификатов каждый раз, когда мы настраиваем новый тестовый сервер.
Это тот код, который в конечном итоге найдет свой путь в производстве (если не от вас, кто-то, кто читает этот вопрос, скопирует и вставляет незащищенные доверительные менеджеры, которые были предложены в их приложениях). Просто так легко забыть удалить этот тип кода, когда у вас есть крайний срок, поскольку он не отображается как проблема.
Если вы беспокоитесь о необходимости добавления новых сертификатов каждый раз, когда у вас есть тестовый сервер, создайте свой собственный ЦС, выпустите все сертификаты для тестовых серверов с помощью этого ЦС и импортируйте этот сертификат ЦС в хранилище доверия клиентов. (Даже если вы не имеете дело с такими вещами, как аннулирование онлайн-сертификата в локальной среде, это, безусловно, лучше, чем использование доверительного менеджера, который пропускает что-либо через.)
Есть инструменты, которые помогут вам сделать это, например TinyCA или XCA.
Ответ 5
Поскольку я новичок в stackoverflow и имею меньшую репутацию, чтобы комментировать ответы других, я помещаю решение, предложенное Крисом Слайем, с некоторой модификацией, которая сработала для меня.
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);
Ответ 6
Для тех, кто на Джерси 2.x без lambdas, используйте это:
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();
}
Протестировано jersey-client 2.11 на JRE 1.7.
Ответ 7
Просто добавьте тот же код с импортом. Также содержит невыполненный код, необходимый для компиляции. Сначала мне не удалось выяснить, что было импортировано для этого кода. Также добавьте правильный пакет для 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) {
;
}
Ответ 8
Для Джерси 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
Ответ 9
Для Джерси 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;
}
});
Ответ 10
Используйте лямбда для Джерси 2.x
ClientBuilder.newBuilder()
.hostnameVerifier((HostnameVerifier) (h, s) -> {
return true;
}).build();
Ответ 11
Я заметил, что при использовании конфигурации http-клиента Apache с диспетчером пула принятый ответ не работает.
В этом случае кажется, что ClientConfig.sslContext
и ClientConfig.hostnameVerifier
игнорируются. Поэтому, если вы используете пул соединений с конфигурацией HTTP-клиента Apache, вы можете использовать следующий код, чтобы игнорировать проверку 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);
Ответ 12
Хорошо, я хотел бы просто добавить свой класс только потому, что в будущем может появиться какой-то разработчик, который захочет подключиться к серверу Netbackup (или что-то подобное) и делать что-то из Java, игнорируя сертификат SSL. Это сработало для меня, и мы используем Windows Active Directory для аутентификации на сервере 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, вероятно, окажется здесь. Кстати большое спасибо всем ответам на этот вопрос! Спецификация, о которой я говорю, находится здесь, и в их примерах кода (в настоящее время) отсутствует пример Java.
*** Это, конечно, небезопасно, поскольку мы игнорируем сертификат!
Ответ 13
работал у меня с этим кодом. Может быть для 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) {
;
}