Merge pull request #66 from Unicon/CASC-210

CASC-210: Added support for having regex expressions in the proxy (chaining) list.
This commit is contained in:
Scott 2015-07-07 17:10:05 -04:00
commit 0a7ffac846
4 changed files with 92 additions and 7 deletions

View File

@ -28,7 +28,13 @@ package org.jasig.cas.client.authentication;
public final class ExactUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
private String pattern;
public ExactUrlPatternMatcherStrategy() {}
public ExactUrlPatternMatcherStrategy(final String pattern) {
this.setPattern(pattern);
}
public boolean matches(final String url) {
return url.equals(this.pattern);
}

View File

@ -30,6 +30,12 @@ import java.util.regex.Pattern;
public final class RegexUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
private Pattern pattern;
public RegexUrlPatternMatcherStrategy() {}
public RegexUrlPatternMatcherStrategy(final String pattern) {
this.setPattern(pattern);
}
public boolean matches(final String url) {
return this.pattern.matcher(url).find();

View File

@ -19,9 +19,13 @@
package org.jasig.cas.client.validation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.jasig.cas.client.authentication.ExactUrlPatternMatcherStrategy;
import org.jasig.cas.client.authentication.RegexUrlPatternMatcherStrategy;
import org.jasig.cas.client.authentication.UrlPatternMatcherStrategy;
import org.jasig.cas.client.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Holding class for the proxy list to make Spring configuration easier.
@ -32,11 +36,28 @@ import org.jasig.cas.client.util.CommonUtils;
*/
public final class ProxyList {
private final List<String[]> proxyChains;
private final Logger logger = LoggerFactory.getLogger(getClass());
private final List<List<UrlPatternMatcherStrategy>> proxyChains;
public ProxyList(final List<String[]> proxyChains) {
CommonUtils.assertNotNull(proxyChains, "List of proxy chains cannot be null.");
this.proxyChains = proxyChains;
this.proxyChains = new ArrayList<List<UrlPatternMatcherStrategy>>();
for (final String[] list : proxyChains) {
final List<UrlPatternMatcherStrategy> chain = new ArrayList<UrlPatternMatcherStrategy>();
for (final String item : list) {
if (item.startsWith("^")) {
chain.add(new RegexUrlPatternMatcherStrategy(item));
} else {
chain.add(new ExactUrlPatternMatcherStrategy(item));
}
}
this.proxyChains.add(chain);
}
}
public ProxyList() {
@ -44,12 +65,33 @@ public final class ProxyList {
}
public boolean contains(final String[] proxiedList) {
for (final String[] list : this.proxyChains) {
if (Arrays.equals(proxiedList, list)) {
return true;
StringBuilder loggingOutput;
for (final List<UrlPatternMatcherStrategy> proxyChain : this.proxyChains) {
loggingOutput = new StringBuilder();
if (proxyChain.size() == proxiedList.length) {
for (int linkIndex = 0; linkIndex < proxyChain.size(); linkIndex++) {
final String linkToTest = proxiedList[linkIndex];
loggingOutput.append(linkToTest);
if (proxyChain.get(linkIndex).matches(linkToTest)) {
//If we are at the last link, we found a good proxyChain.
if (linkIndex == proxyChain.size() - 1) {
logger.info("Proxy chain matched: {}", loggingOutput.toString());
return true;
}
} else {
logger.warn("Proxy chain did not match at {}. Skipping to next allowedProxyChain", loggingOutput.toString());
break;
}
loggingOutput.append("->");
}
}
}
logger.warn("No proxy chain matched the allowedProxyChains list.");
return false;
}

View File

@ -105,6 +105,37 @@ public final class Cas20ProxyTicketValidatorTests extends AbstractTicketValidato
}
}
@Test
public void testRegexProxyChainWithValidProxy() throws TicketValidationException, UnsupportedEncodingException {
final List<String[]> list = new ArrayList<String[]>();
list.add(new String[] { "proxy1", "proxy2", "^proxy3/[a-z]*/" });
this.ticketValidator.setAllowedProxyChains(new ProxyList(list));
final String USERNAME = "username";
final String RESPONSE = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'><cas:authenticationSuccess><cas:user>username</cas:user><cas:proxyGrantingTicket>PGTIOU-84678-8a9d...</cas:proxyGrantingTicket><cas:proxies><cas:proxy>proxy1</cas:proxy><cas:proxy>proxy2</cas:proxy><cas:proxy>proxy3/abc/</cas:proxy></cas:proxies></cas:authenticationSuccess></cas:serviceResponse>";
server.content = RESPONSE.getBytes(server.encoding);
final Assertion assertion = this.ticketValidator.validate("test", "test");
assertEquals(USERNAME, assertion.getPrincipal().getName());
}
@Test
public void testRegexProxyChainWithInvalidProxy() throws TicketValidationException, UnsupportedEncodingException {
final List<String[]> list = new ArrayList<String[]>();
list.add(new String[] { "proxy1", "proxy2", "^proxy3/[a-z]*/" });
this.ticketValidator.setAllowedProxyChains(new ProxyList(list));
final String RESPONSE = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'><cas:authenticationSuccess><cas:user>username</cas:user><cas:proxyGrantingTicket>PGTIOU-84678-8a9d...</cas:proxyGrantingTicket><cas:proxies><cas:proxy>proxy1</cas:proxy><cas:proxy>proxy2</cas:proxy><cas:proxy>proxy3/ABC/</cas:proxy></cas:proxies></cas:authenticationSuccess></cas:serviceResponse>";
server.content = RESPONSE.getBytes(server.encoding);
try {
this.ticketValidator.validate("test", "test");
fail("Invalid proxy chain");
} catch (InvalidProxyChainTicketValidationException e) {
// expected
}
}
@Test
public void testConstructionFromSpringBean() throws TicketValidationException, UnsupportedEncodingException {
final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(