From e19d3485c7ea0eb1cd877d52009e6efc932ce246 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 11 Apr 2019 09:44:41 +0200 Subject: add some utils and new exceptions --- .../eaaf/core/exceptions/EAAFServiceException.java | 30 +++++ .../exceptions/ProtocolResponseExceptions.java | 14 +++ .../eaaf/core/impl/utils/HttpClientFactory.java | 121 +++++++++++++++++++++ .../at/gv/egiz/eaaf/core/impl/utils/X509Utils.java | 62 +++++++++++ 4 files changed, 227 insertions(+) create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/exceptions/EAAFServiceException.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/exceptions/ProtocolResponseExceptions.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java create mode 100644 eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/exceptions/EAAFServiceException.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/exceptions/EAAFServiceException.java new file mode 100644 index 00000000..309834a2 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/exceptions/EAAFServiceException.java @@ -0,0 +1,30 @@ +package at.gv.egiz.eaaf.core.exceptions; + +import org.springframework.lang.NonNull; + +public abstract class EAAFServiceException extends EAAFException { + + private static final long serialVersionUID = -867758153828290337L; + + public EAAFServiceException(String errorId, Object[] params) { + super(errorId, params); + + } + + public EAAFServiceException(String errorId, Object[] params, Throwable e) { + super(errorId, params, e); + + } + + /** + * Get a textual identifier of the service that throws this exception + * + * @return + */ + @NonNull + protected abstract String getServiceIdentifier(); + + + + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/exceptions/ProtocolResponseExceptions.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/exceptions/ProtocolResponseExceptions.java new file mode 100644 index 00000000..194505d3 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/exceptions/ProtocolResponseExceptions.java @@ -0,0 +1,14 @@ +package at.gv.egiz.eaaf.core.exceptions; + +public class ProtocolResponseExceptions extends EAAFProtocolException { + + private static final long serialVersionUID = -7866198705324084601L; + + public ProtocolResponseExceptions(String internalMsgId, Object[] params) { + super(internalMsgId, params); + } + + public ProtocolResponseExceptions(String internalMsgId, Object[] params, Throwable e) { + super(internalMsgId, params, e); + } +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java new file mode 100644 index 00000000..6f6f9f49 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/HttpClientFactory.java @@ -0,0 +1,121 @@ +package at.gv.egiz.eaaf.core.impl.utils; + +import java.security.NoSuchAlgorithmException; + +import javax.annotation.PostConstruct; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; + +@Service +public class HttpClientFactory { + private static final Logger log = LoggerFactory.getLogger(HttpClientFactory.class); + @Autowired(required=true) private IConfiguration basicConfig; + + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE = "client.http.connection.pool.use"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "client.http.connection.pool.maxtotal"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "client.http.connection.pool.maxperroute"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "client.http.connection.timeout.socket"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "client.http.connection.timeout.connection"; + public static final String PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "client.http.connection.timeout.request"; + public static final String PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL = "client.http.ssl.hostnameverifier.trustall"; + + // default configuration values + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET = "300"; + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION = "300"; + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST = "1500"; + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL = "500"; + public static final String DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE = "100"; + + private HttpClientBuilder httpClientBuilder = null; + + /** + * Return an instance of a Apache HTTP client + * + * @return + */ + public CloseableHttpClient getHttpClient() { + return httpClientBuilder.build(); + + } + + + @PostConstruct + private void initalize() { + //initialize http client + log.trace("Initializing HTTP Client-builder ... "); + HttpClientBuilder httpClientBuilder = HttpClients.custom(); + + //set default request configuration + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_CONNECTION)) * 1000) + .setConnectionRequestTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_REQUEST)) * 1000) + .setSocketTimeout(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_TIMEOUT_SOCKET)) * 1000) + .build(); + httpClientBuilder.setDefaultRequestConfig(requestConfig); + + //set pool connection if requested + if (basicConfig.getBasicMOAIDConfigurationBoolean( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_USE, + true)) { + PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager(); + pool.setDefaultMaxPerRoute(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXPERROUTE))); + pool.setMaxTotal(Integer.valueOf(basicConfig.getBasicConfiguration( + PROP_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL, + DEFAULT_CONFIG_CLIENT_HTTP_CONNECTION_POOL_MAXTOTAL))); + + + + httpClientBuilder.setConnectionManager(pool); + log.debug("Initalize http-client pool with, maxTotal: {} maxPerRoute: {}", pool.getMaxTotal(), pool.getDefaultMaxPerRoute()); + + } + + try { + log.trace("Initializing SSL Context ... "); + SSLContext sslContext = SSLContext.getDefault(); + HostnameVerifier hostnameVerifier = null; + if (basicConfig.getBasicMOAIDConfigurationBoolean( + PROP_CONFIG_CLIENT_HTTP_SSL_HOSTNAMEVERIFIER_TRUSTALL, + false)) { + hostnameVerifier = new NoopHostnameVerifier(); + log.warn("HTTP client-builder deactivates SSL Host-name verification!"); + } + + LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext , hostnameVerifier); + httpClientBuilder.setSSLSocketFactory(sslSocketFactory ); + + } catch (NoSuchAlgorithmException e) { + log.warn("HTTP client-builder can NOT initialze SSL-Context", e); + + } + + + log.info("HTTP client-builder successfuly initialized"); + + } + + +} diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java new file mode 100644 index 00000000..b3fb42c4 --- /dev/null +++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/X509Utils.java @@ -0,0 +1,62 @@ +package at.gv.egiz.eaaf.core.impl.utils; + +import java.security.cert.X509Certificate; +import java.util.List; + +import javax.security.auth.x500.X500Principal; + +public class X509Utils { + + /** + * Sorts the Certificate Chain by IssuerDN and SubjectDN. The [0]-Element should be the Hostname, + * the last Element should be the Root Certificate. + * + * @param certs + * The first element must be the correct one. + * @return sorted Certificate Chain + */ + public static List sortCertificates( + List certs) + { + int length = certs.size(); + if (certs.size() <= 1) + { + return certs; + } + + for (X509Certificate cert : certs) + { + if (cert == null) + { + throw new NullPointerException(); + } + } + + for (int i = 0; i < length; i++) + { + boolean found = false; + X500Principal issuer = certs.get(i).getIssuerX500Principal(); + for (int j = i + 1; j < length; j++) + { + X500Principal subject = certs.get(j).getSubjectX500Principal(); + if (issuer.equals(subject)) + { + // sorting necessary? + if (i + 1 != j) + { + X509Certificate tmp = certs.get(i + 1); + certs.set(i + 1, certs.get(j)); + certs.set(j, tmp); + } + found = true; + } + } + if (!found) + { + break; + } + } + + return certs; + } +} -- cgit v1.2.3