Java tutorial
/* ======================================================================== * Copyright (c) 2015 The University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ======================================================================== */ package edu.washington.shibboleth.attribute.resolver.dc.rws; import java.lang.IllegalArgumentException; import java.lang.ThreadLocal; import java.io.File; import java.util.List; import java.io.FileInputStream; import java.io.IOException; import java.util.Date; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.net.URL; import java.net.MalformedURLException; import javax.net.ssl.SSLContext; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import java.security.cert.CertificateFactory; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Key; import java.security.KeyStoreException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import javax.net.ssl.HostnameVerifier; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.params.BasicHttpParams; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.auth.Credentials; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.auth.AuthScope; import org.apache.http.auth.AuthState; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * <code>HttpDataSource</code> provides a webservice data source. */ public class HttpDataSource { /** Class logger. */ private static Logger log = LoggerFactory.getLogger(HttpDataSource.class); private SSLConnectionSocketFactory socketFactory; /** Username if basic auth */ private String username = null; /** Password if basic auth */ private String password = null; /** Cred provider if basic auth */ private CredentialsProvider credsProvider; /** Time, in milliseconds, to wait for a search to return. */ private int searchTimeLimit; /** Accept header. */ private String acceptHeader = null; /** Connection manager */ private PoolingHttpClientConnectionManager connectionManager; /** Http client **/ private CloseableHttpClient httpClient; /** max connections */ private int maxConnections = 10; private String caCertificateFile; private String certificateFile; private String keyFile; /** authn type **/ private boolean isBasicAuthn = false; private boolean isCertAuthn = false; /** /** * Constructor */ public HttpDataSource() { } /** * Initializes the connector and prepares it for use. */ public void initialize() throws IOException { log.info("HttpDataSource: initialize"); SSLConnectionSocketFactory sf = getSocketFactory(); Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("https", sf).build(); connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); connectionManager.setMaxTotal(maxConnections); connectionManager.setDefaultMaxPerRoute(maxConnections); /* * Create our client */ // HttpClientBuilder cb = HttpClients.custom().setConnectionManager(connectionManager); HttpClientBuilder cb = HttpClientBuilder.create().setConnectionManager(connectionManager); // requires lib 4.x // cb = cb.setConnectionManagerShared(true); if (username != null && password != null) { CredentialsProvider credsProvider = new BasicCredentialsProvider(); UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials(username, password); credsProvider.setCredentials(AuthScope.ANY, usernamePasswordCredentials); cb = cb.setDefaultCredentialsProvider(credsProvider); log.info("HttpDataSource: added basic creds "); } httpClient = cb.build(); } /** * Each thread gets a context */ private static final ThreadLocal<HttpClientContext> clientContext = new ThreadLocal<HttpClientContext>() { @Override protected HttpClientContext initialValue() { return new HttpClientContext(); } }; /** * Retrieve a resource */ public String getResource(String url) { String content = null; log.info("rws get: " + url); HttpGet httpget = new HttpGet(url); // parameterize this ( by this request? ) log.info(acceptHeader); if (acceptHeader != null) httpget.setHeader("Accept", acceptHeader); try { CloseableHttpResponse response = httpClient.execute(httpget, clientContext.get()); try { int sc = response.getStatusLine().getStatusCode(); log.info("status: " + sc); HttpEntity entity = response.getEntity(); if (entity != null) { content = EntityUtils.toString(entity); log.trace("content dump:"); log.trace(content); } } finally { response.close(); } } catch (Exception e) { log.error("rws get error: " + e); } return content; } /** * Generate a socket factory using supplied key and trust stores */ protected SSLConnectionSocketFactory getSocketFactory() throws IOException { TrustManager[] trustManagers = null; KeyManager[] keyManagers = null; try { /* trust managers */ if (caCertificateFile != null) { KeyStore trustStore; int cn = 0; log.info("Setting x509 trust from " + caCertificateFile); TrustManagerFactory tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); CertificateFactory cf = CertificateFactory.getInstance("X.509"); FileInputStream in = new FileInputStream(caCertificateFile); Collection certs = cf.generateCertificates(in); trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); Iterator cit = certs.iterator(); while (cit.hasNext()) { X509Certificate cert = (X509Certificate) cit.next(); log.info(" adding " + cert.getSubjectX500Principal().toString()); System.out.println(" adding " + cert.getSubjectX500Principal().toString()); trustStore.setCertificateEntry("CACERT" + cn, cert); cn += 1; } tmf.init(trustStore); trustManagers = tmf.getTrustManagers(); } else { // no verification trustManagers = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { return; } public void checkServerTrusted(X509Certificate[] certs, String authType) { return; } } }; } /* key manager */ if (certificateFile != null && keyFile != null) { KeyStore keyStore; KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null, null); FileInputStream in = new FileInputStream(certificateFile); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate cert = (X509Certificate) cf.generateCertificate(in); PKCS1 pkcs = new PKCS1(); log.info("reading key file: " + keyFile); PrivateKey key = pkcs.readKey(keyFile); X509Certificate[] chain = new X509Certificate[1]; chain[0] = cert; keyStore.setKeyEntry("CERT", (Key) key, "pw".toCharArray(), chain); kmf.init(keyStore, "pw".toCharArray()); keyManagers = kmf.getKeyManagers(); } /* socket factory */ SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(keyManagers, trustManagers, null); return new SSLConnectionSocketFactory(ctx); } catch (IOException e) { log.error("error reading cert or key error: " + e); } catch (KeyStoreException e) { log.error("keystore error: " + e); } catch (NoSuchAlgorithmException e) { log.error("sf error: " + e); } catch (KeyManagementException e) { log.error("sf error: " + e); } catch (CertificateException e) { log.error("sf error: " + e); } catch (UnrecoverableKeyException e) { log.error("sf error: " + e); } return null; } /** Bean property setters */ /** * This sets the certificate key for x509 authn * * @param i <code>String</code> certificate key file */ public void setKeyFile(String v) { keyFile = v; } /** * This sets the certificate for x509 authn * * @param i <code>String</code> certificate file */ public void setCertificateFile(String v) { certificateFile = v; } /** * This sets the CA certificate file * * @param i <code>String</code> CA certificate file */ public void setCaCertificateFile(String v) { caCertificateFile = v; } /** * This sets the time in milliseconds that the ldap will wait for search results. A value of 0 means to wait * indefinitely. This method will remove any cached results. * * @param i <code>int</code> milliseconds */ public void setSearchTimeLimit(int i) { searchTimeLimit = i; } /** * This sets the maximum connections for the pool * * @param i <code>int</code> max connections */ public void setMaxConnections(int i) { maxConnections = i; } /** * This sets the accept header * * @param s <code>String</code> acceptHeader */ public void setAcceptHeader(String v) { acceptHeader = v; } /** * This sets the basic auth username * * @param s <code>String</code> username */ public void setUsername(String u) { username = u; } /** * This sets the basic auth password * * @param s <code>String</code> password */ public void setPassword(String p) { password = p; } public synchronized void close() { } private void clearCache() { } }