updated to reflect that Assertion now has a reference to ProxyRetriever

This commit is contained in:
Scott Battaglia 2006-10-03 13:14:02 +00:00
parent e9467826ae
commit a68b4e8a08
9 changed files with 150 additions and 63 deletions

View File

@ -26,7 +26,7 @@ public abstract class AbstractUrlBasedTicketValidator implements
protected final Log log = LogFactory.getLog(this.getClass());
/**
* Url to CAS server.
* Url to CAS server. Generally of the form https://server:port/cas/
*/
private final String casServerUrl;
@ -36,7 +36,7 @@ public abstract class AbstractUrlBasedTicketValidator implements
private final boolean renew;
/**
* Instance of HttpClient for connecting to server.
* Instance of HttpClient for connecting to server. Care should be taken only inject a multi-threaded HttpClient.
*/
private final HttpClient httpClient;
@ -48,9 +48,23 @@ public abstract class AbstractUrlBasedTicketValidator implements
return parseResponse(response);
}
/**
* Constructs the URL endpoint for contacting CAS for ticket validation.
*
* @param ticketId the opaque ticket id.
* @param service the service we are validating for.
* @return the fully constructed url.
*/
protected abstract String constructURL(final String ticketId,
final Service service);
/**
* Parses the response retrieved from the url endpoint.
*
* @param response the String response.
* @return an Assertion based on the response.
* @throws ValidationException if there was an error validating the ticket.
*/
protected abstract Assertion parseResponse(final String response)
throws ValidationException;

View File

@ -6,6 +6,7 @@
package org.jasig.cas.client.validation;
import org.jasig.cas.authentication.principal.Principal;
import org.jasig.cas.authentication.principal.Service;
import java.io.Serializable;
import java.util.Map;
@ -36,9 +37,10 @@ public interface Assertion extends Serializable {
Map getAttributes();
/**
* Method to retrieve the proxyGrantingTicket Id.
* Retrieves a proxy ticket for the specific service.
*
* @return the ProxyGrantingTicket Id if one exists, otherwise null.
* @param service The service to proxy to.
* @return the Proxy Ticket Id or null.
*/
String getProxyGrantingTicketId();
String getProxyTicketFor(Service service);
}

View File

@ -6,6 +6,8 @@
package org.jasig.cas.client.validation;
import org.jasig.cas.authentication.principal.Principal;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.client.proxy.ProxyRetriever;
import org.jasig.cas.client.util.CommonUtils;
import java.util.HashMap;
@ -41,29 +43,61 @@ public class AssertionImpl implements Assertion {
*/
private final String proxyGrantingTicketId;
/**
* Reference to ProxyRetriever so that clients can retrieve proxy tickets for a service.
*/
private final ProxyRetriever proxyRetriever;
/**
* Simple constructor that accepts a Principal.
*
* @param principal the Principal this assertion is for.
*/
public AssertionImpl(final Principal principal) {
this(principal, null, null);
this(principal, null, null, null);
}
/**
* Constructor that accepts a Principal and a map of attributes.
*
* @param principal the Principal this assertion is for.
* @param attributes a map of attributes about the principal.
*/
public AssertionImpl(final Principal principal, final Map attributes) {
this(principal, attributes, null, null);
}
/**
* @param principal the Principal this assertion is for.
* @param attributes a map of attributes about the principal.
* @param proxyRetriever used to retrieve proxy tickets from CAS Server.
* @param proxyGrantingTicketId the Id to use to request proxy tickets.
*/
public AssertionImpl(final Principal principal, final Map attributes,
final String proxyGrantingTicketId) {
final ProxyRetriever proxyRetriever, final String proxyGrantingTicketId) {
CommonUtils.assertNotNull(principal, "principal cannot be null");
this.principal = principal;
this.attributes = attributes == null ? new HashMap() : attributes;
this.proxyGrantingTicketId = CommonUtils
.isNotEmpty(proxyGrantingTicketId) ? proxyGrantingTicketId : null;
this.proxyRetriever = proxyRetriever;
}
public final Map getAttributes() {
return this.attributes;
}
public String getProxyTicketFor(final Service service) {
if (proxyRetriever == null || proxyGrantingTicketId == null) {
return null;
}
return this.proxyRetriever.getProxyTicketIdFor(this.proxyGrantingTicketId, service);
}
public final Principal getPrincipal() {
return this.principal;
}
public final String getProxyGrantingTicketId() {
return this.proxyGrantingTicketId;
}
}

View File

@ -47,7 +47,7 @@ public final class Cas10TicketValidator extends AbstractUrlBasedTicketValidator
reader.readLine();
final Principal principal = new SimplePrincipal(reader.readLine());
return new AssertionImpl(principal);
return new AssertionImpl(principal, null);
} catch (final IOException e) {
throw new ValidationException("Unable to parse response.", e);
}

View File

@ -9,6 +9,7 @@ import org.apache.commons.httpclient.HttpClient;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.authentication.principal.SimpleService;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.proxy.ProxyRetriever;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
@ -41,19 +42,18 @@ public class Cas20ProxyTicketValidator extends Cas20ServiceTicketValidator {
private final boolean acceptAnyProxy;
/**
* @param casServerUrl the url to the CAS server, minus the endpoint.
* @param renew flag for whether we require authentication to be via an initial authentication.
* @param httpClient an instance of HttpClient to do the calls.
* @param proxyGrantingTicketStorage a reference to the storage of the proxy tickets.
* @param proxyChains the chains of proxy lists that we accept tickets from.
* @param acceptAnyProxy flag on whether we accept any proxy or not.
* @param casServerUrl the url to the CAS server, minus the endpoint.
* @param renew flag for whether we require authentication to be via an initial authentication.
* @param httpClient an instance of HttpClient to do the calls.
* @param proxyChains the chains of proxy lists that we accept tickets from.
* @param acceptAnyProxy flag on whether we accept any proxy or not.
*/
public Cas20ProxyTicketValidator(final String casServerUrl, final boolean renew, final HttpClient httpClient, final ProxyGrantingTicketStorage proxyGrantingTicketStorage, List proxyChains, boolean acceptAnyProxy) {
this(casServerUrl, renew, httpClient, null, proxyGrantingTicketStorage, proxyChains, acceptAnyProxy);
public Cas20ProxyTicketValidator(final String casServerUrl, final boolean renew, final HttpClient httpClient, List proxyChains, boolean acceptAnyProxy) {
this(casServerUrl, renew, httpClient, null, proxyChains, acceptAnyProxy, null, null);
}
public Cas20ProxyTicketValidator(final String casServerUrl, final boolean renew, final HttpClient httpClient, final Service proxyCallbackUrl, final ProxyGrantingTicketStorage proxyGrantingTicketStorage, List proxyChains, boolean acceptAnyProxy) {
super(casServerUrl, renew, httpClient, proxyCallbackUrl, proxyGrantingTicketStorage);
public Cas20ProxyTicketValidator(final String casServerUrl, final boolean renew, final HttpClient httpClient, final Service proxyCallbackUrl, List proxyChains, boolean acceptAnyProxy, final ProxyGrantingTicketStorage proxyGrantingTicketStorage, final ProxyRetriever proxyRetriever) {
super(casServerUrl, renew, httpClient, proxyCallbackUrl, proxyGrantingTicketStorage, proxyRetriever);
CommonUtils.assertTrue(proxyChains != null || acceptAnyProxy,
"proxyChains cannot be null or acceptAnyProxy must be true.");
@ -83,34 +83,27 @@ public class Cas20ProxyTicketValidator extends Cas20ServiceTicketValidator {
return "proxyValidate";
}
protected Assertion getValidAssertionInternal(final String response,
final Assertion assertion) throws ValidationException {
protected Assertion getValidAssertionInternal(final String response, final String principal, final String proxyGrantingTicketIou) throws ValidationException {
final List proxies = XmlUtils.getTextForElements(response, "proxy");
final Service[] principals = new Service[proxies.size()];
// this means there was nothing in the proxy chain, which is okay
if (principals.length == 0 || this.acceptAnyProxy) {
return assertion;
if (proxies.isEmpty() || this.acceptAnyProxy) {
return getAssertionBasedOnProxyGrantingTicketIou(proxyGrantingTicketIou, principal);
}
final Service[] principals = new Service[proxies.size()];
int i = 0;
for (final Iterator iter = proxies.iterator(); iter.hasNext();) {
principals[i++] = new SimpleService((String) iter.next());
}
boolean found = false;
for (Iterator iter = this.proxyChains.iterator(); iter.hasNext();) {
if (Arrays.equals(principals, (Object[]) iter.next())) {
found = true;
break;
return getAssertionBasedOnProxyGrantingTicketIou(proxyGrantingTicketIou, principal);
}
}
if (!found) {
throw new InvalidProxyChainValidationException();
}
return new AssertionImpl(assertion.getPrincipal(), assertion
.getAttributes(), assertion.getProxyGrantingTicketId());
throw new InvalidProxyChainValidationException();
}
}

View File

@ -9,6 +9,7 @@ import org.apache.commons.httpclient.HttpClient;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.authentication.principal.SimplePrincipal;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.proxy.ProxyRetriever;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
@ -33,16 +34,26 @@ public class Cas20ServiceTicketValidator extends
*/
private final ProxyGrantingTicketStorage proxyGrantingTicketStorage;
public Cas20ServiceTicketValidator(final String casServerUrl, final boolean renew, final HttpClient httpClient, final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
this(casServerUrl, renew, httpClient, null, proxyGrantingTicketStorage);
/**
* Injected into Assertions to allow them to retrieve proxy tickets.
*/
private final ProxyRetriever proxyRetriever;
public Cas20ServiceTicketValidator(final String casServerUrl, final boolean renew, final HttpClient httpClient) {
this(casServerUrl, renew, httpClient, null, null, null);
}
public Cas20ServiceTicketValidator(final String casServerUrl, final boolean renew, final HttpClient httpClient, final Service proxyCallbackUrl, final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
public Cas20ServiceTicketValidator(final String casServerUrl, final boolean renew, final HttpClient httpClient, final Service proxyCallbackUrl, final ProxyGrantingTicketStorage proxyGrantingTicketStorage, final ProxyRetriever proxyRetriever) {
super(casServerUrl, renew, httpClient);
CommonUtils.assertNotNull(proxyGrantingTicketStorage,
"proxyGrantingTicketStorage cannot be null");
if (proxyCallbackUrl != null) {
CommonUtils.assertNotNull(proxyGrantingTicketStorage,
"proxyGrantingTicketStorage cannot be null");
CommonUtils.assertNotNull(proxyRetriever, "proxyRetriever cannot be null.");
}
this.proxyCallbackUrl = proxyCallbackUrl;
this.proxyGrantingTicketStorage = proxyGrantingTicketStorage;
this.proxyRetriever = proxyRetriever;
}
protected String constructURL(final String ticketId,
@ -58,8 +69,9 @@ public class Cas20ServiceTicketValidator extends
+ getEncodedService(this.proxyCallbackUrl) : "");
}
protected final Assertion parseResponse(String response)
protected final Assertion parseResponse(final String response)
throws ValidationException {
final String error = XmlUtils.getTextForElement(response,
"authenticationFailure");
@ -76,23 +88,24 @@ public class Cas20ServiceTicketValidator extends
throw new ValidationException("No principal found.");
}
if (CommonUtils.isNotBlank(proxyGrantingTicketIou)) {
return getValidAssertionInternal(response, new AssertionImpl(
new SimplePrincipal(principal), null,
this.proxyGrantingTicketStorage
.retrieve(proxyGrantingTicketIou)));
}
return getValidAssertionInternal(response, new AssertionImpl(
new SimplePrincipal(principal)));
return getValidAssertionInternal(response, principal, proxyGrantingTicketIou);
}
protected String getValidationUrlName() {
return "serviceValidate";
}
protected Assertion getValidAssertionInternal(final String response,
final Assertion assertion) throws ValidationException {
return assertion;
protected final Assertion getAssertionBasedOnProxyGrantingTicketIou(final String proxyGrantingTicketIou, final String principal) {
if (CommonUtils.isNotBlank(proxyGrantingTicketIou)) {
return new AssertionImpl(
new SimplePrincipal(principal), null, this.proxyRetriever, this.proxyGrantingTicketStorage == null ? null : this.proxyGrantingTicketStorage
.retrieve(proxyGrantingTicketIou));
} else {
return new AssertionImpl(new SimplePrincipal(principal));
}
}
protected Assertion getValidAssertionInternal(final String response, final String principal, final String proxyGrantingTicketIou) throws ValidationException {
return getAssertionBasedOnProxyGrantingTicketIou(proxyGrantingTicketIou, principal);
}
}

View File

@ -8,6 +8,7 @@ package org.jasig.cas.client.validation;
import junit.framework.TestCase;
import org.jasig.cas.authentication.principal.Principal;
import org.jasig.cas.authentication.principal.SimplePrincipal;
import org.jasig.cas.authentication.principal.SimpleService;
import java.util.HashMap;
import java.util.Map;
@ -36,16 +37,14 @@ public final class AssertionImplTests extends TestCase {
assertEquals(CONST_PRINCIPAL, assertion.getPrincipal());
assertTrue(assertion.getAttributes().isEmpty());
assertNull(assertion.getProxyGrantingTicketId());
assertNull(assertion.getProxyTicketFor(new SimpleService("test")));
}
public void testCompleteConstructor() {
final Assertion assertion = new AssertionImpl(CONST_PRINCIPAL,
CONST_ATTRIBUTES, CONST_PROXY_GRANTING_TICKET_IOU);
CONST_ATTRIBUTES);
assertEquals(CONST_PRINCIPAL, assertion.getPrincipal());
assertEquals(CONST_ATTRIBUTES, assertion.getAttributes());
assertEquals(CONST_PROXY_GRANTING_TICKET_IOU, assertion
.getProxyGrantingTicketId());
}
}

View File

@ -7,10 +7,12 @@ package org.jasig.cas.client.validation;
import org.apache.commons.httpclient.HttpClient;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.authentication.principal.SimpleService;
import org.jasig.cas.client.PublicTestHttpServer;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl;
import org.jasig.cas.client.proxy.ProxyRetriever;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
@ -37,15 +39,26 @@ public final class Cas20ProxyTicketValidatorTests extends
final List list = new ArrayList();
list.add("proxy1 proxy2 proxy3");
this.ticketValidator = new Cas20ProxyTicketValidator(CONST_CAS_SERVER_URL, true, new HttpClient(), proxyGrantingTicketStorage, list, false);
this.ticketValidator = new Cas20ProxyTicketValidator(CONST_CAS_SERVER_URL, true, new HttpClient(), new SimpleService("test"), list, false, getProxyGrantingTicketStorage(), getProxyRetriever());
}
private ProxyGrantingTicketStorage getProxyGrantingTicketStorage() {
ProxyGrantingTicketStorageImpl proxyGrantingTicketStorageImpl = new ProxyGrantingTicketStorageImpl();
final ProxyGrantingTicketStorageImpl proxyGrantingTicketStorageImpl = new ProxyGrantingTicketStorageImpl();
return proxyGrantingTicketStorageImpl;
}
private ProxyRetriever getProxyRetriever() {
final ProxyRetriever proxyRetriever = new ProxyRetriever() {
public String getProxyTicketIdFor(String proxyGrantingTicketId, Service targetService) {
return "test";
}
};
return proxyRetriever;
}
public void testProxyChainWithValidProxy() throws ValidationException,
UnsupportedEncodingException {
final String USERNAME = "username";

View File

@ -7,10 +7,12 @@ package org.jasig.cas.client.validation;
import org.apache.commons.httpclient.HttpClient;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.authentication.principal.SimpleService;
import org.jasig.cas.client.PublicTestHttpServer;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl;
import org.jasig.cas.client.proxy.ProxyRetriever;
import java.io.UnsupportedEncodingException;
@ -28,21 +30,38 @@ public final class Cas20ServiceTicketValidatorTests extends
private ProxyGrantingTicketStorage proxyGrantingTicketStorage;
private ProxyRetriever proxyRetriever;
public Cas20ServiceTicketValidatorTests() {
super();
}
public Cas20ServiceTicketValidatorTests(Cas20ServiceTicketValidator ticketValidator) {
this.ticketValidator = ticketValidator;
}
protected void setUp() throws Exception {
this.proxyGrantingTicketStorage = getProxyGrantingTicketStorage();
this.ticketValidator = new Cas20ServiceTicketValidator(CONST_CAS_SERVER_URL, true, new HttpClient(), this.proxyGrantingTicketStorage);
this.ticketValidator = new Cas20ServiceTicketValidator(CONST_CAS_SERVER_URL, true, new HttpClient(), new SimpleService("test"), this.proxyGrantingTicketStorage, getProxyRetriever());
}
private ProxyGrantingTicketStorage getProxyGrantingTicketStorage() {
ProxyGrantingTicketStorageImpl proxyGrantingTicketStorageImpl = new ProxyGrantingTicketStorageImpl();
final ProxyGrantingTicketStorageImpl proxyGrantingTicketStorageImpl = new ProxyGrantingTicketStorageImpl();
return proxyGrantingTicketStorageImpl;
}
private ProxyRetriever getProxyRetriever() {
final ProxyRetriever proxyRetriever = new ProxyRetriever() {
public String getProxyTicketIdFor(String proxyGrantingTicketId, Service targetService) {
return "test";
}
};
return proxyRetriever;
}
public void testNoResponse() throws UnsupportedEncodingException {
final String RESPONSE = "<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'><cas:authenticationFailure code=\"INVALID_TICKET\">Ticket ST-1856339-aA5Yuvrxzpv8Tau1cYQ7 not recognized</cas:authenticationFailure></cas:serviceResponse>";
PublicTestHttpServer.instance().content = RESPONSE
@ -88,7 +107,7 @@ public final class Cas20ServiceTicketValidatorTests extends
final Assertion assertion = this.ticketValidator.validate("test",
new SimpleService("test"));
assertEquals(USERNAME, assertion.getPrincipal().getId());
assertEquals(PGT, assertion.getProxyGrantingTicketId());
// assertEquals(PGT, assertion.getProxyGrantingTicketId());
}
public void testInvalidResponse() throws Exception {