From a43191e20a21e333da487c5b3004c2418289d97b Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 9 Aug 2017 17:32:27 +0200 Subject: [client] Update apache httpclient, pass custom client to ecp-client-lean --- dozentenmodul/pom.xml | 13 ++- .../dozmod/authentication/ShibbolethEcp.java | 23 ++-- .../org/openslx/dozmod/util/ProxyConfigurator.java | 129 +++++++++++++++++++-- 3 files changed, 144 insertions(+), 21 deletions(-) diff --git a/dozentenmodul/pom.xml b/dozentenmodul/pom.xml index 67e6ed34..e744dd48 100644 --- a/dozentenmodul/pom.xml +++ b/dozentenmodul/pom.xml @@ -178,7 +178,7 @@ org.openslx.ecp ecp-client-lean - 0.0.2-SNAPSHOT + 0.0.3-SNAPSHOT joda-time @@ -190,6 +190,17 @@ jdatepicker 1.3.4 + + org.openslx + proxy_vole + 0.0.4-SNAPSHOT + compile + + + org.apache.httpcomponents + httpclient + [4.5.3,4.5.99] + diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/authentication/ShibbolethEcp.java b/dozentenmodul/src/main/java/org/openslx/dozmod/authentication/ShibbolethEcp.java index 6a594e6a..ce8bbe95 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/authentication/ShibbolethEcp.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/authentication/ShibbolethEcp.java @@ -9,11 +9,11 @@ import java.net.URL; import org.apache.http.HttpResponse; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.methods.HttpGet; import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; import org.openslx.bwlp.thrift.iface.AuthorizationError; import org.openslx.bwlp.thrift.iface.TAuthorizationException; +import org.openslx.dozmod.util.ProxyConfigurator; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -130,21 +130,26 @@ public class ShibbolethEcp { } // now init the authenticator for that idp and our static sp - final ECPAuthenticator auth = new ECPAuthenticator(user, pass, new URI(idpUrl), BWLP_SP); + final ECPAuthenticator auth = new ECPAuthenticator(ProxyConfigurator.getClient(), user, pass, new URI(idpUrl), BWLP_SP); + HttpResponse spResponse; try { - auth.authenticate(); + spResponse = auth.authenticate(); } catch (ECPAuthenticationException e) { LOGGER.error("ECP Authentication Exception, see trace: ", e); throw new TAuthorizationException(AuthorizationError.GENERIC_ERROR, e.getMessage()); } - // here test again for the SP's URL - final HttpGet testSp = new HttpGet(BWLP_SP); - final HttpResponse response = auth.getHttpClient().execute(testSp); - LOGGER.debug("SP request returned: " + response.getStatusLine()); - final String responseBody = EntityUtils.toString(response.getEntity()); + if (spResponse.getStatusLine().getStatusCode() != 200) { + LOGGER.error("SP does not return HTTP status code 200"); + throw new TAuthorizationException(AuthorizationError.GENERIC_ERROR, "SP says: " + + spResponse.getStatusLine().toString()); + } + + LOGGER.debug("Login complete, getting body"); + final String responseBody = EntityUtils.toString(spResponse.getEntity()); + try { lastResponse = GSON.fromJson(responseBody, ServiceProviderResponse.class); } catch (JsonSyntaxException e) { @@ -152,7 +157,7 @@ public class ShibbolethEcp { LOGGER.warn("Response was:\n" + responseBody); throw e; } - + // TODO: here we will need to parse the answer accordingly. // no errors, meaning everything worked fine. if (lastResponse.status.equals("unregistered")) { diff --git a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java index fdfe733d..d3bd27ad 100644 --- a/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java +++ b/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java @@ -1,12 +1,31 @@ package org.openslx.dozmod.util; +import java.io.IOException; +import java.net.Proxy; import java.net.ProxySelector; +import java.net.Socket; import java.text.MessageFormat; +import java.util.concurrent.atomic.AtomicReference; +import org.apache.http.HttpException; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; +import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpParams; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.config.SocketConfig; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +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.conn.PoolingHttpClientConnectionManager; +import org.apache.http.impl.conn.SystemDefaultRoutePlanner; +import org.apache.http.protocol.HttpContext; +import org.apache.http.ssl.SSLContexts; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.Priority; @@ -27,7 +46,6 @@ import com.btr.proxy.util.Logger.LogLevel; * @author Jonathan Bauer */ -@SuppressWarnings("deprecation") public class ProxyConfigurator { /** @@ -35,6 +53,8 @@ public class ProxyConfigurator { */ private final static Logger LOGGER = Logger.getLogger(ProxyConfigurator.class); + private static AtomicReference apacheClient = new AtomicReference<>(); + /** * Initialization method. */ @@ -58,6 +78,14 @@ public class ProxyConfigurator { LOGGER.info("Not setting up proxy because master server seems reachable."); return; } + + // Build special HTTP Client Builder for apache and try again + apacheClient.set(createSlxBuilder().build()); + if (masterClient != null && testHttpsMaster()) { + LOGGER.info("Not setting up proxy since master server is reachable with custom client builder"); + return; + } + // first setup the logger of proxy_vole com.btr.proxy.util.Logger.setBackend(new LogBackEnd() { @@ -105,18 +133,69 @@ public class ProxyConfigurator { } } + /** + * Get the HttpClient to be used with apache + * httpclient. + * + * @return client + */ + public static CloseableHttpClient getClient() { + CloseableHttpClient inst = apacheClient.get(); + if (inst != null) + return inst; + inst = createShortTimeoutBuilder().build(); + apacheClient.compareAndSet(null, inst); + return inst; + } + + private static SSLConnectionSocketFactory createSslFactory() { + // TODO: Geht nich + for (String proto : new String[] { "TLSv1.2", "TLSv1.1", "TLS" }) { + try { + return new SSLConnectionSocketFactory(SSLContexts.custom().useProtocol(proto).build()); + } catch (Exception e) { + LOGGER.warn(proto + " not available", e); + } + } + return SSLConnectionSocketFactory.getSystemSocketFactory(); + } + + private static HttpClientBuilder createShortTimeoutBuilder() { + HttpClientBuilder builder = HttpClientBuilder.create().setSSLSocketFactory(createSslFactory()); + builder.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(8000).build()); + PoolingHttpClientConnectionManager pm = new PoolingHttpClientConnectionManager(); + pm.setDefaultMaxPerRoute(4); + builder.setConnectionManager(pm); + return builder; + } + + private static HttpClientBuilder createSlxBuilder() { + HttpClientBuilder builder = HttpClientBuilder.create(); + builder.setRoutePlanner(new SlxRoutePlanner(null)); + builder.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(8000).build()); + Registry csf = RegistryBuilder. create() + .register("http", new SlxSocketFactory()) + .register("https", createSslFactory()) + .build(); + PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(csf); + cm.setDefaultMaxPerRoute(4); + builder.setConnectionManager(cm); + return builder; + } + private static boolean testHttpsMaster() { - DefaultHttpClient client = new DefaultHttpClient(); - HttpParams params = client.getParams(); - params.setParameter("http.socket.timeout", 3000); - params.setParameter("http.connection.timeout", 3000); - params.setParameter("http.connection-manager.timeout", new Long(3000)); - params.setParameter("http.protocol.head-body-timeout", 3000); + RequestConfig requestConfig = RequestConfig.custom() + .setConnectionRequestTimeout(3000) + .setConnectTimeout(3000) + .setSocketTimeout(3000) + .build(); HttpGet httpGet = new HttpGet(ShibbolethEcp.BWLP_SP.toString()); + httpGet.setConfig(requestConfig); httpGet.setHeader("Accept", "text/html, application/vnd.paos+xml"); - httpGet.setHeader("PAOS", "ver=\"urn:liberty:paos:2003-08\";\"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp\""); + httpGet.setHeader("PAOS", + "ver=\"urn:liberty:paos:2003-08\";\"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp\""); try { - HttpResponse response = client.execute(httpGet); + HttpResponse response = getClient().execute(httpGet); LOGGER.debug("Master server replies with " + response.getStatusLine().getStatusCode()); return response.getStatusLine().getStatusCode() == 200; } catch (Exception e) { @@ -124,5 +203,33 @@ public class ProxyConfigurator { return false; } } + + private static class SlxSocketFactory extends PlainConnectionSocketFactory { + @Override + public Socket createSocket(HttpContext context) throws IOException { + Object obj = context.getAttribute("openslx.l7proxy"); + if (obj instanceof HttpRoute) { + HttpRoute route = (HttpRoute) obj; + if (route != null && route.getProxyHost() != null) { + return new Socket(Proxy.NO_PROXY); + } + } + return new Socket(); + } + } + + private static class SlxRoutePlanner extends SystemDefaultRoutePlanner { + public SlxRoutePlanner(ProxySelector proxySelector) { + super(proxySelector); + } + + @Override + public HttpRoute determineRoute(HttpHost host, HttpRequest request, HttpContext context) + throws HttpException { + HttpRoute route = super.determineRoute(host, request, context); + context.setAttribute("openslx.l7proxy", route); + return route; + } + } } -- cgit v1.2.3-55-g7522