Java tutorial
/* * Copyright 2002-2011 the original author or authors, or Red-Black IT Ltd, as appropriate. * * 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 com.redblackit.web.client; import java.io.FileInputStream; import java.io.InputStream; import java.security.KeyStore; import org.apache.http.client.HttpClient; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.params.HttpParams; import org.apache.log4j.Logger; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.ResourceUtils; /** * Factory creating an HttpClient for use with x.509, using configured key and * trust store information. * * @author djnorth */ public class X509HttpClientFactoryBean implements FactoryBean<HttpClient>, InitializingBean { /** * Default read timeout, used if no HttpParams are provided. */ private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000); /** * Logger */ private Logger logger = Logger.getLogger("web.client"); /** * KeyStore */ private String keyStore = System.getProperty("javax.net.ssl.keyStore"); /** * KeyStore type */ private String keyStoreType = "jks"; /** * KeyStore password */ private String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword", "changeit"); /** * TrustStore for client */ private String trustStore = System.getProperty("javax.net.ssl.trustStore"); /** * TrustStore type */ private String trustStoreType = "jks"; /** * TrustStore password */ private String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword", "changeit"); /** * https port */ private int httpsPort = 8443; /** * Optional HttpParams */ private HttpParams httpParams = null; /** * HttpClient object */ private HttpClient httpClient = null; /** * Set keyStore filename (default system property javax.net.ssl.keyStore) * * @param keyStore * the keyStore to set */ public void setKeyStore(String keyStore) { this.keyStore = keyStore; } /** * @return the keyStore */ public String getKeyStore() { return keyStore; } /** * Set the keyStore type (default "jks") * * @param keyStoreType * the keyStoreType to set */ public void setKeyStoreType(String keyStoreType) { this.keyStoreType = keyStoreType; } /** * @return the keyStoreType */ public String getKeyStoreType() { return keyStoreType; } /** * Set keyStorePassword (default system property * javax.net.ssl.keyStorePassword, or changeit) N.B. This must equal the * (private) key password * * @param keyStorePassword * the keyStorePassword to set */ public void setKeyStorePassword(String keyStorePassword) { this.keyStorePassword = keyStorePassword; } /** * @return the keyStorePassword */ public String getKeyStorePassword() { return keyStorePassword; } /** * Set trustStore filename (default system property * javax.net.ssl.trustStore) * * @param trustStore * the trustStore to set */ public void setTrustStore(String trustStore) { this.trustStore = trustStore; } /** * @return the trustStore */ public String getTrustStore() { return trustStore; } /** * Set the trustStore type (default "jks") * * @param trustStoreType * the trustStoreType to set */ public void setTrustStoreType(String trustStoreType) { this.trustStoreType = trustStoreType; } /** * @return the trustStoreType */ public String getTrustStoreType() { return trustStoreType; } /** * Set trustStorePassword (default system property * javax.net.ssl.trustStorePassword, or changeit) * * @param trustStorePassword * the trustStorePassword to set */ public void setTrustStorePassword(String trustStorePassword) { this.trustStorePassword = trustStorePassword; } /** * @return the trustStorePassword */ public String getTrustStorePassword() { return trustStorePassword; } /** * Set the https port (default 8443) * * @param httpsPort * the httpsPort to set */ public void setHttpsPort(int httpsPort) { this.httpsPort = httpsPort; } /** * @return the hppsPort */ public int getHttpsPort() { return httpsPort; } /** * Set HttpParams to use. Default is a BasicHttpParams instance with a read * timeout value set to DEFAULT_READ_TIMEOUT_MILLISECONDS. * * @param httpParams * the httpParams to set */ public void setHttpParams(HttpParams httpParams) { this.httpParams = httpParams; } /** * @return the httpParams */ public HttpParams getHttpParams() { return httpParams; } /** * Ensure we have keystores and passwords defined. * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ @Override public void afterPropertiesSet() throws Exception { if (getKeyStore() == null || getKeyStore().length() == 0 || getKeyStoreType() == null || getKeyStoreType().length() == 0 || getKeyStorePassword() == null || getKeyStorePassword().length() == 0 || getTrustStore() == null || getTrustStore().length() == 0 || getTrustStoreType() == null || getTrustStoreType().length() == 0 || getTrustStorePassword() == null || getTrustStorePassword().length() == 0) { throw new IllegalArgumentException("Missing key/trust store info:" + this); } if (logger.isDebugEnabled()) { logger.debug("afterPropertiesSet:E:this=" + this); } try { final KeyStore keystore = KeyStore.getInstance(getKeyStoreType()); InputStream keystoreInput = new FileInputStream(ResourceUtils.getFile(getKeyStore())); keystore.load(keystoreInput, getKeyStorePassword().toCharArray()); KeyStore truststore = KeyStore.getInstance(getTrustStoreType()); InputStream truststoreInput = new FileInputStream(ResourceUtils.getFile(getTrustStore())); truststore.load(truststoreInput, getTrustStorePassword().toCharArray()); final SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("https", getHttpsPort(), new SSLSocketFactory(keystore, getKeyStorePassword(), truststore))); if (httpParams == null) { httpParams = new BasicHttpParams(); httpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, DEFAULT_READ_TIMEOUT_MILLISECONDS); } httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(schemeRegistry), httpParams); if (logger.isDebugEnabled()) { logger.debug("afterPropertiesSet:R:this=" + this); } } catch (Throwable t) { throw new RuntimeException(this.toString(), t); } } /** * Return the httpClient created from the properties set * * @see org.springframework.beans.factory.FactoryBean#getObject() */ @Override public HttpClient getObject() { return httpClient; } /** * Return the interface type. This should be sufficient information to * support @Autowire * * @see org.springframework.beans.factory.FactoryBean#getObjectType() */ @Override public Class<?> getObjectType() { return HttpClient.class; } /** * We do cache our client * * @see org.springframework.beans.factory.FactoryBean#isSingleton() */ @Override public boolean isSingleton() { return true; } /** * toString */ public String toString() { StringBuffer tos = new StringBuffer(super.toString()); tos.append(":keyStore=").append(keyStore); tos.append(":keyStoreType=").append(keyStoreType); tos.append(":keyStorePassword=").append(keyStorePassword); tos.append(":trustStore=").append(trustStore); tos.append(":trustStoreType=").append(trustStoreType); tos.append(":trustStorePassword=").append(trustStorePassword); tos.append(":httpsPort=").append(httpsPort); tos.append(":httpClient=").append(httpClient); tos.append(":httpParams=").append(httpParams); return tos.toString(); } }