mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 09:25:43 +01:00
replace scm-manager 1.x security api with apache shiro and use PasswordService for stronger password hashes
This commit is contained in:
@@ -50,6 +50,7 @@ import static sonia.scm.it.IntegrationTestUtil.*;
|
||||
import com.sun.jersey.api.client.Client;
|
||||
import com.sun.jersey.api.client.ClientResponse;
|
||||
import com.sun.jersey.api.client.WebResource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
@@ -126,9 +127,8 @@ public class DeactivatedUserITCase
|
||||
Client client = createClient();
|
||||
ClientResponse response = authenticate(client, slarti.getName(),
|
||||
"slart123");
|
||||
|
||||
assertNotNull(response);
|
||||
assertEquals(401, response.getStatus());
|
||||
assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus());
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer. 2. Redistributions in
|
||||
* binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
|
||||
* nor the names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.apache.shiro.authc.ExcessiveAttemptsException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.web.security.AuthenticationResult;
|
||||
import sonia.scm.web.security.AuthenticationState;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class ConfigurableLoginAttemptHandlerTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = ExcessiveAttemptsException.class)
|
||||
public void testLoginAttemptLimitReached()
|
||||
{
|
||||
LoginAttemptHandler handler = createHandler(2, 2);
|
||||
UsernamePasswordToken token = new UsernamePasswordToken("hansolo", "hobbo");
|
||||
|
||||
handler.beforeAuthentication(token);
|
||||
handler.onUnsuccessfulAuthentication(token, AuthenticationResult.FAILED);
|
||||
handler.beforeAuthentication(token);
|
||||
handler.onUnsuccessfulAuthentication(token, AuthenticationResult.FAILED);
|
||||
handler.beforeAuthentication(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Test
|
||||
public void testLoginAttemptLimitTimeout() throws InterruptedException
|
||||
{
|
||||
LoginAttemptHandler handler = createHandler(2, 1);
|
||||
UsernamePasswordToken token = new UsernamePasswordToken("hansolo", "hobbo");
|
||||
|
||||
handler.beforeAuthentication(token);
|
||||
handler.onUnsuccessfulAuthentication(token, AuthenticationResult.FAILED);
|
||||
handler.beforeAuthentication(token);
|
||||
handler.onUnsuccessfulAuthentication(token, AuthenticationResult.FAILED);
|
||||
Thread.currentThread().sleep(TimeUnit.MILLISECONDS.toMillis(1200l));
|
||||
handler.beforeAuthentication(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Test
|
||||
public void testLoginAttemptResetOnSuccess() throws InterruptedException
|
||||
{
|
||||
LoginAttemptHandler handler = createHandler(2, 1);
|
||||
UsernamePasswordToken token = new UsernamePasswordToken("hansolo", "hobbo");
|
||||
|
||||
handler.beforeAuthentication(token);
|
||||
handler.onUnsuccessfulAuthentication(token, AuthenticationResult.FAILED);
|
||||
handler.beforeAuthentication(token);
|
||||
handler.onUnsuccessfulAuthentication(token, AuthenticationResult.FAILED);
|
||||
|
||||
handler.onSuccessfulAuthentication(token,
|
||||
new AuthenticationResult(AuthenticationState.SUCCESS));
|
||||
|
||||
handler.beforeAuthentication(token);
|
||||
handler.onUnsuccessfulAuthentication(token, AuthenticationResult.FAILED);
|
||||
handler.beforeAuthentication(token);
|
||||
handler.onUnsuccessfulAuthentication(token, AuthenticationResult.FAILED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param loginAttemptLimit
|
||||
* @param loginAttemptLimitTimeout
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private LoginAttemptHandler createHandler(int loginAttemptLimit,
|
||||
long loginAttemptLimitTimeout)
|
||||
{
|
||||
ScmConfiguration configuration = new ScmConfiguration();
|
||||
|
||||
configuration.setLoginAttemptLimit(loginAttemptLimit);
|
||||
configuration.setLoginAttemptLimitTimeout(loginAttemptLimitTimeout);
|
||||
|
||||
return new ConfigurableLoginAttemptHandler(configuration);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
/**
|
||||
* Copyright (c) 2014, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.DisabledAccountException;
|
||||
import org.apache.shiro.authc.IncorrectCredentialsException;
|
||||
import org.apache.shiro.authc.UnknownAccountException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.authc.credential.DefaultPasswordService;
|
||||
import org.apache.shiro.crypto.hash.DefaultHashService;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.apache.shiro.subject.SimplePrincipalCollection;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupDAO;
|
||||
import sonia.scm.group.GroupNames;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserDAO;
|
||||
import sonia.scm.user.UserTestData;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultRealmTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = DisabledAccountException.class)
|
||||
public void testDisabledAccount()
|
||||
{
|
||||
User user = UserTestData.createMarvin();
|
||||
|
||||
user.setActive(false);
|
||||
|
||||
UsernamePasswordToken token = daoUser(user, "secret");
|
||||
|
||||
realm.getAuthenticationInfo(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGetAuthorizationInfo()
|
||||
{
|
||||
SimplePrincipalCollection col = new SimplePrincipalCollection();
|
||||
|
||||
realm.doGetAuthorizationInfo(col);
|
||||
verify(collector, times(1)).collect(col);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testGroupCollection()
|
||||
{
|
||||
User user = UserTestData.createTrillian();
|
||||
//J-
|
||||
List<Group> groups = Lists.newArrayList(
|
||||
new Group(DefaultRealm.REALM, "scm", user.getName()),
|
||||
new Group(DefaultRealm.REALM, "developers", "perfect")
|
||||
);
|
||||
//J+
|
||||
|
||||
when(groupDAO.getAll()).thenReturn(groups);
|
||||
|
||||
UsernamePasswordToken token = daoUser(user, "secret");
|
||||
AuthenticationInfo info = realm.getAuthenticationInfo(token);
|
||||
GroupNames groupNames = info.getPrincipals().oneByType(GroupNames.class);
|
||||
|
||||
assertNotNull(groupNames);
|
||||
assertThat(groupNames.getCollection(), hasSize(2));
|
||||
assertThat(groupNames, hasItems("scm", GroupNames.AUTHENTICATED));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleAuthentication()
|
||||
{
|
||||
User user = UserTestData.createTrillian();
|
||||
UsernamePasswordToken token = daoUser(user, "secret");
|
||||
AuthenticationInfo info = realm.getAuthenticationInfo(token);
|
||||
|
||||
assertNotNull(info);
|
||||
|
||||
PrincipalCollection collection = info.getPrincipals();
|
||||
|
||||
assertEquals(token.getUsername(), collection.getPrimaryPrincipal());
|
||||
assertThat(collection.getRealmNames(), hasSize(1));
|
||||
assertThat(collection.getRealmNames(), hasItem(DefaultRealm.REALM));
|
||||
assertEquals(user, collection.oneByType(User.class));
|
||||
|
||||
GroupNames groups = collection.oneByType(GroupNames.class);
|
||||
|
||||
assertNotNull(groups);
|
||||
assertThat(groups.getCollection(), hasSize(1));
|
||||
assertThat(groups.getCollection(), hasItem(GroupNames.AUTHENTICATED));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = UnknownAccountException.class)
|
||||
public void testUnknownAccount()
|
||||
{
|
||||
realm.getAuthenticationInfo(new UsernamePasswordToken("tricia", "secret"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWithoutUsername()
|
||||
{
|
||||
realm.getAuthenticationInfo(new UsernamePasswordToken(null, "secret"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = IncorrectCredentialsException.class)
|
||||
public void testWrongCredentials()
|
||||
{
|
||||
UsernamePasswordToken token = daoUser(UserTestData.createDent(), "secret");
|
||||
|
||||
token.setPassword("secret123".toCharArray());
|
||||
realm.getAuthenticationInfo(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testWrongToken()
|
||||
{
|
||||
realm.getAuthenticationInfo(new OtherAuthenticationToken());
|
||||
}
|
||||
|
||||
//~--- set methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
service = new DefaultPasswordService();
|
||||
|
||||
DefaultHashService hashService = new DefaultHashService();
|
||||
|
||||
// use a small number of iterations for faster test execution
|
||||
hashService.setHashIterations(512);
|
||||
service.setHashService(hashService);
|
||||
realm = new DefaultRealm(service, collector, userDAO, groupDAO);
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
* @param password
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private UsernamePasswordToken daoUser(User user, String password)
|
||||
{
|
||||
user.setPassword(service.encryptPassword(password));
|
||||
when(userDAO.get(user.getName())).thenReturn(user);
|
||||
|
||||
return new UsernamePasswordToken(user.getName(), password);
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 14/12/13
|
||||
* @author Enter your name here...
|
||||
*/
|
||||
private static class OtherAuthenticationToken implements AuthenticationToken
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
private static final long serialVersionUID = 8891352342377018022L;
|
||||
|
||||
//~--- get methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Object getCredentials()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported yet."); // To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Object getPrincipal()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not supported yet."); // To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
@Mock
|
||||
private AuthorizationCollector collector;
|
||||
|
||||
/** Field description */
|
||||
@Mock
|
||||
private GroupDAO groupDAO;
|
||||
|
||||
/** Field description */
|
||||
private DefaultRealm realm;
|
||||
|
||||
/** Field description */
|
||||
private DefaultPasswordService service;
|
||||
|
||||
/** Field description */
|
||||
@Mock
|
||||
private UserDAO userDAO;
|
||||
}
|
||||
@@ -1,627 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.apache.shiro.authc.AccountException;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.UnknownAccountException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.authz.AuthorizationInfo;
|
||||
import org.apache.shiro.authz.Permission;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import sonia.scm.cache.CacheManager;
|
||||
import sonia.scm.cache.MapCacheManager;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.group.GroupNames;
|
||||
import sonia.scm.repository.PermissionType;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryDAO;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserDAO;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.user.UserTestData;
|
||||
import sonia.scm.web.security.AuthenticationManager;
|
||||
import sonia.scm.web.security.AuthenticationResult;
|
||||
import sonia.scm.web.security.AuthenticationState;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class ScmRealmTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = UnknownAccountException.class)
|
||||
public void testAuthenticationWithUknownUser()
|
||||
{
|
||||
User trillian = createSampleUser();
|
||||
ScmRealm realm = createRealm(trillian);
|
||||
|
||||
realm.getAuthenticationInfo(token("marvin", trillian.getPassword()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthorizationAdminPermissions()
|
||||
{
|
||||
User trillian = createSampleUser();
|
||||
|
||||
trillian.setAdmin(true);
|
||||
|
||||
AuthorizationInfo ai = authorizationInfo(trillian);
|
||||
Collection<Permission> permissions = ai.getObjectPermissions();
|
||||
|
||||
assertNotNull(permissions);
|
||||
assertFalse(permissions.isEmpty());
|
||||
assertEquals(1, permissions.size());
|
||||
//J-
|
||||
assertTrue(
|
||||
permissions.contains(new RepositoryPermission("*", PermissionType.OWNER))
|
||||
);
|
||||
//J+
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthorizationAdminRoles()
|
||||
{
|
||||
User trillian = createSampleUser();
|
||||
|
||||
trillian.setAdmin(true);
|
||||
|
||||
AuthorizationInfo aci = authorizationInfo(trillian);
|
||||
Collection<String> roles = aci.getRoles();
|
||||
|
||||
assertNotNull(roles);
|
||||
assertEquals(2, roles.size());
|
||||
assertTrue(roles.contains(Role.ADMIN));
|
||||
assertTrue(roles.contains(Role.USER));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthorizationDefaultUserPermissions()
|
||||
{
|
||||
User trillian = createSampleUser();
|
||||
|
||||
AuthorizationInfo ai = authorizationInfo(trillian);
|
||||
Collection<Permission> permissions = ai.getObjectPermissions();
|
||||
|
||||
assertNotNull(permissions);
|
||||
assertTrue(permissions.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthorizationGroupPermissions()
|
||||
{
|
||||
User trillian = createSampleUser();
|
||||
|
||||
String g1 = "g1";
|
||||
String g2 = "g2";
|
||||
Group g3 = new Group("xml", "g3");
|
||||
Group g4 = new Group("xml", "g4");
|
||||
|
||||
Repository r1 = RepositoryTestData.create42Puzzle();
|
||||
|
||||
prepareRepo(r1, g1, PermissionType.READ, true);
|
||||
|
||||
Repository r2 = RepositoryTestData.createHappyVerticalPeopleTransporter();
|
||||
|
||||
prepareRepo(r2, g2, PermissionType.WRITE, true);
|
||||
|
||||
Repository r3 = RepositoryTestData.createHeartOfGold();
|
||||
|
||||
prepareRepo(r3, g3, PermissionType.OWNER);
|
||||
|
||||
Repository r4 = RepositoryTestData.createRestaurantAtTheEndOfTheUniverse();
|
||||
|
||||
Set<Repository> repositories = ImmutableSet.of(r1, r2, r3, r4);
|
||||
ScmRealm realm = createRealm(trillian, ImmutableSet.of(g1, g2),
|
||||
ImmutableSet.of(g3, g4), repositories);
|
||||
AuthenticationInfo aui = realm.getAuthenticationInfo(token(trillian));
|
||||
AuthorizationInfo aci = realm.doGetAuthorizationInfo(aui.getPrincipals());
|
||||
|
||||
Collection<Permission> permissions = aci.getObjectPermissions();
|
||||
|
||||
assertNotNull(permissions);
|
||||
assertFalse(permissions.isEmpty());
|
||||
assertEquals(3, permissions.size());
|
||||
containPermission(permissions, r1, PermissionType.READ);
|
||||
containPermission(permissions, r2, PermissionType.WRITE);
|
||||
containPermission(permissions, r3, PermissionType.OWNER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthorizationUserPermissions()
|
||||
{
|
||||
User trillian = createSampleUser();
|
||||
Repository r1 = RepositoryTestData.create42Puzzle();
|
||||
|
||||
prepareRepo(r1, trillian, PermissionType.READ);
|
||||
|
||||
Repository r2 = RepositoryTestData.createHappyVerticalPeopleTransporter();
|
||||
|
||||
prepareRepo(r2, trillian, PermissionType.WRITE);
|
||||
|
||||
Repository r3 = RepositoryTestData.createHeartOfGold();
|
||||
|
||||
prepareRepo(r3, trillian, PermissionType.OWNER);
|
||||
|
||||
Repository r4 = RepositoryTestData.createRestaurantAtTheEndOfTheUniverse();
|
||||
|
||||
Set<Repository> repositories = ImmutableSet.of(r1, r2, r3, r4);
|
||||
|
||||
ScmRealm realm = createRealm(trillian, null, null, repositories);
|
||||
AuthenticationInfo aui = realm.getAuthenticationInfo(token(trillian));
|
||||
AuthorizationInfo aci = realm.doGetAuthorizationInfo(aui.getPrincipals());
|
||||
Collection<Permission> permissions = aci.getObjectPermissions();
|
||||
|
||||
assertNotNull(permissions);
|
||||
assertFalse(permissions.isEmpty());
|
||||
assertEquals(3, permissions.size());
|
||||
containPermission(permissions, r1, PermissionType.READ);
|
||||
containPermission(permissions, r2, PermissionType.WRITE);
|
||||
containPermission(permissions, r3, PermissionType.OWNER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthorizationUserRoles()
|
||||
{
|
||||
AuthorizationInfo aci = authorizationInfo(createSampleUser());
|
||||
Collection<String> roles = aci.getRoles();
|
||||
|
||||
assertNotNull(roles);
|
||||
assertEquals(1, roles.size());
|
||||
assertEquals(Role.USER, roles.iterator().next());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test(expected = AccountException.class)
|
||||
public void testFailedAuthentication()
|
||||
{
|
||||
User trillian = createSampleUser();
|
||||
ScmRealm realm = createRealm(trillian);
|
||||
|
||||
realm.getAuthenticationInfo(token(trillian.getId(), "hobbo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testSimpleAuthentication()
|
||||
{
|
||||
User trillian = createSampleUser();
|
||||
|
||||
//J-
|
||||
ScmRealm realm = createRealm(
|
||||
trillian,
|
||||
ImmutableSet.of("g1", "g2"),
|
||||
ImmutableSet.of(new Group("xml", "g3"), new Group("xml", "g4")),
|
||||
null
|
||||
);
|
||||
//J+
|
||||
AuthenticationInfo ai = realm.getAuthenticationInfo(token(trillian));
|
||||
|
||||
assertNotNull(ai);
|
||||
|
||||
PrincipalCollection collection = ai.getPrincipals();
|
||||
|
||||
assertNotNull(collection);
|
||||
assertFalse(collection.isEmpty());
|
||||
|
||||
assertEquals(trillian.getId(), collection.getPrimaryPrincipal());
|
||||
assertEquals(trillian, collection.oneByType(User.class));
|
||||
|
||||
GroupNames groups = collection.oneByType(GroupNames.class);
|
||||
|
||||
assertNotNull(groups);
|
||||
assertFalse(groups.getCollection().isEmpty());
|
||||
assertEquals(5, groups.getCollection().size());
|
||||
//J-
|
||||
assertThat(groups,
|
||||
containsInAnyOrder("g1", "g2", "g3", "g4", GroupNames.AUTHENTICATED)
|
||||
);
|
||||
//J+
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private AuthorizationInfo authorizationInfo(User user)
|
||||
{
|
||||
ScmRealm realm = createRealm(user);
|
||||
AuthenticationInfo aui = realm.getAuthenticationInfo(token(user));
|
||||
AuthorizationInfo aci = realm.doGetAuthorizationInfo(aui.getPrincipals());
|
||||
|
||||
assertNotNull(aci);
|
||||
|
||||
return aci;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param permissions
|
||||
* @param repository
|
||||
* @param type
|
||||
*/
|
||||
private void containPermission(Collection<Permission> permissions,
|
||||
Repository repository, PermissionType type)
|
||||
{
|
||||
assertTrue(
|
||||
permissions.contains(new RepositoryPermission(repository.getId(), type)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ScmRealm createRealm(User user)
|
||||
{
|
||||
return createRealm(user, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
* @param authenticationGroups
|
||||
* @param dbGroups
|
||||
* @param repositories
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private ScmRealm createRealm(User user,
|
||||
Collection<String> authenticationGroups, Collection<Group> dbGroups,
|
||||
Collection<Repository> repositories)
|
||||
{
|
||||
UserManager userManager = mock(UserManager.class);
|
||||
GroupManager groupManager = mock(GroupManager.class);
|
||||
|
||||
if (dbGroups != null)
|
||||
{
|
||||
when(groupManager.getGroupsForMember(user.getId())).thenReturn(dbGroups);
|
||||
}
|
||||
|
||||
RepositoryDAO repositoryDAO = mock(RepositoryDAO.class);
|
||||
|
||||
if (repositories != null)
|
||||
{
|
||||
when(repositoryDAO.getAll()).thenReturn(repositories);
|
||||
}
|
||||
|
||||
UserDAO userDAO = mock(UserDAO.class);
|
||||
|
||||
when(userDAO.get(user.getId())).thenReturn(user);
|
||||
|
||||
HttpSession session = mock(HttpSession.class);
|
||||
|
||||
final HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
|
||||
when(request.getSession(true)).thenReturn(session);
|
||||
|
||||
Provider<HttpServletRequest> requestProvider =
|
||||
new Provider<HttpServletRequest>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public HttpServletRequest get()
|
||||
{
|
||||
return request;
|
||||
}
|
||||
};
|
||||
|
||||
final HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
Provider<HttpServletResponse> responseProvider =
|
||||
new Provider<HttpServletResponse>()
|
||||
{
|
||||
|
||||
@Override
|
||||
public HttpServletResponse get()
|
||||
{
|
||||
return response;
|
||||
}
|
||||
};
|
||||
|
||||
//J-
|
||||
AuthenticationManager authManager = mock(AuthenticationManager.class);
|
||||
|
||||
when(
|
||||
authManager.authenticate(
|
||||
eq(requestProvider.get()),
|
||||
eq(responseProvider.get()),
|
||||
eq(user.getId()),
|
||||
eq(user.getPassword())
|
||||
)
|
||||
).thenReturn(
|
||||
new AuthenticationResult(user, authenticationGroups, AuthenticationState.SUCCESS)
|
||||
);
|
||||
|
||||
when(
|
||||
authManager.authenticate(
|
||||
eq(requestProvider.get()),
|
||||
eq(responseProvider.get()),
|
||||
eq(user.getId()),
|
||||
argThat(
|
||||
not(user.getPassword())
|
||||
)
|
||||
)
|
||||
).thenReturn(
|
||||
AuthenticationResult.FAILED
|
||||
);
|
||||
|
||||
when(
|
||||
authManager.authenticate(
|
||||
eq(requestProvider.get()),
|
||||
eq(responseProvider.get()),
|
||||
argThat(
|
||||
not(user.getName())
|
||||
),
|
||||
anyString()
|
||||
)
|
||||
).thenReturn(
|
||||
AuthenticationResult.NOT_FOUND
|
||||
);
|
||||
|
||||
SecuritySystem securitySystem = mock(SecuritySystem.class);
|
||||
when(
|
||||
securitySystem.getPermissions(Mockito.any(Predicate.class))
|
||||
).thenReturn(
|
||||
Collections.EMPTY_LIST
|
||||
);
|
||||
|
||||
CacheManager cacheManager = new MapCacheManager();
|
||||
|
||||
AuthorizationCollector collector = new AuthorizationCollector(
|
||||
cacheManager,
|
||||
repositoryDAO,
|
||||
securitySystem,
|
||||
new RepositoryPermissionResolver()
|
||||
);
|
||||
|
||||
LoginAttemptHandler dummyLoginAttemptHandler = new LoginAttemptHandler()
|
||||
{
|
||||
@Override
|
||||
public void beforeAuthentication(AuthenticationToken token)
|
||||
throws AuthenticationException {}
|
||||
|
||||
@Override
|
||||
public void onSuccessfulAuthentication(AuthenticationToken token,
|
||||
AuthenticationResult result) throws AuthenticationException {}
|
||||
|
||||
@Override
|
||||
public void onUnsuccessfulAuthentication(AuthenticationToken token,
|
||||
AuthenticationResult result) throws AuthenticationException {}
|
||||
};
|
||||
|
||||
return new ScmRealm(
|
||||
new ScmConfiguration(),
|
||||
dummyLoginAttemptHandler,
|
||||
collector,
|
||||
// cacheManager,
|
||||
userManager,
|
||||
groupManager,
|
||||
userDAO,
|
||||
authManager,
|
||||
null,
|
||||
requestProvider,
|
||||
responseProvider
|
||||
);
|
||||
//J+
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private User createSampleUser()
|
||||
{
|
||||
User trillian = UserTestData.createTrillian();
|
||||
|
||||
trillian.setPassword("moppo123");
|
||||
|
||||
return trillian;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private String id()
|
||||
{
|
||||
return String.valueOf(counter.incrementAndGet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param user
|
||||
* @param type
|
||||
*/
|
||||
private void prepareRepo(Repository repository, User user,
|
||||
PermissionType type)
|
||||
{
|
||||
prepareRepo(repository, user.getId(), type, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param group
|
||||
* @param type
|
||||
*/
|
||||
private void prepareRepo(Repository repository, Group group,
|
||||
PermissionType type)
|
||||
{
|
||||
prepareRepo(repository, group.getId(), type, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param repository
|
||||
* @param name
|
||||
* @param type
|
||||
* @param groupPermission
|
||||
*/
|
||||
private void prepareRepo(Repository repository, String name,
|
||||
PermissionType type, boolean groupPermission)
|
||||
{
|
||||
repository.setId(id());
|
||||
|
||||
List<sonia.scm.repository.Permission> permissions =
|
||||
ImmutableList.of(new sonia.scm.repository.Permission(name, type,
|
||||
groupPermission));
|
||||
|
||||
repository.setPermissions(permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private AuthenticationToken token(User user)
|
||||
{
|
||||
return new UsernamePasswordToken(user.getId(), user.getPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param username
|
||||
* @param password
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private AuthenticationToken token(String username, String password)
|
||||
{
|
||||
return new UsernamePasswordToken(username, password);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private AtomicLong counter = new AtomicLong();
|
||||
}
|
||||
@@ -1,384 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import sonia.scm.AbstractTestBase;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.cache.MapCacheManager;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.security.MessageDigestEncryptionHandler;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.user.UserTestData;
|
||||
import sonia.scm.util.MockUtil;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class ChainAuthenticationManagerTest extends AbstractTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateFailed()
|
||||
{
|
||||
manager = createManager();
|
||||
|
||||
AuthenticationResult result = manager.authenticate(request, response,
|
||||
trillian.getName(), "trillian");
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateNotFound()
|
||||
{
|
||||
manager = createManager();
|
||||
|
||||
AuthenticationResult result = manager.authenticate(request, response,
|
||||
"dent", "trillian");
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateSuccess()
|
||||
{
|
||||
manager = createManager();
|
||||
|
||||
AuthenticationResult result = manager.authenticate(request, response,
|
||||
trillian.getName(), "trillian123");
|
||||
|
||||
assertNotNull(result);
|
||||
assertUserEquals(trillian, result.getUser());
|
||||
assertEquals("trilliansType", result.getUser().getType());
|
||||
result = manager.authenticate(request, response, perfect.getName(),
|
||||
"perfect123");
|
||||
assertNotNull(perfect);
|
||||
assertUserEquals(perfect, result.getUser());
|
||||
assertEquals("perfectsType", result.getUser().getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticationOrder()
|
||||
{
|
||||
User trillian = UserTestData.createTrillian();
|
||||
|
||||
trillian.setPassword("trillian123");
|
||||
|
||||
SingleUserAuthenticaionHandler a1 =
|
||||
new SingleUserAuthenticaionHandler("a1", trillian);
|
||||
SingleUserAuthenticaionHandler a2 =
|
||||
new SingleUserAuthenticaionHandler("a2", trillian);
|
||||
|
||||
manager = createManager("a2", false, a1, a2);
|
||||
|
||||
AuthenticationResult result = manager.authenticate(request, response,
|
||||
trillian.getName(), "trillian123");
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals(AuthenticationState.SUCCESS, result.getState());
|
||||
assertEquals("a2", result.getUser().getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testStopChain()
|
||||
{
|
||||
ChainAuthenticatonManager cam = createManager("", false);
|
||||
|
||||
assertTrue(cam.stopChain(new AuthenticationResult(perfect)));
|
||||
assertTrue(cam.stopChain(AuthenticationResult.FAILED));
|
||||
assertFalse(cam.stopChain(AuthenticationResult.NOT_FOUND));
|
||||
cam = createManager("", true);
|
||||
assertTrue(cam.stopChain(new AuthenticationResult(perfect)));
|
||||
assertFalse(cam.stopChain(AuthenticationResult.FAILED));
|
||||
assertFalse(cam.stopChain(AuthenticationResult.NOT_FOUND));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected void postSetUp() throws Exception
|
||||
{
|
||||
request = MockUtil.getHttpServletRequest();
|
||||
response = MockUtil.getHttpServletResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected void preTearDown() throws Exception
|
||||
{
|
||||
manager.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param user
|
||||
* @param other
|
||||
*/
|
||||
private void assertUserEquals(User user, User other)
|
||||
{
|
||||
assertEquals(user.getName(), other.getName());
|
||||
assertEquals(user.getDisplayName(), other.getDisplayName());
|
||||
assertEquals(user.getMail(), other.getMail());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ChainAuthenticatonManager createManager()
|
||||
{
|
||||
perfect = UserTestData.createPerfect();
|
||||
perfect.setPassword("perfect123");
|
||||
trillian = UserTestData.createTrillian();
|
||||
trillian.setPassword("trillian123");
|
||||
|
||||
return createManager("", false,
|
||||
new SingleUserAuthenticaionHandler("perfectsType", perfect),
|
||||
new SingleUserAuthenticaionHandler("trilliansType", trillian));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param defaultType
|
||||
* @param skipFailedAuthenticators
|
||||
* @param handlers
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ChainAuthenticatonManager createManager(String defaultType,
|
||||
boolean skipFailedAuthenticators, AuthenticationHandler... handlers)
|
||||
{
|
||||
if ( handlers == null || handlers.length == 0 ){
|
||||
//J-
|
||||
handlers = new AuthenticationHandler[]{
|
||||
new SingleUserAuthenticaionHandler("perfectsType", perfect),
|
||||
new SingleUserAuthenticaionHandler("trilliansType", trillian)
|
||||
};
|
||||
//J+
|
||||
}
|
||||
ScmConfiguration configuration = new ScmConfiguration();
|
||||
|
||||
configuration.setSkipFailedAuthenticators(skipFailedAuthenticators);
|
||||
|
||||
Set<AuthenticationHandler> handlerSet = ImmutableSet.copyOf(handlers);
|
||||
|
||||
UserManager userManager = mock(UserManager.class);
|
||||
|
||||
when(userManager.getDefaultType()).thenReturn(defaultType);
|
||||
manager = new ChainAuthenticatonManager(configuration, userManager,
|
||||
handlerSet, new MessageDigestEncryptionHandler(), new MapCacheManager());
|
||||
manager.init(contextProvider);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
//~--- inner classes --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class description
|
||||
*
|
||||
*
|
||||
* @version Enter version here..., 2010-12-07
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
private static class SingleUserAuthenticaionHandler
|
||||
implements AuthenticationHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param type
|
||||
* @param user
|
||||
*/
|
||||
public SingleUserAuthenticaionHandler(String type, User user)
|
||||
{
|
||||
this.type = type;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
//~--- methods ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param username
|
||||
* @param password
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public AuthenticationResult authenticate(HttpServletRequest request,
|
||||
HttpServletResponse response, String username, String password)
|
||||
{
|
||||
AuthenticationResult result = null;
|
||||
|
||||
if (username.equals(user.getName()))
|
||||
{
|
||||
if (password.equals(user.getPassword()))
|
||||
{
|
||||
result = new AuthenticationResult(user.clone());
|
||||
}
|
||||
else
|
||||
{
|
||||
result = AuthenticationResult.FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = AuthenticationResult.NOT_FOUND;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
@Override
|
||||
public void init(SCMContextProvider context) {}
|
||||
|
||||
//~--- get methods --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
//~--- fields -------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private final String type;
|
||||
|
||||
/** Field description */
|
||||
private final User user;
|
||||
}
|
||||
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private ChainAuthenticatonManager manager;
|
||||
|
||||
/** Field description */
|
||||
private User perfect;
|
||||
|
||||
/** Field description */
|
||||
private HttpServletRequest request;
|
||||
|
||||
/** Field description */
|
||||
private HttpServletResponse response;
|
||||
|
||||
/** Field description */
|
||||
private User trillian;
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.web.security;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import sonia.scm.AbstractTestBase;
|
||||
import sonia.scm.security.EncryptionHandler;
|
||||
import sonia.scm.security.MessageDigestEncryptionHandler;
|
||||
import sonia.scm.store.JAXBStoreFactory;
|
||||
import sonia.scm.store.StoreFactory;
|
||||
import sonia.scm.user.DefaultUserManager;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserTestData;
|
||||
import sonia.scm.user.xml.XmlUserDAO;
|
||||
import sonia.scm.util.MockUtil;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class DefaultAuthenticationHandlerTest extends AbstractTestBase
|
||||
{
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateFailed()
|
||||
{
|
||||
AuthenticationResult result = handler.authenticate(request, reponse,
|
||||
slarti.getName(), "otherPWD");
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getState() == AuthenticationState.FAILED);
|
||||
assertNull(result.getUser());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateNotFound()
|
||||
{
|
||||
AuthenticationResult result = handler.authenticate(request, reponse,
|
||||
"notSlarti", "otherPWD");
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getState() == AuthenticationState.NOT_FOUND);
|
||||
assertNull(result.getUser());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateSuccess()
|
||||
{
|
||||
AuthenticationResult result = handler.authenticate(request, reponse,
|
||||
slarti.getName(), "slartisPWD");
|
||||
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getState() == AuthenticationState.SUCCESS);
|
||||
assertNotNull(result.getUser());
|
||||
assertEquals(slarti.getName(), result.getUser().getName());
|
||||
assertEquals(slarti.getDisplayName(), result.getUser().getDisplayName());
|
||||
assertEquals(slarti.getMail(), result.getUser().getMail());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected void postSetUp() throws Exception
|
||||
{
|
||||
EncryptionHandler enc = new MessageDigestEncryptionHandler();
|
||||
|
||||
slarti = UserTestData.createSlarti();
|
||||
slarti.setPassword(enc.encrypt("slartisPWD"));
|
||||
|
||||
StoreFactory storeFactory = new JAXBStoreFactory();
|
||||
|
||||
storeFactory.init(contextProvider);
|
||||
|
||||
XmlUserDAO userDAO = new XmlUserDAO(storeFactory);
|
||||
|
||||
setSubject(MockUtil.createAdminSubject());
|
||||
|
||||
DefaultUserManager userManager = new DefaultUserManager(userDAO);
|
||||
|
||||
userManager.init(contextProvider);
|
||||
userManager.create(slarti);
|
||||
clearSubject();
|
||||
|
||||
handler = new DefaultAuthenticationHandler(userManager, enc);
|
||||
handler.init(contextProvider);
|
||||
request = MockUtil.getHttpServletRequest();
|
||||
reponse = MockUtil.getHttpServletResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected void preTearDown() throws Exception
|
||||
{
|
||||
handler.close();
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
private DefaultAuthenticationHandler handler;
|
||||
|
||||
/** Field description */
|
||||
private HttpServletResponse reponse;
|
||||
|
||||
/** Field description */
|
||||
private HttpServletRequest request;
|
||||
|
||||
/** Field description */
|
||||
private User slarti;
|
||||
}
|
||||
Reference in New Issue
Block a user