package org.apereo.cas.web.support;
import org.apache.http.HttpStatus;
import org.apereo.cas.config.CasCoreUtilConfiguration;
import org.apereo.cas.web.support.config.CasThrottlingConfiguration;
import org.apereo.inspektr.common.web.ClientInfo;
import org.apereo.inspektr.common.web.ClientInfoHolder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.*;
/**
* Base class for submission throttle tests.
*
* @author Marvin S. Addison
* @since 3.0.0
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {RefreshAutoConfiguration.class,
CasCoreUtilConfiguration.class,
AopAutoConfiguration.class,
CasThrottlingConfiguration.class})
@EnableAspectJAutoProxy(proxyTargetClass = true)
@TestPropertySource(properties = "spring.aop.proxy-target-class=true")
@EnableScheduling
public abstract class AbstractThrottledSubmissionHandlerInterceptorAdapterTests {
protected static final String IP_ADDRESS = "1.2.3.4";
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractThrottledSubmissionHandlerInterceptorAdapterTests.class);
@Autowired
@Qualifier("authenticationThrottle")
protected ThrottledSubmissionHandlerInterceptor throttle;
@Before
public void setUp() throws Exception {
final MockHttpServletRequest request = new MockHttpServletRequest();
request.setRemoteAddr(IP_ADDRESS);
request.setLocalAddr(IP_ADDRESS);
ClientInfoHolder.setClientInfo(new ClientInfo(request));
}
@After
public void tearDown() throws Exception {
ClientInfoHolder.setClientInfo(null);
}
@Test
public void verifyThrottle() throws Exception {
// Ensure that repeated logins BELOW threshold rate are allowed
failLoop(3, 1000, HttpStatus.SC_UNAUTHORIZED);
// Ensure that repeated logins ABOVE threshold rate are throttled
failLoop(3, 200, HttpStatus.SC_FORBIDDEN);
// Ensure that slowing down relieves throttle
throttle.decrement();
Thread.sleep(1000);
failLoop(3, 1000, HttpStatus.SC_UNAUTHORIZED);
}
private void failLoop(final int trials, final int period, final int expected) throws Exception {
// Seed with something to compare against
loginUnsuccessfully("mog", "1.2.3.4");
for (int i = 0; i < trials; i++) {
LOGGER.debug("Waiting for [{}] ms", period);
Thread.sleep(period);
final MockHttpServletResponse status = loginUnsuccessfully("mog", "1.2.3.4");
assertEquals(expected, status.getStatus());
}
}
protected abstract MockHttpServletResponse loginUnsuccessfully(String username, String fromAddress) throws Exception;
}