Permit plugins to implement AllRequestFilter
If a plugin extends AllRequestFilter and binds it as a member of the DynamicSet, the plugin can filter any HTTP request that passes through the server. This allows a monitoring plugin, or an access control plugin, to glue in very early in the serving pipeline and see all requests. The plugin point is after the RequestContextFilter configures the Guice environment used by Gerrit, but before any user authentication can happen. An access control plugin might be able to reject connections based on remote IP address, or client side SSL certificate, but cannot rely on Gerrit user information. If multiple plugins register implementations, the order they are invoked is currently undefined. The likely order is derived from the sorting of the names in the plugins/ directory, but we don't promise any ordering. Change-Id: I8709373379ec09e79502f67446b8a7b805e8cec7
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
// Copyright (C) 2012 The Android Open Source Project
|
||||
//
|
||||
// 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.google.gerrit.httpd;
|
||||
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.servlet.ServletModule;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
/** Filters all HTTP requests passing through the server. */
|
||||
public abstract class AllRequestFilter implements Filter {
|
||||
public static ServletModule module() {
|
||||
return new ServletModule() {
|
||||
@Override
|
||||
protected void configureServlets() {
|
||||
DynamicSet.setOf(binder(), AllRequestFilter.class);
|
||||
filter("/*").through(FilterProxy.class);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Singleton
|
||||
static class FilterProxy implements Filter {
|
||||
private final DynamicSet<AllRequestFilter> filters;
|
||||
|
||||
@Inject
|
||||
FilterProxy(DynamicSet<AllRequestFilter> filters) {
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res,
|
||||
final FilterChain last) throws IOException, ServletException {
|
||||
final Iterator<AllRequestFilter> itr = filters.iterator();
|
||||
new FilterChain() {
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res)
|
||||
throws IOException, ServletException {
|
||||
if (itr.hasNext()) {
|
||||
itr.next().doFilter(req, res, this);
|
||||
} else {
|
||||
last.doFilter(req, res);
|
||||
}
|
||||
}
|
||||
}.doFilter(req, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig config) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig config) throws ServletException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ package com.google.gerrit.pgm;
|
||||
import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
|
||||
|
||||
import com.google.gerrit.common.ChangeHookRunner;
|
||||
import com.google.gerrit.httpd.AllRequestFilter;
|
||||
import com.google.gerrit.httpd.CacheBasedWebSession;
|
||||
import com.google.gerrit.httpd.GitOverHttpModule;
|
||||
import com.google.gerrit.httpd.HttpCanonicalWebUrlProvider;
|
||||
@@ -354,6 +355,7 @@ public class Daemon extends SiteProgram {
|
||||
private Injector createWebInjector() {
|
||||
final List<Module> modules = new ArrayList<Module>();
|
||||
modules.add(RequestContextFilter.module());
|
||||
modules.add(AllRequestFilter.module());
|
||||
modules.add(CacheBasedWebSession.module());
|
||||
modules.add(HttpContactStoreConnection.module());
|
||||
modules.add(sysInjector.getInstance(GitOverHttpModule.class));
|
||||
|
||||
@@ -224,6 +224,7 @@ public class WebAppInitializer extends GuiceServletContextListener {
|
||||
private Injector createWebInjector() {
|
||||
final List<Module> modules = new ArrayList<Module>();
|
||||
modules.add(RequestContextFilter.module());
|
||||
modules.add(AllRequestFilter.module());
|
||||
modules.add(sysInjector.getInstance(GitOverHttpModule.class));
|
||||
modules.add(sshInjector.getInstance(WebModule.class));
|
||||
modules.add(sshInjector.getInstance(WebSshGlueModule.class));
|
||||
|
||||
Reference in New Issue
Block a user