Skip to content
This repository has been archived by the owner on May 4, 2023. It is now read-only.

Commit

Permalink
add basic authentication for require_valid_user=true users.
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert Newson committed Jul 14, 2010
1 parent 4bda2d7 commit 378e322
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 61 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -562,3 +562,21 @@ If you recreate databases or frequently change your fulltext functions, you will
<pre> <pre>
curl -X POST http://localhost:5984/&lt;db>/_fti/_cleanup curl -X POST http://localhost:5984/&lt;db>/_fti/_cleanup
</pre> </pre>

<h1>Authentication</h1>

By default couchdb-lucene does not attempt to authenticate to CouchDB. If you have set CouchDB's require_valid_user to true, you will need to modify couchdb-lucene.ini. Change the url setting to include a valid username and password. e.g, the default setting is;

<pre>
[local]
url=http://localhost:5984/
</pre>

Change it to;

<pre>
[local]
url=http://foo:bar@localhost:5984/
</pre>

and couchdb-lucene will authenticate to couchdb.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -16,10 +16,25 @@
* limitations under the License. * limitations under the License.
*/ */


import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;


import org.apache.commons.configuration.HierarchicalINIConfiguration;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpVersion; import org.apache.http.HttpVersion;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.AuthState;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ClientConnectionRequest; import org.apache.http.conn.ClientConnectionRequest;
import org.apache.http.conn.ManagedClientConnection; import org.apache.http.conn.ManagedClientConnection;
Expand All @@ -29,12 +44,16 @@
import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams; import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams; import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams; import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;


/** /**
* HttpClient instances just the way we like them. * HttpClient instances just the way we like them.
Expand All @@ -44,6 +63,33 @@
*/ */
public final class HttpClientFactory { public final class HttpClientFactory {


private static final class PreemptiveAuthenticationRequestInterceptor
implements HttpRequestInterceptor {

public void process(final HttpRequest request, final HttpContext context)
throws HttpException, IOException {

final AuthState authState = (AuthState) context
.getAttribute(ClientContext.TARGET_AUTH_STATE);
final CredentialsProvider credsProvider = (CredentialsProvider) context
.getAttribute(ClientContext.CREDS_PROVIDER);
final HttpHost targetHost = (HttpHost) context
.getAttribute(ExecutionContext.HTTP_TARGET_HOST);

// If not auth scheme has been initialized yet
if (authState.getAuthScheme() == null) {
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
// Obtain credentials matching the target host
Credentials creds = credsProvider.getCredentials(authScope);
// If found, generate BasicScheme preemptively
if (creds != null) {
authState.setAuthScheme(new BasicScheme());
authState.setCredentials(creds);
}
}
}
}

private static class ShieldedClientConnManager implements ClientConnectionManager { private static class ShieldedClientConnManager implements ClientConnectionManager {


private final ClientConnectionManager delegate; private final ClientConnectionManager delegate;
Expand All @@ -64,7 +110,10 @@ public SchemeRegistry getSchemeRegistry() {
return delegate.getSchemeRegistry(); return delegate.getSchemeRegistry();
} }


public void releaseConnection(final ManagedClientConnection conn, final long validDuration, final TimeUnit timeUnit) { public void releaseConnection(
final ManagedClientConnection conn,
final long validDuration,
final TimeUnit timeUnit) {
delegate.releaseConnection(conn, validDuration, timeUnit); delegate.releaseConnection(conn, validDuration, timeUnit);
} }


Expand All @@ -73,15 +122,17 @@ public ClientConnectionRequest requestConnection(final HttpRoute route, final Ob
} }


public void shutdown() { public void shutdown() {
// SHIELDED. // SHIELDED.
// delegate.shutdown(); // delegate.shutdown();
} }


} }


private static HttpClient instance; private static DefaultHttpClient instance;

private static HierarchicalINIConfiguration INI;


public static synchronized HttpClient getInstance() { public static synchronized HttpClient getInstance() throws MalformedURLException {
if (instance == null) { if (instance == null) {
final HttpParams params = new BasicHttpParams(); final HttpParams params = new BasicHttpParams();
// protocol params. // protocol params.
Expand All @@ -94,13 +145,34 @@ public static synchronized HttpClient getInstance() {
ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(1000)); ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRouteBean(1000));


final SchemeRegistry schemeRegistry = new SchemeRegistry(); final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 5984)); schemeRegistry
.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 5984));
final ClientConnectionManager cm = new ShieldedClientConnManager( final ClientConnectionManager cm = new ShieldedClientConnManager(
new ThreadSafeClientConnManager(params, schemeRegistry)); new ThreadSafeClientConnManager(params, schemeRegistry));


instance = new DefaultHttpClient(cm, params); 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));
credsProvider.setCredentials(
new AuthScope(url.getHost(), url.getPort()),
new UsernamePasswordCredentials(url.getUserInfo()));
}
}
instance.setCredentialsProvider(credsProvider);
instance.addRequestInterceptor(new PreemptiveAuthenticationRequestInterceptor(), 0);
}
} }
return instance; return instance;
} }


public static void setIni(final HierarchicalINIConfiguration ini) {
INI = ini;
}

} }
111 changes: 56 additions & 55 deletions src/main/java/com/github/rnewson/couchdb/lucene/Main.java
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@


import org.apache.commons.configuration.HierarchicalINIConfiguration; import org.apache.commons.configuration.HierarchicalINIConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.http.client.HttpClient;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mortbay.jetty.Connector; import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler; import org.mortbay.jetty.Handler;
Expand All @@ -32,60 +33,60 @@


public class Main { public class Main {


private static final Logger LOG = Logger.getLogger(Main.class); private static final Logger LOG = Logger.getLogger(Main.class);


/** /**
* Run couchdb-lucene. * Run couchdb-lucene.
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
final HierarchicalINIConfiguration configuration = new HierarchicalINIConfiguration( final HierarchicalINIConfiguration configuration = new HierarchicalINIConfiguration(
Main.class.getClassLoader().getResource("couchdb-lucene.ini")); Main.class.getClassLoader().getResource("couchdb-lucene.ini"));
configuration.setReloadingStrategy(new FileChangedReloadingStrategy()); configuration.setReloadingStrategy(new FileChangedReloadingStrategy());


final File dir = new File(configuration.getString("lucene.dir", final File dir = new File(configuration.getString("lucene.dir", "indexes"));
"indexes"));

if (dir == null) {
if (dir == null) { LOG.error("lucene.dir not set.");
LOG.error("lucene.dir not set."); System.exit(1);
System.exit(1); }
} if (!dir.exists() && !dir.mkdir()) {
if (!dir.exists() && !dir.mkdir()) { LOG.error("Could not create " + dir.getCanonicalPath());
LOG.error("Could not create " + dir.getCanonicalPath()); System.exit(1);
System.exit(1); }
} if (!dir.canRead()) {
if (!dir.canRead()) { LOG.error(dir + " is not readable.");
LOG.error(dir + " is not readable."); System.exit(1);
System.exit(1); }
} if (!dir.canWrite()) {
if (!dir.canWrite()) { LOG.error(dir + " is not writable.");
LOG.error(dir + " is not writable."); System.exit(1);
System.exit(1); }
} LOG.info("Index output goes to: " + dir.getCanonicalPath());
LOG.info("Index output goes to: " + dir.getCanonicalPath());

final Server server = new Server();
final Server server = new Server(); final SelectChannelConnector connector = new SelectChannelConnector();
final SelectChannelConnector connector = new SelectChannelConnector(); connector.setHost(configuration.getString("lucene.host", "localhost"));
connector.setHost(configuration.getString("lucene.host", "localhost")); connector.setPort(configuration.getInt("lucene.port", 5985));
connector.setPort(configuration.getInt("lucene.port", 5985));

LOG.info("Accepting connections with " + connector);
LOG.info("Accepting connections with " + connector);

server.setConnectors(new Connector[]{connector});
server.setConnectors(new Connector[] { connector }); server.setStopAtShutdown(true);
server.setStopAtShutdown(true); server.setSendServerVersion(false);
server.setSendServerVersion(false);

HttpClientFactory.setIni(configuration);
final LuceneServlet servlet = new LuceneServlet(HttpClientFactory.getInstance(), dir, configuration); final HttpClient httpClient = HttpClientFactory.getInstance();

final Context context = new Context(server, "/", Context.NO_SESSIONS final LuceneServlet servlet = new LuceneServlet(httpClient, dir, configuration);
| Context.NO_SECURITY);
context.addServlet(new ServletHolder(servlet), "/*"); final Context context = new Context(server, "/", Context.NO_SESSIONS | Context.NO_SECURITY);
context.addFilter(new FilterHolder(new GzipFilter()), "/*", context.addServlet(new ServletHolder(servlet), "/*");
Handler.DEFAULT); context.addFilter(new FilterHolder(new GzipFilter()), "/*", Handler.DEFAULT);
context.setErrorHandler(new JSONErrorHandler()); context.setErrorHandler(new JSONErrorHandler());
server.setHandler(context); server.setHandler(context);


server.start(); server.start();
server.join(); server.join();
} }


} }

0 comments on commit 378e322

Please sign in to comment.