Add User to the http request attributes

GetUserFilter is adding the user to the request attribute so the user
who requested the URL is printed in the httpd_log but it is only
applied when running Gerrit with the embedded servlet container.

Move GetUserFilter from the gerrit-pgm to gerrit-httpd so it can be
applied when running Gerrit in a servlet container (e.g. Tomcat). Add
a parameter http.addUserAsRequestAttribute in gerrit config to
enable/disable this filter. It is enabled by default.

In tomcat, pattern %{User}r can be used in the AccessLog to print user
to get same functionality as httpd_log when running with the embedded
servlet container.

Change-Id: I591d594848a5b2d4aa9389965365e0621b39a51c
This commit is contained in:
Hugo Arès 2014-03-03 13:52:45 -05:00
parent a2467073ac
commit 88e33ac9f1
5 changed files with 42 additions and 26 deletions

View File

@ -1750,6 +1750,24 @@ Optional password to authenticate to the HTTP proxy with.
This property is honored only if the password does not
appear in the http.proxy property above.
[[http.addUserAsRequestAttribute]]http.addUserAsRequestAttribute::
+
If true, 'User' attribute will be added to the request attributes so it
can be accessed outside the request scope (will be set to username or id
if username not configured).
+
This attribute can be used by the servlet container to log user in the
http access log.
+
When running the embedded servlet container, this attribute is used to
print user in the httpd_log.
+
* `%{User}r`
+
Pattern to print user in Tomcat AccessLog.
+
Default value is true.
[[httpd]]
=== Section httpd

View File

@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.pgm.http.jetty;
package com.google.gerrit.httpd;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.inject.Inject;
import com.google.inject.Provider;
@ -24,7 +25,6 @@ import com.google.inject.servlet.ServletModule;
import org.eclipse.jgit.lib.Config;
import java.io.IOException;
import java.net.URI;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@ -34,28 +34,27 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* Stores as a request attribute, so the {@link HttpLog} can include the the
* user for the request outside of the request scope.
* Stores user as a request attribute, so the servlet container access log like
* {@link HttpLog} can include the the user for the request outside of the
* request scope.
*/
@Singleton
public class GetUserFilter implements Filter {
static final String REQ_ATTR_KEY = CurrentUser.class.toString();
public static final String REQ_ATTR_KEY = "User";
public static class Module extends ServletModule {
private boolean loggingEnabled;
private final boolean enabled;
@Inject
Module(@GerritServerConfig final Config cfg) {
URI[] urls = JettyServer.listenURLs(cfg);
boolean reverseProxy = JettyServer.isReverseProxied(urls);
this.loggingEnabled = cfg.getBoolean("httpd", "requestLog", !reverseProxy);
enabled = cfg.getBoolean("http", "addUserAsRequestAttribute", true);
}
@Override
protected void configureServlets() {
if (loggingEnabled) {
if (enabled) {
filter("/*").through(GetUserFilter.class);
}
}
@ -72,7 +71,15 @@ public class GetUserFilter implements Filter {
public void doFilter(
ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
req.setAttribute(REQ_ATTR_KEY, userProvider.get());
CurrentUser user = userProvider.get();
if (user != null && user.isIdentifiedUser()) {
IdentifiedUser who = (IdentifiedUser) user;
if (who.getUserName() != null && !who.getUserName().isEmpty()) {
req.setAttribute(REQ_ATTR_KEY, who.getUserName());
} else {
req.setAttribute(REQ_ATTR_KEY, "a/" + who.getAccountId());
}
}
chain.doFilter(req, resp);
}

View File

@ -21,6 +21,7 @@ import com.google.common.base.MoreObjects;
import com.google.gerrit.common.ChangeHookRunner;
import com.google.gerrit.httpd.AllRequestFilter;
import com.google.gerrit.httpd.GerritOptions;
import com.google.gerrit.httpd.GetUserFilter;
import com.google.gerrit.httpd.GitOverHttpModule;
import com.google.gerrit.httpd.H2CacheBasedWebSession;
import com.google.gerrit.httpd.HttpCanonicalWebUrlProvider;
@ -31,7 +32,6 @@ import com.google.gerrit.httpd.auth.openid.OpenIdModule;
import com.google.gerrit.httpd.plugins.HttpPluginModule;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.lucene.LuceneIndexModule;
import com.google.gerrit.pgm.http.jetty.GetUserFilter;
import com.google.gerrit.pgm.http.jetty.JettyEnv;
import com.google.gerrit.pgm.http.jetty.JettyModule;
import com.google.gerrit.pgm.http.jetty.ProjectQoSFilter;

View File

@ -14,8 +14,7 @@
package com.google.gerrit.pgm.http.jetty;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.httpd.GetUserFilter;
import com.google.gerrit.server.util.SystemLog;
import com.google.gerrit.server.util.TimeUtil;
import com.google.inject.Inject;
@ -66,11 +65,6 @@ class HttpLog extends AbstractLifeCycle implements RequestLog {
@Override
public void log(final Request req, final Response rsp) {
CurrentUser user = (CurrentUser) req.getAttribute(GetUserFilter.REQ_ATTR_KEY);
doLog(req, rsp, user);
}
private void doLog(Request req, Response rsp, CurrentUser user) {
final LoggingEvent event = new LoggingEvent( //
Logger.class.getName(), // fqnOfCategoryClass
log, // logger
@ -90,13 +84,9 @@ class HttpLog extends AbstractLifeCycle implements RequestLog {
uri = uri + "?" + qs;
}
if (user != null && user.isIdentifiedUser()) {
IdentifiedUser who = (IdentifiedUser) user;
if (who.getUserName() != null && !who.getUserName().isEmpty()) {
event.setProperty(P_USER, who.getUserName());
} else {
event.setProperty(P_USER, "a/" + who.getAccountId());
}
String user = (String) req.getAttribute(GetUserFilter.REQ_ATTR_KEY);
if (user != null) {
event.setProperty(P_USER, user);
}
set(event, P_HOST, req.getRemoteAddr());

View File

@ -344,6 +344,7 @@ public class WebAppInitializer extends GuiceServletContextListener
if (authConfig.getAuthType() == AuthType.OPENID) {
modules.add(new OpenIdModule());
}
modules.add(sysInjector.getInstance(GetUserFilter.Module.class));
return sysInjector.createChildInjector(modules);
}