diff --git a/nexus-logging-extras/src/main/resources/META-INF/log/logback.properties b/nexus-logging-extras/src/main/resources/META-INF/log/logback.properties index 973b7c87c8..49c9d8786a 100644 --- a/nexus-logging-extras/src/main/resources/META-INF/log/logback.properties +++ b/nexus-logging-extras/src/main/resources/META-INF/log/logback.properties @@ -12,5 +12,5 @@ # root.level=INFO -appender.pattern=%4d{yyyy-MM-dd HH:mm:ss} %-5p [%-15.15t] - %c - %m%n +appender.pattern=%4d{yyyy-MM-dd HH:mm:ss} %-5p [%-15.15t] %X{userId} %c - %m%n appender.file=${nexus.log-config-dir}/../logs/nexus.log diff --git a/nexus-web-utils/src/main/java/org/sonatype/nexus/web/MdcUserContextFilter.java b/nexus-web-utils/src/main/java/org/sonatype/nexus/web/MdcUserContextFilter.java new file mode 100644 index 0000000000..17e6303bf7 --- /dev/null +++ b/nexus-web-utils/src/main/java/org/sonatype/nexus/web/MdcUserContextFilter.java @@ -0,0 +1,93 @@ +/* + * Sonatype Nexus (TM) Open Source Version + * Copyright (c) 2007-2012 Sonatype, Inc. + * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions. + * + * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0, + * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html. + * + * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks + * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the + * Eclipse Foundation. All other trademarks are the property of their respective owners. + */ +package org.sonatype.nexus.web; + +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import javax.inject.Named; +import javax.inject.Singleton; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import java.io.IOException; + +// NOTE: This would be better integrated as part of the org.sonatype.security.web.guice.SecurityWebFilter ? + +/** + * Servlet filter to add user context details to the {@link MDC}. + * + * @since 2.5 + */ +@Named +@Singleton +public class MdcUserContextFilter + implements Filter +{ + private static final Logger log = LoggerFactory.getLogger(MdcUserContextFilter.class); + + public static final String USER_ID = "userId"; + + public static final String UNKNOWN_USER_ID = ""; + + @Override + public void init(final FilterConfig config) throws ServletException { + // ignore + } + + @Override + public void destroy() { + // ignore + } + + @Override + public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) + throws IOException, ServletException + { + MDC.put(USER_ID, getCurrentUserId()); + + try { + chain.doFilter(request, response); + } + finally { + MDC.remove(USER_ID); + } + } + + private String getCurrentUserId() { + String userId = UNKNOWN_USER_ID; + + try { + Subject subject = SecurityUtils.getSubject(); + if (subject != null) { + Object principal = subject.getPrincipal(); + if (principal != null) { + userId = principal.toString(); + } + } + } + catch (Exception e) { + log.warn("Unable to determine current user; ignoring", e); + } + + log.trace("Current userId: {}", userId); + + return userId; + } +} diff --git a/plugins/restlet1x/nexus-restlet1x-plugin/src/main/java/org/sonatype/nexus/web/NexusServletModule.java b/plugins/restlet1x/nexus-restlet1x-plugin/src/main/java/org/sonatype/nexus/web/NexusServletModule.java index d1a638f470..feed528687 100644 --- a/plugins/restlet1x/nexus-restlet1x-plugin/src/main/java/org/sonatype/nexus/web/NexusServletModule.java +++ b/plugins/restlet1x/nexus-restlet1x-plugin/src/main/java/org/sonatype/nexus/web/NexusServletModule.java @@ -42,6 +42,7 @@ protected void configureServlets() filter("/service/local/*").through( SecurityWebFilter.class ); filter("/content/*").through( SecurityWebFilter.class ); + filter("/*").through( MdcUserContextFilter.class ); /* * Give components contributed by this plugin a low-level ranking (same level as Nexus core) so they are ordered diff --git a/plugins/siesta/nexus-siesta-plugin/src/main/java/org/sonatype/nexus/plugins/siesta/SiestaModule.java b/plugins/siesta/nexus-siesta-plugin/src/main/java/org/sonatype/nexus/plugins/siesta/SiestaModule.java index 2feb2814fe..0e4283f498 100644 --- a/plugins/siesta/nexus-siesta-plugin/src/main/java/org/sonatype/nexus/plugins/siesta/SiestaModule.java +++ b/plugins/siesta/nexus-siesta-plugin/src/main/java/org/sonatype/nexus/plugins/siesta/SiestaModule.java @@ -16,6 +16,7 @@ import com.google.inject.servlet.ServletModule; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.sonatype.nexus.web.MdcUserContextFilter; import org.sonatype.security.web.guice.SecurityWebFilter; import org.sonatype.sisu.siesta.common.Resource; import org.sonatype.sisu.siesta.jackson.SiestaJacksonModule; @@ -82,6 +83,7 @@ protected String pathOf(final Class type) { protected void configureServlets() { serve(MOUNT_POINT + "/*").with(SiestaServlet.class); filter(MOUNT_POINT + "/*").through(SecurityWebFilter.class); + filter(MOUNT_POINT + "/*").through(MdcUserContextFilter.class); } }); }