mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 15:35:49 +01:00
merge with branch issue-195
This commit is contained in:
@@ -47,6 +47,7 @@ import java.util.Comparator;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
@@ -398,6 +399,23 @@ public class Util
|
|||||||
return parseDate(dateString, null);
|
return parseDate(dateString, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param start
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @since 1.17
|
||||||
|
*/
|
||||||
|
public static boolean startWithIgnoreCase(String value, String start)
|
||||||
|
{
|
||||||
|
return (value != null) && (start != null)
|
||||||
|
&& value.toUpperCase(Locale.ENGLISH).startsWith(start);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -120,18 +120,44 @@ public class BasicAuthenticationFilter extends HttpFilter
|
|||||||
User user = null;
|
User user = null;
|
||||||
String authentication = request.getHeader(HEADER_AUTHORIZATION);
|
String authentication = request.getHeader(HEADER_AUTHORIZATION);
|
||||||
|
|
||||||
if (Util.isNotEmpty(authentication)
|
if (Util.startWithIgnoreCase(authentication, AUTHORIZATION_BASIC_PREFIX))
|
||||||
&& authentication.toUpperCase().startsWith(AUTHORIZATION_BASIC_PREFIX))
|
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("found basic authorization header, start authentication");
|
||||||
|
}
|
||||||
|
|
||||||
user = authenticate(request, response, securityContext, authentication);
|
user = authenticate(request, response, securityContext, authentication);
|
||||||
|
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
logger.trace("user {} successfully authenticated", user.getName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.trace("authentcation failed, user object is null");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (securityContext.isAuthenticated())
|
else if (securityContext.isAuthenticated())
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("user is allready authenticated");
|
||||||
|
}
|
||||||
|
|
||||||
user = securityContext.getUser();
|
user = securityContext.getUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("could not find user send unauthorized");
|
||||||
|
}
|
||||||
|
|
||||||
HttpUtil.sendUnauthorized(response);
|
HttpUtil.sendUnauthorized(response);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -192,6 +218,11 @@ public class BasicAuthenticationFilter extends HttpFilter
|
|||||||
|
|
||||||
if (Util.isNotEmpty(username) && Util.isNotEmpty(password))
|
if (Util.isNotEmpty(username) && Util.isNotEmpty(password))
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("try to authenticate user {}", username);
|
||||||
|
}
|
||||||
|
|
||||||
user = securityContext.authenticate(request, response, username,
|
user = securityContext.authenticate(request, response, username,
|
||||||
password);
|
password);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ package sonia.scm.web.filter;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.io.Closeables;
|
import com.google.common.io.Closeables;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ public class LoggingFilter extends HttpFilter
|
|||||||
{
|
{
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
boolean logBody = logger.isTraceEnabled();
|
boolean logBody = logger.isTraceEnabled() && isTextRequest(request);
|
||||||
BufferedHttpServletRequest bufferedRequest =
|
BufferedHttpServletRequest bufferedRequest =
|
||||||
new BufferedHttpServletRequest(request, logBody);
|
new BufferedHttpServletRequest(request, logBody);
|
||||||
BufferedHttpServletResponse bufferedResponse =
|
BufferedHttpServletResponse bufferedResponse =
|
||||||
@@ -190,7 +191,12 @@ public class LoggingFilter extends HttpFilter
|
|||||||
|
|
||||||
if (logger.isTraceEnabled())
|
if (logger.isTraceEnabled())
|
||||||
{
|
{
|
||||||
logger.trace("Content: ".concat(new String(request.getContentBuffer())));
|
byte[] contentBuffer = request.getContentBuffer();
|
||||||
|
|
||||||
|
if ((contentBuffer != null) && (contentBuffer.length > 0))
|
||||||
|
{
|
||||||
|
logger.trace("Content: ".concat(new String(contentBuffer)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,22 +234,68 @@ public class LoggingFilter extends HttpFilter
|
|||||||
logger.debug("Header: {} = {}", header.getKey(), header.getValue());
|
logger.debug("Header: {} = {}", header.getKey(), header.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logger.isTraceEnabled())
|
if (logger.isTraceEnabled() && isTextRequest(orgResponse))
|
||||||
{
|
{
|
||||||
byte[] content = response.getContentBuffer();
|
byte[] content = response.getContentBuffer();
|
||||||
ServletOutputStream out = null;
|
|
||||||
|
|
||||||
try
|
if ((content != null) && (content.length > 0))
|
||||||
{
|
{
|
||||||
out = orgResponse.getOutputStream();
|
ServletOutputStream out = null;
|
||||||
out.write(content);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Closeables.closeQuietly(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.trace("Content: ".concat(new String(content)));
|
try
|
||||||
|
{
|
||||||
|
out = orgResponse.getOutputStream();
|
||||||
|
out.write(content);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Closeables.closeQuietly(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.trace("Content: ".concat(new String(content)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//~--- get methods ----------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isTextRequest(HttpServletRequest request)
|
||||||
|
{
|
||||||
|
return isTextRequest(request.getContentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isTextRequest(HttpServletResponse response)
|
||||||
|
{
|
||||||
|
return isTextRequest(response.getContentType());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method description
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param contentType
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean isTextRequest(String contentType)
|
||||||
|
{
|
||||||
|
return !Strings.isNullOrEmpty(contentType)
|
||||||
|
&& contentType.toLowerCase().startsWith("text");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,6 +150,15 @@ public abstract class PermissionFilter extends HttpFilter
|
|||||||
|
|
||||||
if (hasPermission(repository, securityContext, writeRequest))
|
if (hasPermission(repository, securityContext, writeRequest))
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("{} access to repository {} for user {} granted",
|
||||||
|
new Object[] { writeRequest
|
||||||
|
? "write"
|
||||||
|
: "read", repository.getName(),
|
||||||
|
user.getName() });
|
||||||
|
}
|
||||||
|
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ import sonia.scm.util.DebugServlet;
|
|||||||
import sonia.scm.util.ScmConfigurationUtil;
|
import sonia.scm.util.ScmConfigurationUtil;
|
||||||
import sonia.scm.web.cgi.CGIExecutorFactory;
|
import sonia.scm.web.cgi.CGIExecutorFactory;
|
||||||
import sonia.scm.web.cgi.DefaultCGIExecutorFactory;
|
import sonia.scm.web.cgi.DefaultCGIExecutorFactory;
|
||||||
|
import sonia.scm.web.filter.LoggingFilter;
|
||||||
import sonia.scm.web.security.AdministrationContext;
|
import sonia.scm.web.security.AdministrationContext;
|
||||||
import sonia.scm.web.security.ApiBasicAuthenticationFilter;
|
import sonia.scm.web.security.ApiBasicAuthenticationFilter;
|
||||||
import sonia.scm.web.security.AuthenticationManager;
|
import sonia.scm.web.security.AuthenticationManager;
|
||||||
@@ -173,6 +174,9 @@ public class ScmServletModule extends ServletModule
|
|||||||
/** Field description */
|
/** Field description */
|
||||||
public static final String REST_PACKAGE = "sonia.scm.api.rest";
|
public static final String REST_PACKAGE = "sonia.scm.api.rest";
|
||||||
|
|
||||||
|
/** Field description */
|
||||||
|
public static final String SYSTEM_PROPERTY_DEBUG_HTTP = "scm.debug.http";
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
public static final String[] PATTERN_STATIC_RESOURCES = new String[] {
|
public static final String[] PATTERN_STATIC_RESOURCES = new String[] {
|
||||||
PATTERN_SCRIPT,
|
PATTERN_SCRIPT,
|
||||||
@@ -303,6 +307,12 @@ public class ScmServletModule extends ServletModule
|
|||||||
// bind repository service factory
|
// bind repository service factory
|
||||||
bind(RepositoryServiceFactory.class);
|
bind(RepositoryServiceFactory.class);
|
||||||
|
|
||||||
|
// bind debug logging filter
|
||||||
|
if ("true".equalsIgnoreCase(System.getProperty(SYSTEM_PROPERTY_DEBUG_HTTP)))
|
||||||
|
{
|
||||||
|
filter(PATTERN_ALL).through(LoggingFilter.class);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* filter(PATTERN_PAGE,
|
* filter(PATTERN_PAGE,
|
||||||
* PATTERN_STATIC_RESOURCES).through(StaticResourceFilter.class);
|
* PATTERN_STATIC_RESOURCES).through(StaticResourceFilter.class);
|
||||||
|
|||||||
@@ -124,9 +124,16 @@ public class BasicSecurityContext implements WebSecurityContext
|
|||||||
HttpServletResponse response, String username,
|
HttpServletResponse response, String username,
|
||||||
String password)
|
String password)
|
||||||
{
|
{
|
||||||
|
if ( logger.isTraceEnabled() ){
|
||||||
|
logger.trace("start authentication for user {}", username);
|
||||||
|
}
|
||||||
AuthenticationResult ar = authenticator.authenticate(request, response,
|
AuthenticationResult ar = authenticator.authenticate(request, response,
|
||||||
username, password);
|
username, password);
|
||||||
|
|
||||||
|
if ( logger.isTraceEnabled() ){
|
||||||
|
logger.trace("authentication ends with {}", ar);
|
||||||
|
}
|
||||||
|
|
||||||
if ((ar != null) && (ar.getState() == AuthenticationState.SUCCESS))
|
if ((ar != null) && (ar.getState() == AuthenticationState.SUCCESS))
|
||||||
{
|
{
|
||||||
authenticate(request, password, ar);
|
authenticate(request, password, ar);
|
||||||
|
|||||||
@@ -130,6 +130,12 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
|||||||
|
|
||||||
if (ar == null)
|
if (ar == null)
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("no authentication result for user {} found in cache",
|
||||||
|
username);
|
||||||
|
}
|
||||||
|
|
||||||
ar = doAuthentication(request, response, username, password);
|
ar = doAuthentication(request, response, username, password);
|
||||||
|
|
||||||
if ((ar != null) && ar.isCacheable())
|
if ((ar != null) && ar.isCacheable())
|
||||||
@@ -157,6 +163,11 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
|||||||
{
|
{
|
||||||
for (AuthenticationHandler authenticator : authenticationHandlerSet)
|
for (AuthenticationHandler authenticator : authenticationHandlerSet)
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("close authenticator {}", authenticator.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
IOUtil.close(authenticator);
|
IOUtil.close(authenticator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,6 +183,11 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
|||||||
{
|
{
|
||||||
for (AuthenticationHandler authenticator : authenticationHandlerSet)
|
for (AuthenticationHandler authenticator : authenticationHandlerSet)
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("initialize authenticator {}", authenticator.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
authenticator.init(context);
|
authenticator.init(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,8 +216,19 @@ public class ChainAuthenticatonManager extends AbstractAuthenticationManager
|
|||||||
{
|
{
|
||||||
AuthenticationResult ar = null;
|
AuthenticationResult ar = null;
|
||||||
|
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("start authentication chain for user {}", username);
|
||||||
|
}
|
||||||
|
|
||||||
for (AuthenticationHandler authenticator : authenticationHandlerSet)
|
for (AuthenticationHandler authenticator : authenticationHandlerSet)
|
||||||
{
|
{
|
||||||
|
if (logger.isTraceEnabled())
|
||||||
|
{
|
||||||
|
logger.trace("check authenticator {} for user {}",
|
||||||
|
authenticator.getClass(), username);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AuthenticationResult result = authenticator.authenticate(request,
|
AuthenticationResult result = authenticator.authenticate(request,
|
||||||
|
|||||||
Reference in New Issue
Block a user