BasicSecurityContext should wrap apache shiro api for compatibility reasons

This commit is contained in:
Sebastian Sdorra
2012-08-27 08:05:46 +02:00
parent 7b3dfd3ce2
commit 761c0b215e

View File

@@ -35,30 +35,25 @@ package sonia.scm.web.security;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.Sets;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.servlet.SessionScoped;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.config.ScmConfiguration; import sonia.scm.config.ScmConfiguration;
import sonia.scm.group.Group; import sonia.scm.security.Groups;
import sonia.scm.group.GroupManager; import sonia.scm.security.ScmAuthenticationToken;
import sonia.scm.security.CipherUtil;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserException;
import sonia.scm.user.UserManager; import sonia.scm.user.UserManager;
import sonia.scm.util.Util;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -68,7 +63,6 @@ import javax.servlet.http.HttpSession;
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@SessionScoped
public class BasicSecurityContext implements WebSecurityContext public class BasicSecurityContext implements WebSecurityContext
{ {
@@ -88,21 +82,14 @@ public class BasicSecurityContext implements WebSecurityContext
* Constructs ... * Constructs ...
* *
* *
*
* @param configuration * @param configuration
* @param authenticator
* @param groupManager
* @param userManager * @param userManager
*/ */
@Inject @Inject
public BasicSecurityContext(ScmConfiguration configuration, public BasicSecurityContext(ScmConfiguration configuration,
AuthenticationManager authenticator,
GroupManager groupManager,
UserManager userManager) UserManager userManager)
{ {
this.configuration = configuration; this.configuration = configuration;
this.authenticator = authenticator;
this.groupManager = groupManager;
this.userManager = userManager; this.userManager = userManager;
} }
@@ -121,25 +108,14 @@ public class BasicSecurityContext implements WebSecurityContext
*/ */
@Override @Override
public User authenticate(HttpServletRequest request, public User authenticate(HttpServletRequest request,
HttpServletResponse response, String username, HttpServletResponse response, String username, String password)
String password)
{ {
if ( logger.isTraceEnabled() ){ Subject subject = SecurityUtils.getSubject();
logger.trace("start authentication for user {}", username);
}
AuthenticationResult ar = authenticator.authenticate(request, response,
username, password);
if ( logger.isTraceEnabled() ){ subject.login(new ScmAuthenticationToken(request, response, username,
logger.trace("authentication ends with {}", ar); password));
}
if ((ar != null) && (ar.getState() == AuthenticationState.SUCCESS)) return subject.getPrincipals().oneByType(User.class);
{
authenticate(request, password, ar);
}
return user;
} }
/** /**
@@ -152,8 +128,7 @@ public class BasicSecurityContext implements WebSecurityContext
@Override @Override
public void logout(HttpServletRequest request, HttpServletResponse response) public void logout(HttpServletRequest request, HttpServletResponse response)
{ {
user = null; SecurityUtils.getSubject().logout();
groups = new HashSet<String>();
HttpSession session = request.getSession(false); HttpSession session = request.getSession(false);
@@ -174,12 +149,21 @@ public class BasicSecurityContext implements WebSecurityContext
@Override @Override
public Collection<String> getGroups() public Collection<String> getGroups()
{ {
if (groups == null) Subject subject = SecurityUtils.getSubject();
Groups groups = getPrincipal(Groups.class);
Collection<String> groupCollection = null;
if (groups != null)
{ {
groups = new HashSet<String>(); groupCollection = groups.getGroups();
}
else
{
groupCollection = Collections.EMPTY_LIST;
} }
return groups; return groupCollection;
} }
/** /**
@@ -191,6 +175,8 @@ public class BasicSecurityContext implements WebSecurityContext
@Override @Override
public User getUser() public User getUser()
{ {
User user = getPrincipal(User.class);
if ((user == null) && configuration.isAnonymousAccessEnabled()) if ((user == null) && configuration.isAnonymousAccessEnabled())
{ {
user = userManager.get(USER_ANONYMOUS); user = userManager.get(USER_ANONYMOUS);
@@ -211,276 +197,27 @@ public class BasicSecurityContext implements WebSecurityContext
return getUser() != null; return getUser() != null;
} }
//~--- methods --------------------------------------------------------------
/** /**
* Method description * Method description
* *
* *
* @param request * @param clazz
* @param password * @param <T>
* @param ar
*/
private void authenticate(HttpServletRequest request, String password,
AuthenticationResult ar)
{
user = ar.getUser();
try
{
Set<String> groupSet = createGroupSet(ar);
// check for admin user
checkForAuthenticatedAdmin(user, groupSet);
// store user
User dbUser = userManager.get(user.getName());
if (dbUser != null)
{
checkDBForAdmin(user, dbUser);
checkDBForActive(user, dbUser);
}
// create new user
else
{
userManager.create(user);
}
if (user.isActive())
{
groups = groupSet;
if (logger.isDebugEnabled())
{
logGroups();
}
// store encrypted credentials in session
String credentials = user.getName();
if (Util.isNotEmpty(password))
{
credentials = credentials.concat(":").concat(password);
}
credentials = CipherUtil.getInstance().encode(credentials);
request.getSession(true).setAttribute(SCM_CREDENTIALS, credentials);
}
else
{
if (logger.isWarnEnabled())
{
logger.warn("user {} is deactivated", user.getName());
}
user = null;
groups = null;
}
}
catch (Exception ex)
{
user = null;
if (groups != null)
{
groups.clear();
}
logger.error("authentication failed", ex);
}
}
/**
* Method description
*
*
* @param user
* @param dbUser
*/
private void checkDBForActive(User user, User dbUser)
{
// user is deactivated by database
if (!dbUser.isActive())
{
if (logger.isDebugEnabled())
{
logger.debug("user {} is marked as deactivated by local database",
user.getName());
}
user.setActive(false);
}
}
/**
* Method description
*
*
* @param user
* @param dbUser
*
* @throws IOException
* @throws UserException
*/
private void checkDBForAdmin(User user, User dbUser)
throws UserException, IOException
{
// if database user is an admin, set admin for the current user
if (dbUser.isAdmin())
{
if (logger.isDebugEnabled())
{
logger.debug("user {} of type {} is marked as admin by local database",
user.getName(), user.getType());
}
user.setAdmin(true);
}
// modify existing user, copy properties except password and admin
if (user.copyProperties(dbUser, false))
{
userManager.modify(dbUser);
}
}
/**
* Method description
*
*
* @param user
* @param groupSet
*/
private void checkForAuthenticatedAdmin(User user, Set<String> groupSet)
{
if (!user.isAdmin())
{
user.setAdmin(isAdmin(groupSet));
if (logger.isDebugEnabled() && user.isAdmin())
{
logger.debug("user {} is marked as admin by configuration",
user.getName());
}
}
else if (logger.isDebugEnabled())
{
logger.debug("authenticator {} marked user {} as admin", user.getType(),
user.getName());
}
}
/**
* Method description
*
*
* @param ar
* *
* @return * @return
*/ */
private Set<String> createGroupSet(AuthenticationResult ar) private <T> T getPrincipal(Class<T> clazz)
{ {
Set<String> groupSet = Sets.newHashSet(); T result = null;
Subject subject = SecurityUtils.getSubject();
// load external groups if (subject.isAuthenticated())
Collection<String> extGroups = ar.getGroups();
if (extGroups != null)
{ {
groupSet.addAll(extGroups); PrincipalCollection pc = subject.getPrincipals();
}
// load internal groups if (pc != null)
loadGroups(groupSet);
return groupSet;
}
/**
* Method description
*
*
* @param groupSet
*/
private void loadGroups(Set<String> groupSet)
{ {
Collection<Group> groupCollection = result = pc.oneByType(clazz);
groupManager.getGroupsForMember(user.getName());
if (groupCollection != null)
{
for (Group group : groupCollection)
{
groupSet.add(group.getName());
}
}
}
/**
* Method description
*
*/
private void logGroups()
{
StringBuilder msg = new StringBuilder("user ");
msg.append(user.getName());
if (Util.isNotEmpty(groups))
{
msg.append(" is member of ");
Iterator<String> groupIt = groups.iterator();
while (groupIt.hasNext())
{
msg.append(groupIt.next());
if (groupIt.hasNext())
{
msg.append(", ");
}
}
}
else
{
msg.append(" is not a member of a group");
}
logger.debug(msg.toString());
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
*
* @param groups
* @return
*/
private boolean isAdmin(Collection<String> groups)
{
boolean result = false;
Set<String> adminUsers = configuration.getAdminUsers();
if (adminUsers != null)
{
result = adminUsers.contains(user.getName());
}
if (!result)
{
Set<String> adminGroups = configuration.getAdminGroups();
if (adminGroups != null)
{
result = Util.containsOne(adminGroups, groups);
} }
} }
@@ -489,21 +226,9 @@ public class BasicSecurityContext implements WebSecurityContext
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */
private AuthenticationManager authenticator;
/** Field description */ /** Field description */
private ScmConfiguration configuration; private ScmConfiguration configuration;
/** Field description */
private GroupManager groupManager;
/** Field description */
private Set<String> groups = new HashSet<String>();
/** Field description */
private User user;
/** Field description */ /** Field description */
private UserManager userManager; private UserManager userManager;
} }