/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////
package org.projectforge.user;
import junit.framework.Assert;
import org.junit.Test;
public class LoginProtectionTest
{
private static final long DURATION_48_HOURS = 48 * 60 * 60 * 1000;
private static final long DURATION_4_HOURS = 4 * 60 * 60 * 1000;
@Test
public void testLoginProtection() throws InterruptedException
{
final long current = System.currentTimeMillis();
final LoginProtectionMap lp = LoginProtection.instance().getMapByUserId();
lp.clearAll();
Assert.assertEquals("Maps should be empty.", 0, lp.getSizeOfLastFailedLoginMap());
Assert.assertEquals("Maps should be empty.", 0, lp.getSizeOfLoginFailedAttemptsMap());
lp.incrementFailedLoginTimeOffset("kai");
lp.incrementFailedLoginTimeOffset("kai");
lp.incrementFailedLoginTimeOffset("kai");
Assert.assertTrue("Time offset due to 3 failed logins expected.", lp.getFailedLoginTimeOffsetIfExists("kai") > 0);
Assert.assertTrue("Time offset due to 3 failed logins not more than 3 seconds expected.",
lp.getFailedLoginTimeOffsetIfExists("kai") < 3001);
Assert.assertEquals("No offset for new user 'horst' expected.", 0, (int) lp.getFailedLoginTimeOffsetIfExists("horst"));
lp.setEntry("horst", 10, current - DURATION_48_HOURS); // Expired.
lp.incrementFailedLoginTimeOffset("kai"); // 10 failed login attempts should be deleted now:
Assert.assertEquals("Penalty for 'horst' should be deleted, because it's expired.", 1, lp.getSizeOfLastFailedLoginMap());
Assert.assertEquals("Penalty for 'horst' should be deleted, because it's expired.", 1, lp.getSizeOfLoginFailedAttemptsMap());
Assert.assertEquals("Penalty for 'horst' should be deleted, because it's expired.", 0, lp.getNumberOfFailedLoginAttempts("horst"));
Assert.assertEquals("Penalty for 'horst' should be deleted, because it's expired.", 0,
(int) lp.getFailedLoginTimeOffsetIfExists("horst"));
lp.setEntry("horst", 10, current - DURATION_4_HOURS); // Not expired.
lp.incrementFailedLoginTimeOffset("kai");
Assert.assertEquals("No time offset for 'horst' expected because last login was 4 hours ago.", 0,
(int) lp.getFailedLoginTimeOffsetIfExists("horst"));
lp.incrementFailedLoginTimeOffset("horst");
Assert.assertEquals("11 failed login attempts expected.", 11, lp.getNumberOfFailedLoginAttempts("horst"));
Assert.assertTrue("Time offset due to 11 failed logins expected.", lp.getFailedLoginTimeOffsetIfExists("horst") > 0);
Assert.assertTrue("Time offset due to 11 failed logins not more than 11 seconds expected.",
lp.getFailedLoginTimeOffsetIfExists("horst") < 11001);
lp.clearLoginTimeOffset("horst");
Assert.assertEquals("Penalty for 'horst' should be deleted.", 0, (int) lp.getFailedLoginTimeOffsetIfExists("horst"));
lp.incrementFailedLoginTimeOffset("horst");
final long offset = lp.getFailedLoginTimeOffsetIfExists("horst");
Assert.assertTrue("Time offset between 0 and 1 second expected due to 1 failed login attempt.", offset > 0 && offset < 1001);
Thread.sleep(offset + 1);
Assert.assertEquals("No time offset for 'horst' expected, because time offest was run down.", 0,
(int) lp.getFailedLoginTimeOffsetIfExists("horst"));
}
@Test
public void testLoginProtectionByIp() throws InterruptedException
{
final LoginProtection lp = LoginProtection.instance();
lp.clearAll();
Assert.assertEquals("Maps should be empty.", 0, lp.getMapByIpAddress().getSizeOfLastFailedLoginMap());
Assert.assertEquals("Maps should be empty.", 0, lp.getMapByIpAddress().getSizeOfLoginFailedAttemptsMap());
final String ip = "192.168.76.1";
for (int i = 0; i < 3001; i++) {
lp.incrementFailedLoginTimeOffset(String.valueOf(i), ip);
}
Assert.assertTrue("Time offset due to 3 failed logins expected.", lp.getFailedLoginTimeOffsetIfExists("kai", ip) > 0);
Assert.assertTrue("Time offset due to 3 failed logins not more than 3 seconds expected.",
lp.getFailedLoginTimeOffsetIfExists("kai", ip) < 3001);
Assert.assertEquals("No offset for new ip address expected.", 0, (int) lp.getFailedLoginTimeOffsetIfExists("horst", "192.168.76.2"));
}
}