fix anonymous access

This commit is contained in:
Sebastian Sdorra
2012-09-13 15:28:46 +02:00
parent f33a32a625
commit 492fb08558
9 changed files with 245 additions and 102 deletions

View File

@@ -113,7 +113,7 @@ public class PermissionUtil
@Deprecated
public static void assertPermission(Repository repository, PermissionType pt)
{
if (!hasPermission(repository, pt))
if (!hasPermission(null, repository, pt))
{
throw new ScmSecurityException("action denied");
}
@@ -136,7 +136,7 @@ public class PermissionUtil
public static boolean hasPermission(Repository repository,
Provider<WebSecurityContext> securityContextProvider, PermissionType pt)
{
return hasPermission(repository, securityContextProvider.get(), pt);
return hasPermission(null, repository, pt);
}
/**
@@ -154,24 +154,23 @@ public class PermissionUtil
public static boolean hasPermission(Repository repository,
WebSecurityContext securityContext, PermissionType pt)
{
return hasPermission(repository, pt);
return hasPermission(null, repository, pt);
}
/**
* Method description
*
*
* @param configuration
* @param repository
* @param securityContext
* @param pt
*
* @return
* @since 1.21
*
* @deprecated
* @since 1.21
*/
@Deprecated
public static boolean hasPermission(Repository repository, PermissionType pt)
public static boolean hasPermission(ScmConfiguration configuration,
Repository repository, PermissionType pt)
{
boolean result = false;
@@ -179,7 +178,6 @@ public class PermissionUtil
if (subject.isAuthenticated())
{
String username = subject.getPrincipal().toString();
AssertUtil.assertIsNotEmpty(username);
@@ -203,6 +201,14 @@ public class PermissionUtil
}
}
}
else
{
// check anonymous access
result = (configuration != null)
&& configuration.isAnonymousAccessEnabled()
&& repository.isPublicReadable() && (pt == PermissionType.READ);
}
return result;
}
@@ -252,7 +258,7 @@ public class PermissionUtil
}
else
{
permitted = PermissionUtil.hasPermission(repository,
permitted = PermissionUtil.hasPermission(configuration, repository,
PermissionType.WRITE);
}

View File

@@ -40,20 +40,19 @@ import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.HandlerEvent;
import sonia.scm.cache.Cache;
import sonia.scm.cache.CacheManager;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.repository.BlameResult;
import sonia.scm.repository.Branches;
import sonia.scm.repository.BrowserResult;
import sonia.scm.repository.ChangesetPagingResult;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.PermissionUtil;
import sonia.scm.repository.PostReceiveRepositoryHook;
import sonia.scm.repository.PreProcessorUtil;
import sonia.scm.repository.Repository;
@@ -65,7 +64,6 @@ import sonia.scm.repository.RepositoryNotFoundException;
import sonia.scm.repository.Tags;
import sonia.scm.repository.spi.RepositoryServiceProvider;
import sonia.scm.repository.spi.RepositoryServiceResolver;
import sonia.scm.security.RepositoryPermission;
import sonia.scm.security.ScmSecurityException;
//~--- JDK imports ------------------------------------------------------------
@@ -135,12 +133,38 @@ public final class RepositoryServiceFactory
* @param securityContextProvider provider for the current security context
* @param resolvers a set of {@link RepositoryServiceResolver}
* @param preProcessorUtil helper object for pre processor handling
*
* @deprecated
*/
@Inject
@Deprecated
public RepositoryServiceFactory(CacheManager cacheManager,
RepositoryManager repositoryManager,
Set<RepositoryServiceResolver> resolvers, PreProcessorUtil preProcessorUtil)
{
this(null, cacheManager, repositoryManager, resolvers, preProcessorUtil);
}
/**
* Constructs a new {@link RepositoryServiceFactory}. This constructor
* should not be called manually, it should only be used by the injection
* container.
*
*
* @param configuration configuration
* @param cacheManager cache manager
* @param repositoryManager manager for repositories
* @param securityContextProvider provider for the current security context
* @param resolvers a set of {@link RepositoryServiceResolver}
* @param preProcessorUtil helper object for pre processor handling
*
* @since 1.21
*/
@Inject
public RepositoryServiceFactory(ScmConfiguration configuration,
CacheManager cacheManager, RepositoryManager repositoryManager,
Set<RepositoryServiceResolver> resolvers, PreProcessorUtil preProcessorUtil)
{
this.configuration = configuration;
this.cacheManager = cacheManager;
this.repositoryManager = repositoryManager;
this.resolvers = resolvers;
@@ -249,10 +273,8 @@ public final class RepositoryServiceFactory
Preconditions.checkNotNull(repository, "repository is required");
// check for read permissions of current user
Subject subject = SecurityUtils.getSubject();
if (!subject.isPermitted(new RepositoryPermission(repository,
PermissionType.READ)))
if (!PermissionUtil.hasPermission(configuration, repository,
PermissionType.READ))
{
throw new ScmSecurityException("read permission are required");
}
@@ -408,6 +430,9 @@ public final class RepositoryServiceFactory
/** Field description */
private CacheManager cacheManager;
/** scm-manager configuration */
private ScmConfiguration configuration;
/** Field description */
private PreProcessorUtil preProcessorUtil;

View File

@@ -35,6 +35,7 @@ package sonia.scm.web.filter;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -45,6 +46,8 @@ import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContext;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.security.ScmAuthenticationToken;
import sonia.scm.user.User;
import sonia.scm.util.HttpUtil;
@@ -85,12 +88,6 @@ public class BasicAuthenticationFilter extends HttpFilter
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
* @since 1.21
*/
public BasicAuthenticationFilter() {}
/**
* Constructs ...
*
@@ -102,6 +99,19 @@ public class BasicAuthenticationFilter extends HttpFilter
public BasicAuthenticationFilter(
Provider<WebSecurityContext> securityContextProvider) {}
/**
* Constructs a new basic authenticaton filter
*
* @param configuration scm-manager global configuration
*
* @since 1.21
*/
@Inject
public BasicAuthenticationFilter(ScmConfiguration configuration)
{
this.configuration = configuration;
}
//~--- methods --------------------------------------------------------------
/**
@@ -155,6 +165,13 @@ public class BasicAuthenticationFilter extends HttpFilter
user = subject.getPrincipals().oneByType(User.class);
}
else if ((configuration != null)
&& configuration.isAnonymousAccessEnabled())
{
user = new User(SCMContext.USER_ANONYMOUS, "SCM Anonymous",
"scm-anonymous@scm-manager.com");
}
if (user == null)
{
@@ -258,4 +275,9 @@ public class BasicAuthenticationFilter extends HttpFilter
return user;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private ScmConfiguration configuration;
}

View File

@@ -45,7 +45,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.ArgumentIsInvalidException;
import sonia.scm.SCMContext;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.repository.PermissionType;
import sonia.scm.repository.PermissionUtil;
@@ -80,12 +79,11 @@ public abstract class PermissionFilter extends HttpFilter
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
*
* @param configuration
* @param securityContextProvider
* Constructs a new permission filter
*
* @param configuration global scm-manager configuration
*
* @since 1.21
*/
public PermissionFilter(ScmConfiguration configuration)
{
@@ -150,87 +148,76 @@ public abstract class PermissionFilter extends HttpFilter
{
Subject subject = SecurityUtils.getSubject();
if (subject.isAuthenticated())
try
{
try
Repository repository = getRepository(request);
if (repository != null)
{
Repository repository = getRepository(request);
boolean writeRequest = isWriteRequest(request);
if (repository != null)
if (hasPermission(repository, writeRequest))
{
boolean writeRequest = isWriteRequest(request);
if (hasPermission(repository, writeRequest))
if (logger.isTraceEnabled())
{
if (logger.isTraceEnabled())
{
logger.trace("{} access to repository {} for user {} granted",
new Object[] { writeRequest
? "write"
: "read", repository.getName(), subject.getPrincipal() });
}
chain.doFilter(request, response);
logger.trace("{} access to repository {} for user {} granted",
new Object[] { writeRequest
? "write"
: "read", repository.getName(), subject.getPrincipal() });
}
else
{
if (logger.isInfoEnabled())
{
logger.info("{} access to repository {} for user {} denied",
new Object[] { writeRequest
? "write"
: "read", repository.getName(), subject.getPrincipal() });
}
sendAccessDenied(response, subject);
}
chain.doFilter(request, response);
}
else
{
if (logger.isDebugEnabled())
if (logger.isInfoEnabled())
{
logger.debug("repository not found");
logger.info("{} access to repository {} for user {} denied",
new Object[] { writeRequest
? "write"
: "read", repository.getName(), subject.getPrincipal() });
}
response.sendError(HttpServletResponse.SC_NOT_FOUND);
sendAccessDenied(response, subject);
}
}
catch (ArgumentIsInvalidException ex)
else
{
if (logger.isTraceEnabled())
if (logger.isDebugEnabled())
{
logger.trace(
"wrong request at ".concat(request.getRequestURI()).concat(
" send redirect"), ex);
}
else if (logger.isWarnEnabled())
{
logger.warn("wrong request at {} send redirect",
request.getRequestURI());
logger.debug("repository not found");
}
response.sendRedirect(getRepositoryRootHelpUrl(request));
}
catch (ScmSecurityException ex)
{
if (logger.isWarnEnabled())
{
logger.warn("user {} has not enough permissions",
subject.getPrincipal());
}
sendAccessDenied(response, subject);
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
else
catch (ArgumentIsInvalidException ex)
{
if (logger.isDebugEnabled())
if (logger.isTraceEnabled())
{
logger.debug("user in not authenticated");
logger.trace(
"wrong request at ".concat(request.getRequestURI()).concat(
" send redirect"), ex);
}
else if (logger.isWarnEnabled())
{
logger.warn("wrong request at {} send redirect",
request.getRequestURI());
}
response.sendError(HttpServletResponse.SC_FORBIDDEN);
response.sendRedirect(getRepositoryRootHelpUrl(request));
}
catch (ScmSecurityException ex)
{
if (logger.isWarnEnabled())
{
logger.warn("user {} has not enough permissions",
subject.getPrincipal());
}
sendAccessDenied(response, subject);
}
}
/**
@@ -269,15 +256,13 @@ public abstract class PermissionFilter extends HttpFilter
private void sendAccessDenied(HttpServletResponse response, Subject subject)
throws IOException
{
// TODO check anonymous access
if (SCMContext.USER_ANONYMOUS.equals(subject.getPrincipal()))
if (subject.isAuthenticated())
{
HttpUtil.sendUnauthorized(response);
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
else
{
response.sendError(HttpServletResponse.SC_FORBIDDEN);
HttpUtil.sendUnauthorized(response);
}
}
@@ -322,7 +307,8 @@ public abstract class PermissionFilter extends HttpFilter
}
else
{
permitted = PermissionUtil.hasPermission(repository, PermissionType.READ);
permitted = PermissionUtil.hasPermission(configuration, repository,
PermissionType.READ);
}
return permitted;