Updated Tomcat container authnz support with abstracted
version-agnostic core, cas-client-integration-tomcat-common, to facilitate
integration with multiple versions of Tomcat.
This commit is contained in:
Marvin S. Addison 2010-09-17 20:37:19 +00:00
parent 0f3d8a5c60
commit 54afd070ec
23 changed files with 924 additions and 176 deletions

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cas-client</artifactId>
<groupId>org.jasig.cas.client</groupId>
<version>3.1.12-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-integration-tomcat-common</artifactId>
<packaging>jar</packaging>
<name>JA-SIG CAS Client for Java - Common Tomcat Integration Support</name>
<dependencies>
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-core</artifactId>
<version>${project.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,88 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
import java.security.Principal;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.authentication.AttributePrincipal;
/**
* {@link CasRealm} implementation with prinicpal and role data backed by the {@link Assertion}.
* In particular, an {@link AttributePrincipal} is expected from which the values of
* the role attribute are retrieved. The default role attribute name is "role",
* but this can be customized via {@link #setRoleAttributeName(String)}.
* <p>
* Authentication always succeeds and simply returns the given principal.
*
* @author Marvin S. Addison
* @version $Revision$
*
*/
public class AssertionCasRealmDelegate implements CasRealm {
/** Default role attribute name */
public static final String DEFAULT_ROLE_NAME = "role";
/** Log instance */
private final Log log = LogFactory.getLog(getClass());
/** Name of the role attribute in the principal's attributes */
private String roleAttributeName = DEFAULT_ROLE_NAME;
/**
* @param name Name of the attribute in the principal that contains role data.
*/
public void setRoleAttributeName(final String name) {
this.roleAttributeName = name;
}
/** {@inheritDoc} */
public Principal authenticate(final Principal p) {
return p;
}
/** {@inheritDoc} */
public String[] getRoles(final Principal p) {
if (p instanceof AttributePrincipal) {
final Collection roles = getRoleCollection(p);
if (roles != null) {
final String[] array = new String[roles.size()];
roles.toArray(array);
return array;
} else {
return new String[0];
}
} else {
throw new IllegalArgumentException("Expected instance of AttributePrincipal but got " + p);
}
}
/** {@inheritDoc} */
public boolean hasRole(final Principal principal, final String role) {
final Collection roles = getRoleCollection(principal);
if (roles != null) {
return roles.contains(role);
} else {
return false;
}
}
private Collection getRoleCollection(final Principal p) {
if (p instanceof AttributePrincipal) {
final Collection attributes =
(Collection) ((AttributePrincipal) p).getAttributes().get(roleAttributeName);
if (attributes == null) {
log.debug(p + " has no attribute named " + roleAttributeName);
}
return attributes;
} else {
return null;
}
}
}

View File

@ -0,0 +1,196 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
import java.io.IOException;
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.TicketValidationException;
import org.jasig.cas.client.validation.TicketValidator;
/**
* Version-agnostic authenticator which encapsulates the core CAS workflow of
* redirecting to CAS for unauthenticated sessions and validating service tickets
* when found in the request. Implementations of the Tomcat <code>Authenticator</code>
* class are expected to be thin wrappers that delegate most if not all authentication
* logic to this class.
*
* @author Marvin S. Addison
* @version $Revision$
*
*/
public class AuthenticatorDelegate {
/** Log instance */
private final Log log = LogFactory.getLog(getClass());
private String serviceUrl;
private String serverName;
private String casServerLoginUrl;
private String artifactParameterName;
private String serviceParameterName;
private TicketValidator ticketValidator;
private CasRealm realm;
/**
* Performs CAS authentication on the given request and returns the principal
* determined by the configured {@link CasRealm} on success.
*
* @param request HTTP request.
* @param response HTTP response.
*
* @return The authenticated principal on authentication success, otherwise
* null. In the case where authentication explicitly fails, either due to
* ticket validation failure or realm authentication failure, a 403 status
* code is set on the response. In cases where no existing CAS session exists,
* a 302 redirect is set on the response to redirect to the CAS server for
* authentication.
*/
public final Principal authenticate(final HttpServletRequest request, final HttpServletResponse response) {
Assertion assertion = null;
HttpSession session = request.getSession();
if (session != null) {
assertion = (Assertion) session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
}
if (assertion == null) {
log.debug("CAS assertion not found in session -- authentication required.");
final String token = request.getParameter(this.artifactParameterName);
final String service = CommonUtils.constructServiceUrl(request, response, this.serviceUrl, this.serverName, this.artifactParameterName, true);
if (CommonUtils.isBlank(token)) {
final String redirectUrl = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, this.serviceParameterName, service, false, false);
log.debug("Redirecting to " + redirectUrl);
try {
response.sendRedirect(redirectUrl);
} catch (IOException e) {
throw new IllegalStateException("Cannot redirect to " + redirectUrl, e);
}
return null;
}
try {
log.debug("Attempting to validate " + token + " for " + service);
assertion = this.ticketValidator.validate(token, service);
log.debug("CAS authentication succeeded.");
if (session == null) {
session = request.getSession(true);
}
session.setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, assertion);
} catch (final TicketValidationException e) {
setUnauthorized(response, e.getMessage());
return null;
}
}
Principal p = realm.authenticate(assertion.getPrincipal());
if (p == null) {
log.debug(assertion.getPrincipal().getName() + " failed to authenticate to " + realm);
setUnauthorized(response, null);
}
return p;
}
/**
* @return the serviceUrl
*/
public String getServiceUrl() {
return serviceUrl;
}
/**
* @param serviceUrl the serviceUrl to set
*/
public void setServiceUrl(final String serviceUrl) {
this.serviceUrl = serviceUrl;
}
/**
* @return the serverName
*/
public String getServerName() {
return serverName;
}
/**
* @param serverName the serverName to set
*/
public void setServerName(final String serverName) {
this.serverName = serverName;
}
/**
* @return the casServerLoginUrl
*/
public String getCasServerLoginUrl() {
return casServerLoginUrl;
}
/**
* @param casServerLoginUrl the casServerLoginUrl to set
*/
public void setCasServerLoginUrl(final String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
/**
* @return the ticketValidator
*/
public TicketValidator getTicketValidator() {
return ticketValidator;
}
/**
* @param artifactParameterName the artifactParameterName to set
*/
public void setArtifactParameterName(final String artifactParameterName) {
this.artifactParameterName = artifactParameterName;
}
/**
* @param serviceParameterName the serviceParameterName to set
*/
public void setServiceParameterName(final String serviceParameterName) {
this.serviceParameterName = serviceParameterName;
}
/**
* @param ticketValidator the ticketValidator to set
*/
public void setTicketValidator(final TicketValidator ticketValidator) {
this.ticketValidator = ticketValidator;
}
/**
* @param realm the realm to set
*/
public void setRealm(final CasRealm realm) {
this.realm = realm;
}
private void setUnauthorized(final HttpServletResponse response, final String message) {
try {
if (message != null) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, message);
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
} catch (IOException e) {
throw new IllegalStateException("Error setting 403 status.", e);
}
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
import java.security.Principal;
/**
* Describes Tomcat <code>Realm</code> implementations that do not require password
* for authentication.
*
* @author Marvin S. Addison
* @version $Revision$
*
*/
public interface CasRealm {
/**
* Authenticates the given principal.
*
* @param p Principal to authenticate.
*
* @return New principal.
*/
Principal authenticate(Principal p);
/**
* Gets the roles defined for the given principal.
*
* @return Roles for given principal or empty array if none exist.
*/
String[] getRoles(Principal p);
/**
* Determines whether the given principal possesses the given role.
*
* @param principal Principal to evaluate.
* @param role Role to test for possession.
*
* @return True if principal has given role, false otherwise.
*/
boolean hasRole(Principal principal, String role);
}

View File

@ -0,0 +1,107 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.Principal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.HashSet;
import org.jasig.cas.client.util.CommonUtils;
/**
* {@link CasRealm} implementation with users and roles defined by a properties
* file with the following format:
* <pre>
* username1=role1,role2,role3
* username2=role1
* username3=role2,role3
* </pre>
* User authentication succeeds if the name of the given principal exists as
* a username in the properties file.
*
* @author Middleware
* @version $Revision$
*
*/
public class PropertiesCasRealmDelegate implements CasRealm {
/** Path to backing properties file */
private String propertiesFilePath;
/** Map of usernames to roles */
private Map roleMap;
/**
* @param path Path to properties file container username/role data.
*/
public void setPropertiesFilePath(final String path) {
propertiesFilePath = path;
}
/** {@inheritDoc} */
public void readProperties()
{
CommonUtils.assertNotNull(propertiesFilePath, "PropertiesFilePath not set.");
File file = new File(propertiesFilePath);
if (!file.isAbsolute()) {
file = new File(System.getProperty("catalina.base"), propertiesFilePath);
}
CommonUtils.assertTrue(file.exists(), "File not found " + file);
CommonUtils.assertTrue(file.canRead(), "Cannot read " + file);
final Properties properties = new Properties();
try {
properties.load(new BufferedInputStream(new FileInputStream(file)));
} catch (IOException e) {
throw new IllegalStateException("Error loading users/roles from " + file, e);
}
roleMap = new HashMap(properties.size());
final Iterator keys = properties.keySet().iterator();
while (keys.hasNext()) {
final String user = (String) keys.next();
// Use TreeSet to sort roles
final Set roleSet = new HashSet();
final String[] roles = properties.getProperty(user).split(",\\s*");
for (int i = 0; i < roles.length; i++) {
roleSet.add(roles[i]);
}
roleMap.put(user, roleSet);
}
}
/** {@inheritDoc} */
public Principal authenticate(final Principal p) {
if (roleMap.get(p.getName()) != null) {
return p;
} else {
return null;
}
}
/** {@inheritDoc} */
public String[] getRoles(final Principal p) {
final Set roleSet = (Set) roleMap.get(p.getName());
final String[] roles = new String[roleSet.size()];
roleSet.toArray(roles);
return roles;
}
/** {@inheritDoc} */
public boolean hasRole(final Principal principal, final String role) {
final Set roles = (Set) roleMap.get(principal.getName());
if (roles != null) {
return roles.contains(role);
} else {
return false;
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
import java.security.Principal;
import junit.framework.TestCase;
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
/**
* Unit test for {@link PropertiesCasRealmDelegate} class.
*
* @author Middleware
* @version $Revision$
*
*/
public class PropertiesCasRealmDelegateTests extends TestCase {
private PropertiesCasRealmDelegate realm = new PropertiesCasRealmDelegate();
/** {@inheritDoc} */
protected void setUp() throws Exception {
super.setUp();
realm.setPropertiesFilePath("src/test/resources/org/jasig/cas/client/tomcat/user-roles.properties");
realm.readProperties();
}
public void testAuthenticate() {
final Principal p = new AttributePrincipalImpl("rosencrantz");
assertTrue(p == realm.authenticate(p));
}
public void testGetRoles() {
final Principal p = new AttributePrincipalImpl("rosencrantz");
final String[] expected = new String[] {"admins", "users"};
final String[] actual = realm.getRoles(p);
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++) {
assertEquals(expected[i], actual[i]);
}
}
public void testHasRole() {
assertTrue(realm.hasRole(new AttributePrincipalImpl("rosencrantz"), "admins"));
assertTrue(realm.hasRole(new AttributePrincipalImpl("rosencrantz"), "users"));
assertTrue(realm.hasRole(new AttributePrincipalImpl("guildenstern"), "users"));
}
}

View File

@ -0,0 +1,2 @@
rosencrantz=users,admins
guildenstern=users

View File

@ -10,11 +10,18 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-integration-tomcat</artifactId>
<artifactId>cas-client-integration-tomcat-v7</artifactId>
<packaging>jar</packaging>
<name>JA-SIG CAS Client for Java - Tomcat Integration</name>
<name>JA-SIG CAS Client for Java - Tomcat 7.x Integration</name>
<dependencies>
<dependency>
<groupId>org.jasig.cas.client</groupId>
<artifactId>cas-client-integration-tomcat-common</artifactId>
<version>${project.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
@ -32,4 +39,4 @@
</dependency>
</dependencies>
</project>
</project>

View File

@ -0,0 +1,153 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Realm;
import org.apache.catalina.authenticator.AuthenticatorBase;
import org.apache.catalina.connector.Request;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.tomcat.AuthenticatorDelegate;
import org.jasig.cas.client.tomcat.CasRealm;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.validation.TicketValidator;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
/**
* Base authenticator for all authentication protocols supported by CAS.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public abstract class AbstractAuthenticator extends AuthenticatorBase implements LifecycleListener {
protected final Log log = LogFactory.getLog(getClass());
private final AuthenticatorDelegate delegate = new AuthenticatorDelegate();
private String casServerUrlPrefix;
private String encoding;
private boolean encode;
private boolean renew;
protected abstract String getAuthenticationMethod();
protected abstract String getArtifactParameterName();
protected abstract String getServiceParameterName();
protected abstract TicketValidator getTicketValidator();
protected void startInternal() throws LifecycleException {
super.startInternal();
final Realm realm = this.context.getRealm();
if (!(realm instanceof CasRealm)) {
throw new LifecycleException("Expected CasRealm but got " + realm.getInfo());
}
try {
CommonUtils.assertNotNull(this.casServerUrlPrefix, "casServerUrlPrefix cannot be null.");
CommonUtils.assertNotNull(this.delegate.getCasServerLoginUrl(), "casServerLoginUrl cannot be null.");
CommonUtils.assertTrue(
this.delegate.getServerName() != null || this.delegate.getServiceUrl() != null,
"either serverName or serviceUrl must be set.");
this.delegate.setRealm((CasRealm) realm);
} catch (final Exception e) {
throw new LifecycleException(e);
}
// Complete delegate initialization after the component is started.
// See #lifecycleEvent() method.
addLifecycleListener(this);
}
protected final String getCasServerUrlPrefix() {
return this.casServerUrlPrefix;
}
public final void setCasServerUrlPrefix(final String casServerUrlPrefix) {
this.casServerUrlPrefix = casServerUrlPrefix;
}
public final void setCasServerLoginUrl(final String casServerLoginUrl) {
this.delegate.setCasServerLoginUrl(casServerLoginUrl);
}
public final boolean isEncode() {
return this.encode;
}
public final void setEncode(final boolean encode) {
this.encode = encode;
}
protected final boolean isRenew() {
return this.renew;
}
public void setRenew(final boolean renew) {
this.renew = renew;
}
public final void setServerName(final String serverName) {
this.delegate.setServerName(serverName);
}
public final void setServiceUrl(final String serviceUrl) {
this.delegate.setServiceUrl(serviceUrl);
}
protected final String getEncoding() {
return this.encoding;
}
public final void setEncoding(final String encoding) {
this.encoding = encoding;
}
/** {@inheritDoc} */
public final boolean authenticate(final Request request, final HttpServletResponse response, final LoginConfig loginConfig) throws IOException {
Principal principal = request.getUserPrincipal();
boolean result = false;
if (principal == null) {
// Authentication sets the response headers for status and redirect if needed
principal = this.delegate.authenticate(request.getRequest(), response);
if (principal != null) {
request.setAuthType(getAuthenticationMethod());
request.setUserPrincipal(principal);
result = true;
}
} else {
result = true;
}
return result;
}
/** {@inheritDoc} */
public void lifecycleEvent(final LifecycleEvent event) {
if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
this.delegate.setTicketValidator(getTicketValidator());
this.delegate.setArtifactParameterName(getArtifactParameterName());
this.delegate.setServiceParameterName(getServiceParameterName());
}
}
/** {@inheritDoc} */
public String getInfo() {
return getClass().getName() + "/1.0";
}
}

View File

@ -3,10 +3,10 @@
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
package org.jasig.cas.client.tomcat.v7;
/**
*
* Base class for all CAS protocol authenticators.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
@ -14,17 +14,8 @@ package org.jasig.cas.client.tomcat;
*/
public abstract class AbstractCasAuthenticator extends AbstractAuthenticator {
private String encoding;
private String proxyCallbackUrl;
protected final String getEncoding() {
return this.encoding;
}
public final void setEncoding(final String encoding) {
this.encoding = encoding;
}
protected final String getProxyCallbackUrl() {
return this.proxyCallbackUrl;

View File

@ -0,0 +1,65 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat.v7;
import java.security.Principal;
import org.apache.catalina.realm.RealmBase;
import org.jasig.cas.client.tomcat.CasRealm;
/**
* Base <code>Realm</code> implementation for all CAS realms.
*
* @author Marvin S. Addison
* @version $Revision$
*
*/
public abstract class AbstractCasRealm extends RealmBase implements CasRealm {
/** {@inheritDoc} */
public Principal authenticate(final Principal p) {
return getDelegate().authenticate(p);
}
/** {@inheritDoc} */
public String[] getRoles(final Principal p) {
return getDelegate().getRoles(p);
}
/** {@inheritDoc} */
public boolean hasRole(final Principal principal, final String role) {
return getDelegate().hasRole(principal, role);
}
/** {@inheritDoc} */
public String toString() {
return getName();
}
/** {@inheritDoc} */
public String getInfo() {
return getClass().getName() + "/1.0";
}
/** {@inheritDoc} */
protected String getName() {
return getClass().getSimpleName();
}
/** {@inheritDoc} */
protected String getPassword(final String username) {
throw new UnsupportedOperationException();
}
/** {@inheritDoc} */
protected Principal getPrincipal(String username) {
throw new UnsupportedOperationException();
}
/**
* @return Delegate that all {@link CasRealm} operations are delegated to.
*/
protected abstract CasRealm getDelegate();
}

View File

@ -3,7 +3,7 @@
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;

View File

@ -0,0 +1,35 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat.v7;
import org.jasig.cas.client.tomcat.AssertionCasRealmDelegate;
import org.jasig.cas.client.tomcat.CasRealm;
/**
* Tomcat <code>Realm</code> that implements {@link CasRealm} for principal and
* role data backed by the CAS {@link Assertion}.
* <p>
* Authentication always succeeds and simply returns the given principal.
*
* @author Marvin S. Addison
* @version $Revision$
*
*/
public class AssertionCasRealm extends AbstractCasRealm {
private final AssertionCasRealmDelegate delegate = new AssertionCasRealmDelegate();
/**
* @param name Name of the attribute in the principal that contains role data.
*/
public void setRoleAttributeName(final String name) {
delegate.setRoleAttributeName(name);
}
/** {@inheritDoc} */
protected CasRealm getDelegate() {
return delegate;
}
}

View File

@ -3,30 +3,34 @@
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.LifecycleException;
import org.jasig.cas.client.validation.Cas10TicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
/**
* Authenticator that handles CAS 1.0 responses.
* Authenticator that handles CAS 1.0 protocol.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public class Cas10CasAuthenticator extends AbstractCasAuthenticator {
public static final String AUTH_METHOD = "CAS10";
private TicketValidator ticketValidator;
private Cas10TicketValidator ticketValidator;
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}
protected String getAuthenticationMethod() {
return AUTH_METHOD;
}
protected void startInternal() throws LifecycleException {
super.startInternal();
this.ticketValidator = new Cas10TicketValidator(getCasServerUrlPrefix());
}
}

View File

@ -3,26 +3,31 @@
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.LifecycleException;
import org.jasig.cas.client.validation.Cas20ServiceTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
/**
* Authenticator that handles the CAS 2 protocol.
* Authenticator that handles the CAS 2.0 protocol.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public final class Cas20CasAuthenticator extends AbstractCasAuthenticator {
public static final String AUTH_METHOD = "CAS20";
private Cas20ServiceTicketValidator ticketValidator;
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}
protected String getAuthenticationMethod() {
return AUTH_METHOD;
}
protected void startInternal() throws LifecycleException {
super.startInternal();

View File

@ -3,7 +3,7 @@
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.LifecycleException;
import org.jasig.cas.client.util.CommonUtils;
@ -11,14 +11,17 @@ import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
/**
* Authenticator that handles the CAS 2.0 protocol with proxying support.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public final class Cas20ProxyCasAuthenticator extends AbstractCasAuthenticator {
public static final String AUTH_METHOD = "CAS20-PROXY";
private Cas20ProxyTicketValidator ticketValidator;
private boolean acceptAnyProxy;
private String allowedProxyChains;
@ -34,10 +37,13 @@ public final class Cas20ProxyCasAuthenticator extends AbstractCasAuthenticator {
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}
protected String getAuthenticationMethod() {
return AUTH_METHOD;
}
protected void startInternal() throws LifecycleException {
super.startInternal();
this.ticketValidator = new Cas20ProxyTicketValidator(getCasServerUrlPrefix());
this.ticketValidator.setRenew(isRenew());
this.ticketValidator.setProxyCallbackUrl(getProxyCallbackUrl());

View File

@ -0,0 +1,48 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.LifecycleException;
import org.jasig.cas.client.tomcat.CasRealm;
import org.jasig.cas.client.tomcat.PropertiesCasRealmDelegate;
/**
* Tomcat <code>Realm</code> that implements {@link CasRealm} backed by properties file
* containing usernames/and roles of the following format:
* <pre>
* username1=role1,role2,role3
* username2=role1
* username3=role2,role3
* </pre>
* User authentication succeeds if the name of the given principal exists as
* a username in the properties file.
*
* @author Marvin S. Addison
* @version $Revision$
*
*/
public class PropertiesCasRealm extends AbstractCasRealm {
private final PropertiesCasRealmDelegate delegate = new PropertiesCasRealmDelegate();
/**
* @param path Path to properties file container username/role data.
*/
public void setPropertiesFilePath(final String path) {
delegate.setPropertiesFilePath(path);
}
/** {@inheritDoc} */
protected void startInternal() throws LifecycleException {
super.startInternal();
delegate.readProperties();
}
/** {@inheritDoc} */
protected CasRealm getDelegate() {
return delegate;
}
}

View File

@ -3,7 +3,7 @@
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Request;

View File

@ -3,7 +3,7 @@
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Request;

View File

@ -0,0 +1,65 @@
/*
* Copyright 2010 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.LifecycleException;
import org.jasig.cas.client.validation.Saml11TicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
/**
* CAS authenticator that uses the SAML 1.1 protocol.
*
* @author Marvin S. Addison
* @version $Revision$
*
*/
public class Saml11Authenticator extends AbstractAuthenticator {
public static final String AUTH_METHOD = "SAML11";
private Saml11TicketValidator ticketValidator;
/** SAML protocol clock drift tolerance in ms */
private int tolerance = -1;
/**
* @param ms SAML clock drift tolerance in milliseconds.
*/
public void setTolerance(final int ms) {
this.tolerance = ms;
}
protected void startInternal() throws LifecycleException {
super.startInternal();
this.ticketValidator = new Saml11TicketValidator(getCasServerUrlPrefix());
if (this.tolerance > -1) {
this.ticketValidator.setTolerance(this.tolerance);
}
if (getEncoding() != null) {
this.ticketValidator.setEncoding(getEncoding());
}
this.ticketValidator.setRenew(isRenew());
}
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}
protected String getAuthenticationMethod() {
return AUTH_METHOD;
}
/** {@inheritDoc} */
protected String getArtifactParameterName() {
return "SAMLart";
}
/** {@inheritDoc} */
protected String getServiceParameterName() {
return "TARGET";
}
}

View File

@ -3,7 +3,7 @@
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
package org.jasig.cas.client.tomcat.v7;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Request;

View File

@ -1,147 +0,0 @@
/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/index.html
*/
package org.jasig.cas.client.tomcat;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.authenticator.AuthenticatorBase;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.connector.Request;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.util.AbstractCasFilter;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.TicketValidationException;
import org.jasig.cas.client.validation.TicketValidator;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
/**
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public abstract class AbstractAuthenticator extends AuthenticatorBase {
private static final String INFO = "org.jasig.cas.client.tomcat.AbstractAuthenticator/1.0";
private static final Log log = LogFactory.getLog(AbstractAuthenticator.class);
private String casServerLoginUrl;
private String casServerUrlPrefix;
private boolean encode;
private boolean renew;
protected abstract String getArtifactParameterName();
protected abstract String getServiceParameterName();
protected abstract TicketValidator getTicketValidator();
private String serverName;
private String serviceUrl;
protected final String getCasServerUrlPrefix() {
return this.casServerUrlPrefix;
}
protected void startInternal() throws LifecycleException {
super.startInternal();
try {
CommonUtils.assertNotNull(this.casServerUrlPrefix, "casServerUrlPrefix cannot be null.");
CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null.");
CommonUtils.assertTrue(this.serverName != null || this.serviceUrl != null, "either serverName or serviceUrl must be set.");
} catch (final Exception e) {
throw new LifecycleException(e);
}
}
public final void setCasServerUrlPrefix(final String casServerUrlPrefix) {
this.casServerUrlPrefix = casServerUrlPrefix;
}
public final void setCasServerLoginUrl(final String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
public final boolean isEncode() {
return this.encode;
}
public final void setEncode(final boolean encode) {
this.encode = encode;
}
protected final boolean isRenew() {
return this.renew;
}
public void setRenew(final boolean renew) {
this.renew = renew;
}
public final void setServerName(final String serverName) {
this.serverName = serverName;
}
public final void setServiceUrl(final String serviceUrl) {
this.serviceUrl = serviceUrl;
}
public final String getInfo() {
return INFO;
}
public final boolean authenticate(final Request request, final HttpServletResponse response, final LoginConfig loginConfig) throws IOException {
final Principal principal = request.getUserPrincipal();
final String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
if (principal != null && ssoId != null) {
associate(ssoId, request.getSessionInternal(true));
return true;
}
if (ssoId != null && reauthenticateFromSSO(ssoId, request)) {
return true;
}
final String token = request.getParameter(getArtifactParameterName());
final String service = CommonUtils.constructServiceUrl(request, response, this.serviceUrl, this.serverName, getArtifactParameterName(), true);
if (CommonUtils.isBlank(token)) {
final String redirectUrl = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), service, false, false);
response.sendRedirect(redirectUrl);
return false;
}
try {
final Assertion newAssertion = getTicketValidator().validate(token, service);
request.getSession(true).setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, newAssertion);
final Principal p = context.getRealm().authenticate(newAssertion.getPrincipal().getName(), null);
if (p != null) {
register(request, response, p, Constants.SINGLE_SIGN_ON_COOKIE, p.getName(), null);
return true;
}
} catch (final TicketValidationException e) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
return false;
}
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return false;
}
}

View File

@ -139,7 +139,8 @@
<module>cas-client-integration-jboss</module>
<module>cas-client-support-distributed-ehcache</module>
<module>cas-client-support-distributed-memcached</module>
<module>cas-client-integration-tomcat</module>
<module>cas-client-integration-tomcat-common</module>
<module>cas-client-integration-tomcat-v7</module>
</modules>
<properties>