From 8718cc38f66e713901276b93bd3207e875516c95 Mon Sep 17 00:00:00 2001 From: Scott Battaglia Date: Mon, 14 Sep 2009 14:21:09 +0000 Subject: [PATCH] NOJIRA tag for 3.1.8 --- cas-client-core/pom.xml | 2 +- .../authentication/AuthenticationFilter.java | 59 +++--- .../client/session/SingleSignOutFilter.java | 4 +- .../util/AbstractConfigurationFilter.java | 6 +- .../jasig/cas/client/util/CommonUtils.java | 27 ++- .../cas/client/util/DelegatingFilter.java | 4 +- .../AbstractTicketValidationFilter.java | 2 +- ...0ProxyReceivingTicketValidationFilter.java | 18 +- .../cas/client/validation/ProxyList.java | 9 + .../validation/Saml11TicketValidator.java | 10 +- .../cas/client/proxy/CleanUpListenerTest.java | 125 ------------- .../cas/client/util/CommonUtilsTests.java | 16 ++ ...xyReceivingTicketValidationFilterTest.java | 34 ---- ...yReceivingTicketValidationFilterTests.java | 176 ++++++++++++++++++ cas-client-integration-atlassian/pom.xml | 6 +- .../atlassian/ConfluenceCasAuthenticator.java | 50 +++-- .../atlassian/JiraCasAuthenticator.java | 47 +++-- pom.xml | 2 +- 18 files changed, 360 insertions(+), 237 deletions(-) delete mode 100644 cas-client-core/src/test/java/org/jasig/cas/client/proxy/CleanUpListenerTest.java delete mode 100644 cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilterTest.java create mode 100644 cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilterTests.java diff --git a/cas-client-core/pom.xml b/cas-client-core/pom.xml index eb28d0e..bdc4d34 100644 --- a/cas-client-core/pom.xml +++ b/cas-client-core/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> org.jasig.cas - 3.1.5 + 3.1.8 cas-client 4.0.0 diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationFilter.java index b265769..9b546f0 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationFilter.java @@ -87,38 +87,43 @@ public class AuthenticationFilter extends AbstractCasFilter { final HttpServletRequest request = (HttpServletRequest) servletRequest; final HttpServletResponse response = (HttpServletResponse) servletResponse; final HttpSession session = request.getSession(false); - final String ticket = request.getParameter(getArtifactParameterName()); final String serviceUrl = constructServiceUrl(request, response); - final Assertion assertion = session != null ? (Assertion) session - .getAttribute(CONST_CAS_ASSERTION) : null; - final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl); + final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null; - if (CommonUtils.isBlank(ticket) && assertion == null && !wasGatewayed) { - final String modifiedServiceUrl; - - log.debug("no ticket and no assertion found"); - if (this.gateway) { - log.debug("setting gateway attribute in session"); - modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl); - } else { - modifiedServiceUrl = serviceUrl; - } - - if (log.isDebugEnabled()) { - log.debug("Constructed service url: " + modifiedServiceUrl); - } - - final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway); - - if (log.isDebugEnabled()) { - log.debug("redirecting to \"" + urlToRedirectTo + "\""); - } - - response.sendRedirect(urlToRedirectTo); + if (assertion != null) { + filterChain.doFilter(request, response); return; } - filterChain.doFilter(request, response); + final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName()); + final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl); + + if (CommonUtils.isNotBlank(ticket) || wasGatewayed) { + filterChain.doFilter(request, response); + return; + } + + final String modifiedServiceUrl; + + log.debug("no ticket and no assertion found"); + if (this.gateway) { + log.debug("setting gateway attribute in session"); + modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl); + } else { + modifiedServiceUrl = serviceUrl; + } + + if (log.isDebugEnabled()) { + log.debug("Constructed service url: " + modifiedServiceUrl); + } + + final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway); + + if (log.isDebugEnabled()) { + log.debug("redirecting to \"" + urlToRedirectTo + "\""); + } + + response.sendRedirect(urlToRedirectTo); } public final void setRenew(final boolean renew) { diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java index 951aebf..5c6cf7c 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java @@ -57,7 +57,7 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter { final HttpServletRequest request = (HttpServletRequest) servletRequest; if ("POST".equals(request.getMethod())) { - final String logoutRequest = request.getParameter("logoutRequest"); + final String logoutRequest = CommonUtils.safeGetParameter(request, "logoutRequest"); if (CommonUtils.isNotBlank(logoutRequest)) { @@ -87,7 +87,7 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter { } } } else { - final String artifact = request.getParameter(this.artifactParameterName); + final String artifact = CommonUtils.safeGetParameter(request, this.artifactParameterName); final HttpSession session = request.getSession(); if (log.isDebugEnabled() && session != null) { diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java index 9c359f8..4f9eb94 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java @@ -38,12 +38,14 @@ public abstract class AbstractConfigurationFilter implements Filter { final String value = filterConfig.getInitParameter(propertyName); if (CommonUtils.isNotBlank(value)) { + log.info("Property [" + propertyName + "] loaded from FilterConfig.getInitParameter with value [" + value + "]"); return value; } final String value2 = filterConfig.getServletContext().getInitParameter(propertyName); if (CommonUtils.isNotBlank(value2)) { + log.info("Property [" + propertyName + "] loaded from ServletContext.getInitParameter with value [" + value2 + "]"); return value2; } InitialContext context = null; @@ -59,15 +61,18 @@ public abstract class AbstractConfigurationFilter implements Filter { final String value3 = loadFromContext(context, "java:comp/env/cas/" + shortName + "/" + propertyName); if (CommonUtils.isNotBlank(value3)) { + log.info("Property [" + propertyName + "] loaded from JNDI Filter Specific Property with value [" + value3 + "]"); return value3; } final String value4 = loadFromContext(context, "java:comp/env/cas/" + propertyName); if (CommonUtils.isNotBlank(value4)) { + log.info("Property [" + propertyName + "] loaded from JNDI with value [" + value3 + "]"); return value4; } + log.info("Property [" + propertyName + "] not found. Using default value [" + defaultValue + "]"); return defaultValue; } @@ -79,7 +84,6 @@ public abstract class AbstractConfigurationFilter implements Filter { try { return (String) context.lookup(path); } catch (final NamingException e) { - log.warn("No value found in context for: '" + path + "'; Returning null."); return null; } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java index b8e4a62..5b7598d 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java @@ -11,6 +11,7 @@ import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletRequest; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -138,7 +139,7 @@ public final class CommonUtils { */ public static final String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName, final String serviceUrl, final boolean renew, final boolean gateway) { try { - return casServerLoginUrl + "?" + serviceParameterName + "=" + return casServerLoginUrl + (casServerLoginUrl.indexOf("?") != -1 ? "&" : "?") + serviceParameterName + "=" + URLEncoder.encode(serviceUrl, "UTF-8") + (renew ? "&renew=true" : "") + (gateway ? "&gateway=true" : ""); @@ -147,7 +148,7 @@ public final class CommonUtils { } } - public static final void readAndRespondToProxyReceptorRequest(final HttpServletRequest request, final HttpServletResponse response, final ProxyGrantingTicketStorage proxyGrantingTicketStorage) throws IOException { + public static void readAndRespondToProxyReceptorRequest(final HttpServletRequest request, final HttpServletResponse response, final ProxyGrantingTicketStorage proxyGrantingTicketStorage) throws IOException { final String proxyGrantingTicketIou = request .getParameter(PARAM_PROXY_GRANTING_TICKET_IOU); @@ -182,7 +183,7 @@ public final class CommonUtils { * @param response the HttpServletResponse * @return the service url to use. */ - public static final String constructServiceUrl(final HttpServletRequest request, + public static String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response, final String service, final String serverName, final String artifactParameterName, final boolean encode) { if (CommonUtils.isNotBlank(service)) { return encode ? response.encodeURL(service) : service; @@ -236,4 +237,24 @@ public final class CommonUtils { return returnValue; } + /** + * Safe method for retrieving a parameter from the request without disrupting the reader UNLESS the parameter + * actually exists in the query string. + *

+ * Note, this does not work for POST Requests for "logoutRequest". It works for all other CAS POST requests because the + * parameter is ALWAYS in the GET request. + *

+ * If we see the "logoutRequest" parameter we MUST treat it as if calling the standard request.getParameter. + * + * @param request the request to check. + * @param parameter the parameter to look for. + * @return the value of the parameter. + */ + public static String safeGetParameter(final HttpServletRequest request, final String parameter) { + if ("POST".equals(request.getMethod()) && "logoutRequest".equals(parameter)) { + LOG.warn("safeGetParameter called on a POST HttpServletRequest for LogoutRequest. Cannot complete check safely. Reverting to standard behavior for this Parameter"); + return request.getParameter(parameter); + } + return request.getQueryString() == null || request.getQueryString().indexOf(parameter) == -1 ? null : request.getParameter(parameter); + } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/DelegatingFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/DelegatingFilter.java index 28eb08f..55f22e3 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/util/DelegatingFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/DelegatingFilter.java @@ -14,6 +14,7 @@ import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Iterator; import java.util.Map; @@ -89,8 +90,7 @@ public final class DelegatingFilter implements Filter { final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException { - final String parameter = request - .getParameter(this.requestParameterName); + final String parameter = CommonUtils.safeGetParameter((HttpServletRequest) request, this.requestParameterName); if (CommonUtils.isNotEmpty(parameter)) { for (final Iterator iter = this.delegators.keySet().iterator(); iter diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java index b285b72..26e284b 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java @@ -121,7 +121,7 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter { final HttpServletRequest request = (HttpServletRequest) servletRequest; final HttpServletResponse response = (HttpServletResponse) servletResponse; - final String ticket = request.getParameter(getArtifactParameterName()); + final String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName()); if (CommonUtils.isNotBlank(ticket)) { if (log.isDebugEnabled()) { diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java index 3bc7a72..61d3742 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java @@ -91,7 +91,7 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal if (CommonUtils.isNotBlank(allowAnyProxy) || CommonUtils.isNotBlank(allowedProxyChains)) { final Cas20ProxyTicketValidator v = new Cas20ProxyTicketValidator(casServerUrlPrefix); v.setAcceptAnyProxy(parseBoolean(allowAnyProxy)); - v.setAllowedProxyChains(new ProxyList(constructListOfProxies(allowedProxyChains))); + v.setAllowedProxyChains(createProxyList(allowedProxyChains)); validator = v; } else { validator = new Cas20ServiceTicketValidator(casServerUrlPrefix); @@ -117,17 +117,15 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal return validator; } - protected final List constructListOfProxies(final String proxies) { + protected final ProxyList createProxyList(final String proxies) { if (CommonUtils.isBlank(proxies)) { - return new ArrayList(); + return new ProxyList(); } - final String[] splitProxies = proxies.split("\n"); - final List items = Arrays.asList(splitProxies); final ProxyListEditor editor = new ProxyListEditor(); - editor.setValue(items); - return (List) editor.getValue(); - } + editor.setAsText(proxies); + return (ProxyList) editor.getValue(); + } public void destroy() { super.destroy(); @@ -166,4 +164,8 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal public void setTimerTask(final TimerTask timerTask) { this.timerTask = timerTask; } + + public void setMillisBetweenCleanUps(final int millisBetweenCleanUps) { + this.millisBetweenCleanUps = millisBetweenCleanUps; + } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java index 107b042..0105713 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/ProxyList.java @@ -5,6 +5,8 @@ */ package org.jasig.cas.client.validation; +import org.jasig.cas.client.util.CommonUtils; + import java.util.ArrayList; import java.util.List; import java.util.Iterator; @@ -22,6 +24,13 @@ public final class ProxyList { private final List proxyChains; public ProxyList(final List proxyChains) { + CommonUtils.assertNotNull(proxyChains, "List of proxy chains cannot be null."); + + // Assert that all entries in the list are String[] + for (final Iterator iter = proxyChains.iterator(); iter.hasNext();) { + CommonUtils.assertTrue(iter.next() instanceof String[], "Proxy chains must contain String[] items exclusively."); + } + this.proxyChains = proxyChains; } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidator.java index b707b88..6c40ba3 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Saml11TicketValidator.java @@ -13,6 +13,8 @@ import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.*; +import java.text.DateFormat; +import java.text.SimpleDateFormat; /** * TicketValidator that can understand validating a SAML artifact. This includes the SOAP request/response. @@ -158,8 +160,14 @@ public final class Saml11TicketValidator extends AbstractUrlBasedTicketValidator return list; } + private static String getFormattedDateAndTime(final Date date) { + final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + return dateFormat.format(date); + } + + protected String retrieveResponseFromServer(final URL validationUrl, final String ticket) { - final String MESSAGE_TO_SEND = "" + final String MESSAGE_TO_SEND = "" + "" + ticket + ""; diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/proxy/CleanUpListenerTest.java b/cas-client-core/src/test/java/org/jasig/cas/client/proxy/CleanUpListenerTest.java deleted file mode 100644 index 95b57bd..0000000 --- a/cas-client-core/src/test/java/org/jasig/cas/client/proxy/CleanUpListenerTest.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.jasig.cas.client.proxy; - -import java.util.Timer; -import java.util.TimerTask; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; - -import junit.framework.TestCase; - -import org.jasig.cas.client.util.MethodFlag; -import org.springframework.mock.web.MockServletContext; - -/** - * Unit test for {@link CleanUpListener} - * - * @author Brad Cupit (brad [at] lsu {dot} edu) - */ -public class CleanUpListenerTest extends TestCase { - private final Timer defaultTimer = new Timer(true); - /* - private final CleanUpTimerTask defaultTimerTask = new CleanUpTimerTask(); - - - public void testStartsThreadAtStartup() throws Exception { - final MethodFlag scheduleMethodFlag = new MethodFlag(); - - final Timer timer = new Timer(true) { - public void schedule(TimerTask task, long delay, long period) { - scheduleMethodFlag.setCalled(); - } - }; - - final CleanUpListener cleanUpListener = new CleanUpListener(timer, defaultTimerTask); - cleanUpListener.contextInitialized(new TestServletContextEvent(1)); - - assertTrue(scheduleMethodFlag.wasCalled()); - } - - public void testShutsDownTimerThread() throws Exception { - final MethodFlag cancelMethodFlag = new MethodFlag(); - - final Timer timer = new Timer(true) { - public void cancel() { - cancelMethodFlag.setCalled(); - super.cancel(); - } - }; - - final CleanUpListener cleanUpListener = new CleanUpListener(timer, defaultTimerTask); - cleanUpListener.contextInitialized(new TestServletContextEvent(1)); - cleanUpListener.contextDestroyed(null); - - assertTrue(cancelMethodFlag.wasCalled()); - } - - public void testCallsCleanAllOnSchedule() throws Exception { - final MethodFlag timerTaskFlag = new MethodFlag(); - - final TimerTask timerTask = new TimerTask() { - public void run() { - timerTaskFlag.setCalled(); - } - }; - - long millisBetweenCleanUps = 250; - - final CleanUpListener cleanUpListener = new CleanUpListener(defaultTimer, timerTask); - cleanUpListener.contextInitialized(new TestServletContextEvent(millisBetweenCleanUps)); - - // wait long enough for the clean up to occur - Thread.sleep(millisBetweenCleanUps * 2); - - assertTrue(timerTaskFlag.wasCalled()); - } - - public void testDelaysFirstCleanAll() throws Exception { - final MethodFlag timerTaskFlag = new MethodFlag(); - - final TimerTask timerTask = new TimerTask() { - public void run() { - timerTaskFlag.setCalled(); - } - }; - - long millisBetweenCleanUps = 250; - - final CleanUpListener cleanUpListener = new CleanUpListener(defaultTimer, timerTask); - cleanUpListener.contextInitialized(new TestServletContextEvent(millisBetweenCleanUps)); - - assertFalse(timerTaskFlag.wasCalled()); - - // wait long enough for the clean up to occur - Thread.sleep(millisBetweenCleanUps * 2); - - assertTrue(timerTaskFlag.wasCalled()); - } - - public void testReturnsDefaultWhenNoContextParamConfigured() throws Exception { - final ServletContext servletContext = new MockServletContext(); - - long millisBetweenCleanups = new CleanUpListener().getMillisBetweenCleanups(servletContext); - assertEquals(CleanUpListener.DEFAULT_MILLIS_BETWEEN_CLEANUPS, millisBetweenCleanups); - } - - public void testFailsWithInvalidNumber() throws Exception { - final ServletContext servletContext = new MockServletContext() { - public String getInitParameter(String name) { - if (name.equals(CleanUpListener.MILLIS_BETWEEN_CLEANUPS_INIT_PARAM)) { - return "not a number"; - } else { - return null; - } - } - }; - - try { - new CleanUpListener().getMillisBetweenCleanups(servletContext); - fail("expected an exception"); - } catch (RuntimeException e) { - // expected, test passes - } - } - */ -} diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/util/CommonUtilsTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/util/CommonUtilsTests.java index a75abc2..99cb6e2 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/util/CommonUtilsTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/util/CommonUtilsTests.java @@ -19,6 +19,22 @@ import java.util.Collection; */ public final class CommonUtilsTests extends TestCase { + public void testRedirectUrlWithParam() { + final String loginUrl = "http://localhost:8080/login?myName=foo"; + final String fullyConstructedUrl = CommonUtils.constructRedirectUrl(loginUrl, "foo", "foo", false, false); + + int count = 0; + final char[] chars = fullyConstructedUrl.toCharArray(); + + for (int i = 0; i < chars.length; i++) { + if (chars[i] == '?') { + count ++; + } + } + + assertEquals(1, count); + } + public void testAssertNotNull() { final String CONST_MESSAGE = "test"; CommonUtils.assertNotNull(new Object(), CONST_MESSAGE); diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilterTest.java b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilterTest.java deleted file mode 100644 index 9f6df06..0000000 --- a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilterTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.jasig.cas.client.validation; - -import junit.framework.TestCase; - -/** - * Unit test for {@link Cas20ProxyReceivingTicketValidationFilter} - * - * @author Brad Cupit (brad [at] lsu {dot} edu) - */ -public class Cas20ProxyReceivingTicketValidationFilterTest extends TestCase { - - public void testThrowsForNullStorage() throws Exception { - Cas20ProxyReceivingTicketValidationFilter filter = newCas20ProxyReceivingTicketValidationFilter(); - filter.setProxyGrantingTicketStorage(null); - - try { - filter.init(); - fail("expected an exception due to null ProxyGrantingTicketStorage"); - } catch (IllegalArgumentException exception) { - // test passes - } - } - - /** - * construct a working {@link Cas20ProxyReceivingTicketValidationFilter} - */ - private Cas20ProxyReceivingTicketValidationFilter newCas20ProxyReceivingTicketValidationFilter() { - final Cas20ProxyReceivingTicketValidationFilter filter = new Cas20ProxyReceivingTicketValidationFilter(); - filter.setServerName("localhost"); - filter.setTicketValidator(new Cas20ProxyTicketValidator("")); - - return filter; - } -} diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilterTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilterTests.java new file mode 100644 index 0000000..daa2556 --- /dev/null +++ b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilterTests.java @@ -0,0 +1,176 @@ +package org.jasig.cas.client.validation; + +import junit.framework.TestCase; +import org.jasig.cas.client.proxy.CleanUpTimerTask; +import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; +import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl; +import org.jasig.cas.client.util.MethodFlag; +import org.springframework.mock.web.MockFilterConfig; + +import java.util.Timer; +import java.util.TimerTask; + +/** + * Unit test for {@link org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter} + * + * @author Brad Cupit (brad [at] lsu {dot} edu) + */ +public class Cas20ProxyReceivingTicketValidationFilterTests extends TestCase { + + private final Timer defaultTimer = new Timer(true); + + private final ProxyGrantingTicketStorage storage = new ProxyGrantingTicketStorageImpl(); + + private final CleanUpTimerTask defaultTimerTask = new CleanUpTimerTask(storage); + + public void testStartsThreadAtStartup() throws Exception { + final MethodFlag scheduleMethodFlag = new MethodFlag(); + final Cas20ProxyReceivingTicketValidationFilter filter = newCas20ProxyReceivingTicketValidationFilter(); + + final Timer timer = new Timer(true) { + public void schedule(TimerTask task, long delay, long period) { + scheduleMethodFlag.setCalled(); + } + }; + + filter.setMillisBetweenCleanUps(1); + filter.setProxyGrantingTicketStorage(storage); + filter.setTimer(timer); + filter.setTimerTask(defaultTimerTask); + + filter.init(); + assertTrue(scheduleMethodFlag.wasCalled()); + } + + public void testShutsDownTimerThread() throws Exception { + final MethodFlag cancelMethodFlag = new MethodFlag(); + final Cas20ProxyReceivingTicketValidationFilter filter = newCas20ProxyReceivingTicketValidationFilter(); + + final Timer timer = new Timer(true) { + public void cancel() { + cancelMethodFlag.setCalled(); + super.cancel(); + } + }; + + filter.setProxyGrantingTicketStorage(storage); + filter.setMillisBetweenCleanUps(1); + filter.setTimer(timer); + filter.setTimerTask(defaultTimerTask); + filter.init(); + filter.destroy(); + + assertTrue(cancelMethodFlag.wasCalled()); + } + +public void testCallsCleanAllOnSchedule() throws Exception { + final MethodFlag timerTaskFlag = new MethodFlag(); + final Cas20ProxyReceivingTicketValidationFilter filter = newCas20ProxyReceivingTicketValidationFilter(); + + final TimerTask timerTask = new TimerTask() { + public void run() { + timerTaskFlag.setCalled(); + } + }; + + final int millisBetweenCleanUps = 250; + filter.setProxyGrantingTicketStorage(storage); + filter.setTimerTask(timerTask); + filter.setTimer(defaultTimer); + filter.setMillisBetweenCleanUps(millisBetweenCleanUps); + + filter.init(); + + // wait long enough for the clean up to occur + Thread.sleep(millisBetweenCleanUps * 2); + + assertTrue(timerTaskFlag.wasCalled()); + filter.destroy(); + } + + public void testDelaysFirstCleanAll() throws Exception { + final MethodFlag timerTaskFlag = new MethodFlag(); + final Cas20ProxyReceivingTicketValidationFilter filter = newCas20ProxyReceivingTicketValidationFilter(); + + final TimerTask timerTask = new TimerTask() { + public void run() { + timerTaskFlag.setCalled(); + } + }; + + final int millisBetweenCleanUps = 250; + filter.setProxyGrantingTicketStorage(storage); + filter.setMillisBetweenCleanUps(millisBetweenCleanUps); + filter.setTimer(defaultTimer); + filter.setTimerTask(timerTask); + + filter.init(); + + assertFalse(timerTaskFlag.wasCalled()); + + // wait long enough for the clean up to occur + Thread.sleep(millisBetweenCleanUps * 2); + + assertTrue(timerTaskFlag.wasCalled()); + + filter.destroy(); + } + + public void testThrowsForNullStorage() throws Exception { + Cas20ProxyReceivingTicketValidationFilter filter = newCas20ProxyReceivingTicketValidationFilter(); + filter.setProxyGrantingTicketStorage(null); + + try { + filter.init(); + fail("expected an exception due to null ProxyGrantingTicketStorage"); + } catch (IllegalArgumentException exception) { + // test passes + } + } + + public void testGetTicketValidator() throws Exception { + Cas20ProxyReceivingTicketValidationFilter filter = newCas20ProxyReceivingTicketValidationFilter(); + filter.setProxyGrantingTicketStorage(storage); + filter.setMillisBetweenCleanUps(250); + filter.setTimer(defaultTimer); + filter.setTimerTask(new TimerTask() { + public void run() {} + }); + filter.init(); + + // Test case #1 + final MockFilterConfig config1 = new MockFilterConfig(); + config1.addInitParameter("allowedProxyChains", "https://a.example.com"); + config1.addInitParameter("casServerUrlPrefix", "https://cas.jasig.org/"); + assertNotNull(filter.getTicketValidator(config1)); + + // Test case #2 + final MockFilterConfig config2 = new MockFilterConfig(); + config2.addInitParameter( + "allowedProxyChains", + "https://a.example.com https://b.example.com"); + config2.addInitParameter("casServerUrlPrefix", "https://cas.jasig.org/"); + assertNotNull(filter.getTicketValidator(config2)); + + // Test case #3 + final MockFilterConfig config3 = new MockFilterConfig(); + config3.addInitParameter( + "allowedProxyChains", + "https://a.example.com https://b.example.com\nhttps://c.example.com"); + config3.addInitParameter("casServerUrlPrefix", "https://cas.jasig.org/"); + assertNotNull(filter.getTicketValidator(config3)); + } + + + + /** + * construct a working {@link org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter} + */ + private Cas20ProxyReceivingTicketValidationFilter newCas20ProxyReceivingTicketValidationFilter() { + final Cas20ProxyReceivingTicketValidationFilter filter = new Cas20ProxyReceivingTicketValidationFilter(); + filter.setServerName("localhost"); + filter.setTicketValidator(new Cas20ProxyTicketValidator("")); + + return filter; + } +} \ No newline at end of file diff --git a/cas-client-integration-atlassian/pom.xml b/cas-client-integration-atlassian/pom.xml index cc38cbd..9ebe77e 100644 --- a/cas-client-integration-atlassian/pom.xml +++ b/cas-client-integration-atlassian/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> org.jasig.cas - 3.1.5 + 3.1.8 cas-client 4.0.0 @@ -65,13 +65,13 @@ opensymphony propertyset - + com.atlassian.confluence confluence - 2.7.3 + 2.7.3 provided diff --git a/cas-client-integration-atlassian/src/main/java/org/jasig/cas/client/integration/atlassian/ConfluenceCasAuthenticator.java b/cas-client-integration-atlassian/src/main/java/org/jasig/cas/client/integration/atlassian/ConfluenceCasAuthenticator.java index 0ae8233..0ecfddd 100644 --- a/cas-client-integration-atlassian/src/main/java/org/jasig/cas/client/integration/atlassian/ConfluenceCasAuthenticator.java +++ b/cas-client-integration-atlassian/src/main/java/org/jasig/cas/client/integration/atlassian/ConfluenceCasAuthenticator.java @@ -6,6 +6,7 @@ package org.jasig.cas.client.integration.atlassian; import com.atlassian.confluence.user.ConfluenceAuthenticator; +import com.atlassian.seraph.auth.AuthenticatorException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jasig.cas.client.util.AbstractCasFilter; @@ -21,35 +22,54 @@ import java.security.Principal; * via CAS. * * @author Scott Battaglia + * @author John Watson * @version $Revision$ $Date$ * @since 3.1.2 */ public final class ConfluenceCasAuthenticator extends ConfluenceAuthenticator { - private static final Log log = LogFactory.getLog(ConfluenceCasAuthenticator.class); + private static final Log LOG = LogFactory.getLog(ConfluenceCasAuthenticator.class); public Principal getUser(final HttpServletRequest request, final HttpServletResponse response) { final HttpSession session = request.getSession(); - if (session != null) { // user already exists - if (session.getAttribute(ConfluenceCasAuthenticator.LOGGED_IN_KEY) != null) { - log.info("Session found; user already logged in."); - return (Principal) session.getAttribute(LOGGED_IN_KEY); + if (session.getAttribute(LOGGED_IN_KEY) != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Session found; user already logged in."); + } + return (Principal) session.getAttribute(LOGGED_IN_KEY); + } + + final Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); + + if (assertion != null) { + final Principal p = getUser(assertion.getPrincipal().getName()); + + if (LOG.isDebugEnabled()) { + LOG.debug("Logging in [" + p.getName() + "] from CAS."); } - final Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); - - if (assertion != null) { - if (assertion != null) { - final Principal p = getUser(assertion.getPrincipal().getName()); - request.getSession().setAttribute(LOGGED_IN_KEY, p); - request.getSession().setAttribute(LOGGED_OUT_KEY, null); - return p; - } - } + session.setAttribute(LOGGED_IN_KEY, p); + session.setAttribute(LOGGED_OUT_KEY, null); + return p; } return super.getUser(request, response); } + + public boolean logout(final HttpServletRequest request, final HttpServletResponse response) throws AuthenticatorException { + final HttpSession session = request.getSession(); + + final Principal principal = (Principal) session.getAttribute(LOGGED_IN_KEY); + + if (LOG.isDebugEnabled()) { + LOG.debug("Logging out [" + principal.getName() + "] from CAS."); + } + + session.setAttribute(LOGGED_OUT_KEY, principal); + session.setAttribute(LOGGED_IN_KEY, null); + session.setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, null); + return true; + } } \ No newline at end of file diff --git a/cas-client-integration-atlassian/src/main/java/org/jasig/cas/client/integration/atlassian/JiraCasAuthenticator.java b/cas-client-integration-atlassian/src/main/java/org/jasig/cas/client/integration/atlassian/JiraCasAuthenticator.java index 8d882aa..db4e5d7 100644 --- a/cas-client-integration-atlassian/src/main/java/org/jasig/cas/client/integration/atlassian/JiraCasAuthenticator.java +++ b/cas-client-integration-atlassian/src/main/java/org/jasig/cas/client/integration/atlassian/JiraCasAuthenticator.java @@ -6,6 +6,7 @@ package org.jasig.cas.client.integration.atlassian; import com.atlassian.seraph.auth.DefaultAuthenticator; +import com.atlassian.seraph.auth.AuthenticatorException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jasig.cas.client.util.AbstractCasFilter; @@ -21,33 +22,53 @@ import java.security.Principal; * via CAS. * * @author Scott Battaglia + * @author John Watson * @version $Revision$ $Date$ * @since 3.1.3 */ public final class JiraCasAuthenticator extends DefaultAuthenticator { - private static final Log log = LogFactory.getLog(JiraCasAuthenticator.class); + private static final Log LOG = LogFactory.getLog(JiraCasAuthenticator.class); public Principal getUser(final HttpServletRequest request, final HttpServletResponse response) { final HttpSession session = request.getSession(); - if (session != null) { // user already exists - if (session.getAttribute(ConfluenceCasAuthenticator.LOGGED_IN_KEY) != null) { - log.info("Session found; user already logged in."); - return (Principal) session.getAttribute(LOGGED_IN_KEY); + if (session.getAttribute(LOGGED_IN_KEY) != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Session found; user already logged in."); + } + return (Principal) session.getAttribute(LOGGED_IN_KEY); + } + + final Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); + + if (assertion != null) { + final Principal p = getUser(assertion.getPrincipal().getName()); + + if (LOG.isDebugEnabled()) { + LOG.debug("Logging in [" + p.getName() + "] from CAS."); } - final Assertion assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION); - - if (assertion != null) { - final Principal p = getUser(assertion.getPrincipal().getName()); - request.getSession().setAttribute(LOGGED_IN_KEY, p); - request.getSession().setAttribute(LOGGED_OUT_KEY, null); - return p; - } + session.setAttribute(LOGGED_IN_KEY, p); + session.setAttribute(LOGGED_OUT_KEY, null); + return p; } return super.getUser(request, response); } + + public boolean logout(final HttpServletRequest request, final HttpServletResponse response) throws AuthenticatorException { + final HttpSession session = request.getSession(); + final Principal p = (Principal) session.getAttribute(LOGGED_IN_KEY); + + if (LOG.isDebugEnabled()) { + LOG.debug("Logging out [" + p.getName() + "] from CAS."); + } + + session.setAttribute(LOGGED_OUT_KEY, p); + session.setAttribute(LOGGED_IN_KEY, null); + session.setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, null); + return true; + } } \ No newline at end of file diff --git a/pom.xml b/pom.xml index f88ed7d..6c0540c 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 4.0.0 org.jasig.cas - 3.1.5 + 3.1.8 cas-client pom JA-SIG CAS Client for Java