Permalink
Browse files

pass-through authentication

  • Loading branch information...
1 parent daf007b commit 60ff6354cca36d84963d76c88bd411f375e475e5 @jalpedersen committed Feb 20, 2012
@@ -0,0 +1,79 @@
+package com.github.rnewson.couchdb.lucene;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import org.apache.http.Header;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+
+public class AuthenticatingHttpClient implements HttpClient {
+ private final HttpClient delegate;
+ private final Collection<Header> headers;
+
+ public AuthenticatingHttpClient(HttpClient delegate, Collection<Header> headers) {
+ this.delegate = delegate;
+ this.headers = headers;
+ }
+
+ public HttpParams getParams() {
+ return delegate.getParams();
+ }
+
+ public ClientConnectionManager getConnectionManager() {
+ return delegate.getConnectionManager();
+ }
+
+ public HttpResponse execute(HttpUriRequest request) throws IOException, ClientProtocolException {
+ return delegate.execute(addHeaders(request));
+ }
+
+ public HttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException,
+ ClientProtocolException {
+ return delegate.execute(addHeaders(request), context);
+ }
+
+ public HttpResponse execute(HttpHost target, HttpRequest request) throws IOException, ClientProtocolException {
+ return delegate.execute(target, addHeaders(request));
+ }
+
+ public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException,
+ ClientProtocolException {
+ return delegate.execute(target, addHeaders(request), context);
+ }
+
+ public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler) throws IOException,
+ ClientProtocolException {
+ return delegate.execute(addHeaders(request), responseHandler);
+ }
+
+ public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
+ throws IOException, ClientProtocolException {
+ return delegate.execute(addHeaders(request), responseHandler, context);
+ }
+
+ public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler)
+ throws IOException, ClientProtocolException {
+ return delegate.execute(target, addHeaders(request), responseHandler);
+ }
+
+ public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler,
+ HttpContext context) throws IOException, ClientProtocolException {
+ return delegate.execute(target, addHeaders(request), responseHandler, context);
+ }
+
+ public <T extends HttpRequest> T addHeaders(T request) {
+ for (Header h: headers) {
+ request.addHeader(h);
+ }
+ return request;
+ }
+}
@@ -19,10 +19,16 @@
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Collection;
+import java.util.Enumeration;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
+import javax.servlet.http.HttpServletRequest;
+
import org.apache.commons.configuration.HierarchicalINIConfiguration;
+import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
@@ -49,6 +55,7 @@
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
+import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
@@ -129,49 +136,85 @@ public void shutdown() {
}
- private static DefaultHttpClient instance;
+ private static HttpClient instance;
+ private static HttpClient unauthenticatedClient;
private static HierarchicalINIConfiguration INI;
+ /**
+ * Returns a client where each request is responsible for authentication
+ *
+ * @return
+ * @throws MalformedURLException
+ */
+ public static synchronized HttpClient getAuthenticatingInstance(HttpServletRequest request) throws MalformedURLException {
+ if (unauthenticatedClient == null) {
+ unauthenticatedClient = createInstance(false);
+ }
+ final Collection<Header> headers = new LinkedList<Header>();
+ @SuppressWarnings("unchecked")
+ final Enumeration<String> headerEnum = request.getHeaderNames();
+ while (headerEnum.hasMoreElements()) {
+ final String name = headerEnum.nextElement();
+ @SuppressWarnings("unchecked")
+ final Enumeration<String> values = request.getHeaders(name);
+ while (values.hasMoreElements()) {
+ headers.add(new BasicHeader(name, values.nextElement()));
+ }
+ }
+ return new AuthenticatingHttpClient(unauthenticatedClient, headers);
+ }
+
+ /**
+ * Returns a client where the credentials in the configuration file are used for authentication
+ *
+ * @return
+ * @throws MalformedURLException
+ */
public static synchronized HttpClient getInstance() throws MalformedURLException {
if (instance == null) {
- final HttpParams params = new BasicHttpParams();
- // protocol params.
- HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
- HttpProtocolParams.setUseExpectContinue(params, false);
- // connection params.
- HttpConnectionParams.setTcpNoDelay(params, true);
- HttpConnectionParams.setStaleCheckingEnabled(params, false);
- ConnManagerParams.setMaxTotalConnections(params, 1000);
- ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(1000));
-
- final SchemeRegistry schemeRegistry = new SchemeRegistry();
- schemeRegistry
- .register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 5984));
- schemeRegistry
- .register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
- final ClientConnectionManager cm = new ShieldedClientConnManager(
- new ThreadSafeClientConnManager(params, schemeRegistry));
-
- instance = new DefaultHttpClient(cm, params);
-
- if (INI != null) {
- final CredentialsProvider credsProvider = new BasicCredentialsProvider();
- final Iterator<?> it = INI.getKeys();
- while (it.hasNext()) {
- final String key = (String) it.next();
- if (!key.startsWith("lucene.") && key.endsWith(".url")) {
- final URL url = new URL(INI.getString(key));
- if (url.getUserInfo() != null) {
- credsProvider.setCredentials(
- new AuthScope(url.getHost(), url.getPort()),
- new UsernamePasswordCredentials(url.getUserInfo()));
- }
+ instance = createInstance(true);
+ }
+ return instance;
+ }
+
+ private static HttpClient createInstance(boolean authenticate) throws MalformedURLException {
+ final HttpParams params = new BasicHttpParams();
+ // protocol params.
+ HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
+ HttpProtocolParams.setUseExpectContinue(params, false);
+ // connection params.
+ HttpConnectionParams.setTcpNoDelay(params, true);
+ HttpConnectionParams.setStaleCheckingEnabled(params, false);
+ ConnManagerParams.setMaxTotalConnections(params, 1000);
+ ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(1000));
+
+ final SchemeRegistry schemeRegistry = new SchemeRegistry();
+ schemeRegistry
+ .register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 5984));
+ schemeRegistry
+ .register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
+ final ClientConnectionManager cm = new ShieldedClientConnManager(
+ new ThreadSafeClientConnManager(params, schemeRegistry));
+
+ final DefaultHttpClient instance = new DefaultHttpClient(cm, params);
+
+ if (INI != null) {
+ final CredentialsProvider credsProvider = new BasicCredentialsProvider();
+ final Iterator<?> it = INI.getKeys();
+ while (it.hasNext()) {
+ final String key = (String) it.next();
+ if (!key.startsWith("lucene.") && key.endsWith(".url")) {
+ final URL url = new URL(INI.getString(key));
+ if (authenticate && url.getUserInfo() != null) {
+ credsProvider.setCredentials(
+ new AuthScope(url.getHost(), url.getPort()),
+ new UsernamePasswordCredentials(url.getUserInfo()));
}
}
- instance.setCredentialsProvider(credsProvider);
- instance.addRequestInterceptor(new PreemptiveAuthenticationRequestInterceptor(), 0);
}
+ instance.setCredentialsProvider(credsProvider);
+ instance.addRequestInterceptor(new PreemptiveAuthenticationRequestInterceptor(), 0);
}
return instance;
}
@@ -36,6 +36,7 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.HttpClient;
+import org.apache.http.client.HttpResponseException;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
@@ -121,7 +122,7 @@ private void cleanup(final HttpServletRequest req,
ServletUtils.sendJsonSuccess(req, resp);
}
- private Couch getCouch(final HttpServletRequest req) throws IOException {
+ private Couch getCouch(final HttpServletRequest req, HttpClient client) throws IOException {
final String sectionName = new PathParts(req).getKey();
final Configuration section = ini.getSection(sectionName);
if (!section.containsKey("url")) {
@@ -130,6 +131,14 @@ private Couch getCouch(final HttpServletRequest req) throws IOException {
return new Couch(client, section.getString("url"));
}
+ private Couch getAuthenticatingCouch(final HttpServletRequest req) throws IOException {
+ return getCouch(req, HttpClientFactory.getAuthenticatingInstance(req));
+ }
+
+ private Couch getCouch(final HttpServletRequest req) throws IOException {
+ return getCouch(req, client);
+ }
+
private synchronized DatabaseIndexer getIndexer(final Database database)
throws IOException, JSONException {
DatabaseIndexer result = indexers.get(database);
@@ -186,6 +195,9 @@ private void doGetInternal(final HttpServletRequest req, final HttpServletRespon
handleWelcomeReq(req, resp);
return;
case 5:
+ if ( ! validateDatabaseRequest(req, resp)) {
+ return;
+ }
final DatabaseIndexer indexer = getIndexer(req);
if (indexer == null) {
ServletUtils.sendJsonError(req, resp, 500, "error_creating_index");
@@ -228,7 +240,19 @@ private void doPostInternal(final HttpServletRequest req, final HttpServletRespo
indexer.admin(req, resp);
return;
}
- ServletUtils.sendJsonError(req, resp, 400, "bad_request");
+ ServletUtils.sendJsonError(req, resp, 400, "bad_request");
+ }
+
+ private boolean validateDatabaseRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException, JSONException {
+ final Couch couch = getAuthenticatingCouch(req);
+ final Database db = couch.getDatabase(new PathParts(req).getDatabaseName());
+ try {
+ db.getInfo(); //This will throw an HttpResponseException if not authenticated
+ return true;
+ } catch (HttpResponseException e) {
+ ServletUtils.sendJsonError(req, resp, e.getStatusCode(), new JSONObject(e.getMessage()));
+ }
+ return false;
}
}

0 comments on commit 60ff635

Please sign in to comment.