Java Quarkus/MicroProfile Restclient inject sslContext - java

How I can inject a custom sslContext by use the #RegisterRestClient inside a interface ?

Nor Quarkus or Microprofile allow you to programmatically build the rest client (that's the purpose of providing you a interface auto-implemented afterall).
You could nevertheless implement by yourself the rest-client interface and set your javax.net.ssl.SSLContext.
The example below is meant to provide a SSLContext trusting all hosts:
package org.me.rest;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.annotation.Priority;
import javax.enterprise.context.ApplicationScoped;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.me.rest.MyRestClient;
#Priority(value = 1) //choose an appropriate value here
#RestClient
#ApplicationScoped
public class MyRestClientImpl implements MyRestClient {
#Override
public Response getTheResource() {
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("TLS");
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] {
tm
}, null);
} catch (Exception e) {
e.printStackTrace();
}
AuthRestClient client =
RestClientBuilder.newBuilder().baseUri(URI.create("https://hostname:port/some/rest/resource/"))
.hostnameVerifier(new NoopHostnameVerifier()).sslContext(sslContext).build(AuthRestClient.class);
return client.getTheResource();
}
}

Related

Exception occurred while loading keystore in springboot || Can't get the password

Not able to get password for key-store i tried with "changeit" but it didn't worked.
When i click on springblog.jks it asks for password.How can i get the password for key-store it throwing error while running the application.
package com.devesh.springreddit.security;
import com.devesh.springreddit.exception.SpringRedditException;
import io.jsonwebtoken.Jwts;
import jakarta.annotation.PostConstruct;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.cert.CertificateException;
#Service
public class JWTProvider {
private KeyStore keyStore;
#PostConstruct
public void init(){
try{
keyStore = KeyStore.getInstance("JKS");
InputStream inputStream = getClass().getResourceAsStream("/springblog.jks");
keyStore.load(inputStream,"secret".toCharArray());
} catch (KeyStoreException |CertificateException | NoSuchAlgorithmException | IOException e) {
throw new SpringRedditException("Exception occurred while loading keystore");
}
}
public String generateToken(Authentication authentication){
User principle = (User) authentication.getPrincipal();
return Jwts.builder().setSubject(principle.getUsername())
.signWith(getPrivateKey())
.compact();
}
private PrivateKey getPrivateKey() {
try{
return (PrivateKey) keyStore.getKey("springblog","secret".toCharArray());
}catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e){
throw new SpringRedditException("Exception occurred while getting public key from keystore");
}
}
}

System.err: TypeError: com.tns.TestObject is not a constructor

I'm using Nativescript. I create TestObject.java in C:\project\platforms\android\app\src\main\java\com\tns and write this:
package com.tns;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class TestObject {
public void disableSSLCertificateChecking() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// Not implemented
}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
// Not implemented
}
} };
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
My question is, how to call this function in main.ts in my application?
I tried ti add in TestObject.java
public String doSomething () {
return "hello";
}
and in main.ts write this:
var test = new com.tns.TestObject();
console.log(test.doSomething());
error when app execute
System.err: java.lang.RuntimeException: Unable to create application
com.tns.NativeScriptApplication: com.tns.NativeScriptException:
System.err: Error calling module function
System.err: TypeError: com.tns.TestObject is not a constructor
System.err: File: "file:///data/data/org.nativescript.project/files/app/main.js, line:
29, column: 15
System.err: StackTrace:
System.err: Frame: function:'', file:'file:///data/data/org.nativescript.project/files/app/main.js',
line: 29, column: 16
Any idea please?

HTTPS Volley Invalid header issue

Before all : if you don't know the exact answer so just give me advice how to check. Thanks
I have alreary tried a lot of different way how to implement ssl to my volley request but without success.
I can not understand way I get this error
ResponseJsonString = <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Header</h2>
<hr><p>HTTP Error 400. The request has an invalid header name.</p>
</BODY></HTML>
So step by step my code implementation
This is how I get the volley queue
mRequestQueue = Volley.newRequestQueue(this, new SslHurlStuck(SslUtils.KEYSTORE, SslUtils.PASSWORD_SSL, this));
there is my SslHurlStuck
package utils.ssl;
import android.content.Context;
import android.util.Log;
import com.android.volley.toolbox.HurlStack;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import utils.global.AppUtils;
public class SslHurlStuck extends HurlStack
{
private final static String TAG = SslHurlStuck.class.getSimpleName();
private String mTrustStoreAssetName;
private String mTrustStorePassword;
private Context mContext;
public SslHurlStuck(final String iTrustStoreAssetName, final String iTrustStorePassword, Context iContext)
{
super();
mTrustStoreAssetName = iTrustStoreAssetName;
mTrustStorePassword = iTrustStorePassword;
mContext = iContext;
}
#Override
protected HttpURLConnection createConnection(URL url) throws IOException
{
HttpsURLConnection urlConnection = null;
try
{
urlConnection = new PinnedCertificateHttpsURLConnectionFactory(mContext).createHttpsURLConnection(url.toString(), mTrustStoreAssetName, mTrustStorePassword);
}
catch (Throwable iThrowable)
{
AppUtils.printLog(Log.ERROR, TAG, iThrowable.getMessage());
}
return urlConnection;
}
}
And eventually there is my PinnedCertificateHttpsURLConnectionFactory
package utils.ssl;
import android.content.Context;
import android.util.Log;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import utils.global.AppUtils;
import webServices.global.RequestStringBuilder;
public class PinnedCertificateHttpsURLConnectionFactory
{
private final static String TAG = PinnedCertificateHttpsURLConnectionFactory.class.getSimpleName();
private final Context mContext;
public PinnedCertificateHttpsURLConnectionFactory(Context iContext)
{
mContext = iContext;
}
HttpsURLConnection createHttpsURLConnection(String urlString, final String iTrustStoreAssetName, final String iTrustStorePassword) throws Throwable
{
// Initialize the trust manager factory instance with our trust store
// as source of certificate authorities and trust material.
KeyStore trustStore = new TrustStoreFactory(iTrustStoreAssetName, iTrustStorePassword, mContext).createTrustStore();
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm);
trustManagerFactory.init(trustStore);
// Initialize the SSL context.
TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(trustManagerFactory.getTrustManagers());
SSLContext sslContext = SSLContext.getInstance(SslUtils.PROTOCOL_TLS);
sslContext.init(null, wrappedTrustManagers, null);
// Create the https URL connection.
URL url = new URL(urlString);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(sslContext.getSocketFactory());
urlConnection.setHostnameVerifier(getHostnameVerifier());
return urlConnection;
}
// Let's assume your server app is hosting inside a server machine
// which has a server certificate in which "Issued to" is "localhost",for example.
// Then, inside verify method you can verify "localhost".
// If not, you can temporarily return true
private HostnameVerifier getHostnameVerifier()
{
return new HostnameVerifier()
{
#Override
public boolean verify(String hostname, SSLSession session)
{
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
String localHost = SslUtils.SSL_LOCAL_HOST_DEV;
if (RequestStringBuilder.isEnvironmentProd())
{
localHost = SslUtils.SSL_LOCAL_HOST_PROD;
}
return hv.verify(localHost, session);
// return hv.verify("localhost", session);
// return true;
}
};
}
private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers)
{
final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
final X509TrustManager x509TrustManager = new X509TrustManager()
{
public X509Certificate[] getAcceptedIssuers()
{
return originalTrustManager.getAcceptedIssuers();
}
public void checkClientTrusted(X509Certificate[] certs, String authType)
{
try
{
if (certs != null && certs.length > 0)
{
for (X509Certificate cer : certs)
{
cer.checkValidity();
}
}
else
{
originalTrustManager.checkClientTrusted(certs, authType);
}
}
catch (CertificateException e)
{
AppUtils.printLog(Log.ERROR, TAG, "checkClientTrusted" + e.toString());
}
}
public void checkServerTrusted(X509Certificate[] certs, String authType)
{
try
{
if (certs != null && certs.length > 0)
{
for (X509Certificate cer : certs)
{
cer.checkValidity();
}
}
else
{
originalTrustManager.checkServerTrusted(certs, authType);
}
}
catch (CertificateException e)
{
AppUtils.printLog(Log.ERROR, TAG, "checkServerTrusted" + e.toString());
}
}
};
return new TrustManager[] {x509TrustManager};
}
}
And last one TrustStoreFactory
public class TrustStoreFactory
{
private String mTrustStoreAssetName;
private String mTrustStorePassword;
private Context mContext;
public TrustStoreFactory(final String iTrustStoreAssetName, final String iTrustStorePassword, final Context iContext)
{
mTrustStoreAssetName = iTrustStoreAssetName;
mTrustStorePassword = iTrustStorePassword;
mContext = iContext;
}
KeyStore createTrustStore() throws Throwable
{
// Retrieve the trust store file from the assets.
InputStream inputStream = mContext.getAssets().open(mTrustStoreAssetName);
try
{
// Create a key store with the retrieved input stream.
KeyStore trustStore = KeyStore.getInstance(SslUtils.KEYSTORE_EXTENSION_BKS);
trustStore.load(inputStream, mTrustStorePassword.toCharArray());
return trustStore;
}
finally
{
inputStream.close();
}
}
}
So, question is , what am I doing wrong?
My keystore consist 2 cer files, I tried different combinations to add the cer to the keystore... but nothing was changed.
Actually I don't think that there is a problems with a code, I think some issue with certificates , but I can not understand what exactly, and how to fix it
And also what is intresting that in iOS the same ssl checking work in another way, we just need to get certificate from response and then getPublicKey() on it, and compare if public key from response certificate equal to certificate public key that consist within app... But in android it is much more difficult...
Feel free to ask
So eventyally in my case, I don't know why , but I just deleted Content-type header with the value from the response, and all is ok.
My answer was found here
Android Volley gives me 400 error
The Content-Type header is not treated the same way as other headers by Volley. In particular, overriding getHeaders() to change the content type does not always work. Check this ans for more information
Try this
headers.put("Content-Type", "application/json");

Java: Overriding function to disable SSL certificate check

The web service is rest over SSL and it has self signed certificate, hosted in remote system.I have already created a client accessing that web service. This is done by adding the certificate to the key store programatically.
Now I heard that, it is not necessary to add certificate to key store for accesing a self signed web service. Instead we can disable the certificate check by overriding some methods. Is this true? Which are those methods? Please help.
This should be sufficient. I use this when testing code against testing and staging servers where we don't have properly signed certificates. However, you should really really strongly consider getting a valid SSL certificate on your production server. Nobody wants to be wiretapped and have their privacy violated.
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[] { new TrustAllX509TrustManager() }, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){
public boolean verify(String string,SSLSession ssls) {
return true;
}
});
And this.
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
/**
* DO NOT USE IN PRODUCTION!!!!
*
* This class will simply trust everything that comes along.
*
* #author frank
*
*/
public class TrustAllX509TrustManager implements X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs,
String authType) {
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs,
String authType) {
}
}
Best of luck!
===UPDATE===
I just wanted to point out that there's a service called Let's Encrypt which automates the process of generating and setting up SSL/TLS certificates recognised by virtually everybody, and it's absolutely free!
Ignoring certs on a per-connection basis is much safer since any other code will still use the secure defaults.
The following code:
Overrides the trust manager and hostname verifier on a per-connection basis.
Reuses the SSLSocketFactory in order to support persistent connections, bypassing the expensive SSL handshake for repeated requests to the same server.
As others have stated, this should only be used for testing, and/or for internal systems communicating with other internal systems.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class TestPersistentConnection
{
private static SSLSocketFactory sslSocketFactory = null;
/**
* Use the VM argument <code>-Djavax.net.debug=ssl</code> for SSL specific debugging;
* the SSL handshake will appear a single time when connections are re-used, and multiple
* times when they are not.
*
* Use the VM <code>-Djavax.net.debug=all</code> for all network related debugging, but
* note that it is verbose.
*
* #throws Exception
*/
public static void main(String[] args) throws Exception
{
//URL url = new URL("https://google.com/");
URL url = new URL("https://localhost:8443/");
// Disable first
request(url, false);
// Enable; verifies our previous disable isn't still in effect.
request(url, true);
}
public static void request(URL url, boolean enableCertCheck) throws Exception {
BufferedReader reader = null;
// Repeat several times to check persistence.
System.out.println("Cert checking=["+(enableCertCheck?"enabled":"disabled")+"]");
for (int i = 0; i < 5; ++i) {
try {
HttpURLConnection httpConnection = (HttpsURLConnection) url.openConnection();
// Normally, instanceof would also be used to check the type.
if( ! enableCertCheck ) {
setAcceptAllVerifier((HttpsURLConnection)httpConnection);
}
reader = new BufferedReader(new InputStreamReader(httpConnection.getInputStream()), 1);
char[] buf = new char[1024];
StringBuilder sb = new StringBuilder();
int count = 0;
while( -1 < (count = reader.read(buf)) ) {
sb.append(buf, 0, count);
}
System.out.println(sb.toString());
reader.close();
} catch (IOException ex) {
System.out.println(ex);
if( null != reader ) {
reader.close();
}
}
}
}
/**
* Overrides the SSL TrustManager and HostnameVerifier to allow
* all certs and hostnames.
* WARNING: This should only be used for testing, or in a "safe" (i.e. firewalled)
* environment.
*
* #throws NoSuchAlgorithmException
* #throws KeyManagementException
*/
protected static void setAcceptAllVerifier(HttpsURLConnection connection) throws NoSuchAlgorithmException, KeyManagementException {
// Create the socket factory.
// Reusing the same socket factory allows sockets to be
// reused, supporting persistent connections.
if( null == sslSocketFactory) {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, ALL_TRUSTING_TRUST_MANAGER, new java.security.SecureRandom());
sslSocketFactory = sc.getSocketFactory();
}
connection.setSSLSocketFactory(sslSocketFactory);
// Since we may be using a cert with a different name, we need to ignore
// the hostname as well.
connection.setHostnameVerifier(ALL_TRUSTING_HOSTNAME_VERIFIER);
}
private static final TrustManager[] ALL_TRUSTING_TRUST_MANAGER = new TrustManager[] {
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
};
private static final HostnameVerifier ALL_TRUSTING_HOSTNAME_VERIFIER = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
}
Many thanks to:
http://runtime32.blogspot.com/2008/11/let-java-ssl-trust-all-certificates.html
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
GetCustomerPhone http = new GetCustomerPhone();
System.out.println("Processing..");
try{
http.sendPost();
}
catch(Exception e){
e.printStackTrace();
}
}
I think it will working fine.because it fine of me...

How to disable certificate validation in JAX-WS Client?

How do you disable certificate validation in JAX-WS client using javax.xml.ws.Service?
I tried creating an all-trusting TrustManager in the SSLSocketFactory and tried to bind it with BindingProvider
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
Map<String, Object> ctxt = ((BindingProvider) wsport ).getRequestContext();
ctxt.put(JAXWSProperties.SSL_SOCKET_FACTORY, sc.getSocketFactory());
but I still getting Exception: unable to find valid certification path to requested target
But it works when I just use
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
Or is there a way to make javax.xml.ws.Service use the HttpsURLConnection that I created?
I found a solution here:
http://schrepfler.blogspot.com.br/2009/06/relaxing-ssl-validation-for-jaxws.html
I'm using that solution calling the two static methods on a static block at the main class, like this:
static {
SSLUtilities.trustAllHostnames();
SSLUtilities.trustAllHttpsCertificates();
}
Hope this helps
EDIT: As David J. Liszewski pointed out, this breaks SSL/TLS for all connections from this JVM. So, keep that in mind.
The truth can be found from Erik Wramner's blog here http://erikwramner.wordpress.com/2013/03/27/trust-self-signed-ssl-certificates-and-skip-host-name-verification-with-jax-ws
I include the full solution where Apache CXF is used to make SOAP web service requests to a self-signed SharePoint https service:
NaiveSSLHelper.java
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.transport.http.HTTPConduit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.ws.BindingProvider;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
public class NaiveSSLHelper {
public static void makeWebServiceClientTrustEveryone(
Object webServicePort) {
if (webServicePort instanceof BindingProvider) {
BindingProvider bp = (BindingProvider) webServicePort;
Map requestContext = bp.getRequestContext();
requestContext.put(JAXWS_SSL_SOCKET_FACTORY, getTrustingSSLSocketFactory());
requestContext.put(JAXWS_HOSTNAME_VERIFIER,
new NaiveHostnameVerifier());
} else {
throw new IllegalArgumentException(
"Web service port "
+ webServicePort.getClass().getName()
+ " does not implement "
+ BindingProvider.class.getName());
}
}
public static SSLSocketFactory getTrustingSSLSocketFactory() {
return SSLSocketFactoryHolder.INSTANCE;
}
private static SSLSocketFactory createSSLSocketFactory() {
TrustManager[] trustManagers = new TrustManager[] {
new NaiveTrustManager()
};
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[0], trustManagers,
new SecureRandom());
return sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
return null;
}
}
public static void makeCxfWebServiceClientTrustEveryone(HTTPConduit http) {
TrustManager[] trustManagers = new TrustManager[]{
new NaiveTrustManager()
};
TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setSecureSocketProtocol("TLS");
tlsParams.setKeyManagers(new KeyManager[0]);
tlsParams.setTrustManagers(trustManagers);
tlsParams.setDisableCNCheck(true);
http.setTlsClientParameters(tlsParams);
}
private interface SSLSocketFactoryHolder {
SSLSocketFactory INSTANCE = createSSLSocketFactory();
}
private static class NaiveHostnameVerifier implements
HostnameVerifier {
#Override
public boolean verify(String hostName,
SSLSession session) {
return true;
}
}
private static class NaiveTrustManager implements
X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] certs,
String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] certs,
String authType) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
private static final java.lang.String JAXWS_HOSTNAME_VERIFIER =
"com.sun.xml.internal.ws.transport.https.client.hostname.verifier";
private static final java.lang.String JAXWS_SSL_SOCKET_FACTORY =
"com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory";
}
SoapTester.java
import crawler.common.sharepoint.stubs.sitedata.ArrayOfSList;
import crawler.common.sharepoint.stubs.sitedata.GetListCollectionResponse;
import crawler.common.sharepoint.stubs.sitedata.SList;
import crawler.common.sharepoint.stubs.sitedata.SiteData;
import crawler.common.sharepoint.stubs.sitedata.SiteDataSoap;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit;
import org.apache.cxf.transport.http.auth.HttpAuthHeader;
import org.apache.cxf.transport.http.auth.SpnegoAuthSupplier;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.ietf.jgss.GSSName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Holder;
import javax.xml.ws.Service;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This example will invoke a web service on SharePoint 2013+ with optional kerberos auth.
*/
public class SoapTester {
private static final Logger LOG = LoggerFactory.getLogger(SoapTester.class);
public static void main(String[] args) {
String endpointAddress = args[0];
String keytabFilePath = args.length > 2 ? args[1] : null;
String principalName = args.length > 2 ? args[2] : null;
String servicePrincipalName = args.length > 3 ? args[3] : null;
if (!endpointAddress.endsWith("/")) {
endpointAddress += "/";
}
endpointAddress += "_vti_bin/SiteData.asmx";
final String endpointAddressFinal = endpointAddress;
Service service = Service.create(SiteData.SERVICE);
SiteDataSoap soap = service.getPort(SiteDataSoap.class);
NaiveSSLHelper.makeWebServiceClientTrustEveryone(soap);
BindingProvider bindingProvider = (BindingProvider) soap;
bindingProvider.getRequestContext().put(AsyncHTTPConduit.USE_ASYNC,
Boolean.TRUE);
bindingProvider.getRequestContext().put(
BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointAddress);
List<Handler> chain = bindingProvider.getBinding().getHandlerChain();
chain.add(new SOAPHandler<SOAPMessageContext>() {
#Override
public boolean handleMessage(SOAPMessageContext context) {
String endpointAddress = (String) context.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
SOAPMessage msg = context.getMessage();
Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
msg.writeTo(out);
String str = new String(out.toByteArray());
LOG.info("Sharepoint xml [" + endpointAddress + "]" + (outbound ? " (Outbound)" : " (Inbound)") + ": " + str);
} catch (Exception e) {
LOG.error("Cannot get soap xml from message ", e);
}
if (outbound.booleanValue()) {
try {
context.getMessage().setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return true;
}
#Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
#Override
public void close(MessageContext context) {
}
#Override
public Set<QName> getHeaders() {
return null;
}
});
bindingProvider.getBinding().setHandlerChain(chain);
Client client = ClientProxy.getClient(bindingProvider);
client.getEndpoint().put("org.apache.cxf.stax.maxChildElements", System.getProperty("org.apache.cxf.stax.maxChildElements") != null ? System.getProperty("org.apache.cxf.stax.maxChildElements") : "5000000");
HTTPConduit http = (HTTPConduit) client.getConduit();
NaiveSSLHelper.makeCxfWebServiceClientTrustEveryone(http);
AuthorizationPolicy authorization = new AuthorizationPolicy();
authorization.setAuthorizationType(HttpAuthHeader.AUTH_TYPE_NEGOTIATE);
http.setAuthorization(authorization);
SpnegoAuthSupplier authSupplier = new SpnegoAuthSupplier();
if (servicePrincipalName != null) {
authSupplier.setServicePrincipalName(servicePrincipalName);
authSupplier.setServiceNameType(GSSName.NT_HOSTBASED_SERVICE);
}
Map<String, String> loginConfig = new HashMap<>();
loginConfig.put("useKeyTab", "true");
loginConfig.put("storeKey", "true");
loginConfig.put("refreshKrb5Config", "true");
loginConfig.put("keyTab", keytabFilePath);
loginConfig.put("principal", principalName);
loginConfig.put("useTicketCache", "true");
loginConfig.put("debug", String.valueOf(true));
authSupplier.setLoginConfig(new Configuration() {
#Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
return new AppConfigurationEntry[] {
new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
loginConfig)};
}
});
http.setAuthSupplier(authSupplier);
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setAutoRedirect(true);
http.setClient(httpClientPolicy);
Holder<ArrayOfSList> vLists = new Holder<>();
Holder<Long> getListCollectionResult = new Holder<>();
soap.getListCollectionAsync(getListCollectionResult, vLists, res -> {
try {
GetListCollectionResponse listCollectionResponse = res.get();
ArrayOfSList arrayOfSList = listCollectionResponse.getVLists();
LOG.info("Successfully got {} lists from {}", arrayOfSList.getSList().size(), endpointAddressFinal);
for (SList slist : arrayOfSList.getSList()) {
LOG.info("Successfully got list {}", slist.getTitle());
}
System.exit(0);
} catch (Exception e) {
LOG.error("List collection response", e);
}
});
}
}
Here is another example with respect to JDK7 and glassfish. Please pay attention for Nikolay Smirnov's comment as well. I use jdk 7 and glassfish 3.1.2. In this environment the suggested solution works perfect if the server deal with a self signed cerfificate.
// import com.sun.xml.ws.developer.JAXWSProperties;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.xml.ws.BindingProvider;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
/**
*
* Usage examples (BindingProvider port):
* NaiveSSLHelper.makeWebServiceClientTrustEveryone(port); // GlassFish
* NaiveSSLHelper.makeCxfWebServiceClientTrustEveryone(port); // TomEE
*
* Based on Erik Wramner's example frome here:
* http://erikwramner.wordpress.com/2013/03/27/trust-self-signed-ssl-certificates-and-skip-host-name-verification-with-jax-ws/
*
* I have extended the functionality when Apache CXF is used.
*/
public class NaiveSSLHelper {
private static final String JAXWS_HOSTNAME_VERIFIER = "com.sun.xml.ws.transport.https.client.hostname.verifier"; // JAXWSProperties.HOSTNAME_VERIFIER;
private static final String JAXWS_SSL_SOCKET_FACTORY = "com.sun.xml.ws.transport.https.client.SSLSocketFactory"; // JAXWSProperties.SSL_SOCKET_FACTORY;
// In Glassfish (Metro) environment you can use this function (Erik Wramner's solution)
public static void makeWebServiceClientTrustEveryone(Object webServicePort) {
if (webServicePort instanceof BindingProvider) {
BindingProvider bp = (BindingProvider) webServicePort;
Map requestContext = bp.getRequestContext();
requestContext.put(JAXWS_SSL_SOCKET_FACTORY, getTrustingSSLSocketFactory());
requestContext.put(JAXWS_HOSTNAME_VERIFIER, new NaiveHostnameVerifier());
} else {
throw new IllegalArgumentException(
"Web service port "
+ webServicePort.getClass().getName()
+ " does not implement "
+ BindingProvider.class.getName());
}
}
// In TomEE (Apache CXF) environment you can use this function (my solution)
public static void makeCxfWebServiceClientTrustEveryone(Object port) {
TrustManager[] trustManagers = new TrustManager[]{
new NaiveTrustManager()
};
Client c = ClientProxy.getClient(port);
HTTPConduit httpConduit = (HTTPConduit) c.getConduit();
TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setSecureSocketProtocol("SSL");
tlsParams.setKeyManagers(new KeyManager[0]);
tlsParams.setTrustManagers(trustManagers);
tlsParams.setDisableCNCheck(true);
httpConduit.setTlsClientParameters(tlsParams);
}
public static SSLSocketFactory getTrustingSSLSocketFactory() {
return SSLSocketFactoryHolder.INSTANCE;
}
private static SSLSocketFactory createSSLSocketFactory() {
TrustManager[] trustManagers = new TrustManager[]{
new NaiveTrustManager()
};
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(new KeyManager[0], trustManagers, new SecureRandom());
return sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
return null;
}
}
private static interface SSLSocketFactoryHolder {
public static final SSLSocketFactory INSTANCE = createSSLSocketFactory();
}
private static class NaiveHostnameVerifier implements
HostnameVerifier {
#Override
public boolean verify(String hostName,
SSLSession session) {
return true;
}
}
private static class NaiveTrustManager implements
X509TrustManager {
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] certs,
String authType) throws java.security.cert.CertificateException {
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] certs,
String authType) throws java.security.cert.CertificateException {
}
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[0];
}
}
}
Putting aside all security issues that come with it, if anyone still want to disable certificate validation in a JAX-WS Client. This is how i do.
NB: And this way, instead of breaking SSL/TLS for ALL connections, you disable certificate validation for THAT client only.
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
/** Custom JAX-WS client factory used to ignore certificate validation */
public class NotSecureClientFactory extends JaxWsProxyFactoryBean {
#Override
protected ClientProxy clientClientProxy(Client c) {
// Create a client factory that does not validate certificate chains
ClientProxy cp = super.clientClientProxy(c);
HTTPConduit httpConduit = (HTTPConduit) cp.getClient().getConduit();
httpConduit.setTlsClientParameters(tlsClientParameters());
return cp;
}
public TLSClientParameters tlsClientParameters() {
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) {
}
} };
TLSClientParameters tlsClientParameters = new TLSClientParameters();
tlsClientParameters.setTrustManagers(trustAllCerts);
return tlsClientParameters;
}
}
Actually CXF comes w/ an InsecureTrustManager for testing purpose.
For a Spring Boot app, it would be as easy as the following to disable TLS validation in all your CXF clients. Needless to say, u should NEVER do this in a prod env.
import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transport.https.InsecureTrustManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import javax.inject.Inject;
import javax.xml.ws.BindingProvider;
import java.util.Set;
#ConditionalOnProperty(value = "soap.validate-tls.client", havingValue = "true")
#Configuration
class DisableTlsCxfClientConfig {
#Inject
DisableTlsCxfClientConfig(Set<BindingProvider> soapClients) {
var insecureTlsParam = new TLSClientParameters();
insecureTlsParam.setTrustManagers(InsecureTrustManager.getNoOpX509TrustManagers());
insecureTlsParam.setDisableCNCheck(true);
soapClients.stream()
.map(ClientProxy::getClient)
.map(Client::getConduit)
.map(HTTPConduit.class::cast)
.forEach(c -> c.setTlsClientParameters(insecureTlsParam));
}
}
Shout out to #addiene, #jontro & #Miklos Krivan who provided all the pieces! Thank u very much!

Categories

Resources