From 6f7ef142bcd0cbea4cd6e4a7d738aa56139314ac Mon Sep 17 00:00:00 2001 From: Misagh Moayyed Date: Fri, 9 Aug 2019 15:04:33 +0430 Subject: [PATCH] add tomcat 9.0.x --- README.md | 16 +- cas-client-integration-tomcat-v90/pom.xml | 99 +++++++++ .../tomcat/v90/AbstractAuthenticator.java | 208 ++++++++++++++++++ .../tomcat/v90/AbstractCasAuthenticator.java | 51 +++++ .../client/tomcat/v90/AbstractCasRealm.java | 76 +++++++ .../tomcat/v90/AbstractLogoutValve.java | 58 +++++ .../client/tomcat/v90/AssertionCasRealm.java | 50 +++++ .../tomcat/v90/Cas10CasAuthenticator.java | 60 +++++ .../tomcat/v90/Cas20CasAuthenticator.java | 66 ++++++ .../v90/Cas20ProxyCasAuthenticator.java | 81 +++++++ .../client/tomcat/v90/PropertiesCasRealm.java | 65 ++++++ .../client/tomcat/v90/ProxyCallbackValve.java | 94 ++++++++ .../tomcat/v90/RegexUriLogoutValve.java | 57 +++++ .../tomcat/v90/Saml11Authenticator.java | 90 ++++++++ .../client/tomcat/v90/SingleSignOutValve.java | 98 +++++++++ .../tomcat/v90/StaticUriLogoutValve.java | 57 +++++ pom.xml | 1 + 17 files changed, 1224 insertions(+), 3 deletions(-) create mode 100644 cas-client-integration-tomcat-v90/pom.xml create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractAuthenticator.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractCasAuthenticator.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractCasRealm.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractLogoutValve.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AssertionCasRealm.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas10CasAuthenticator.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas20CasAuthenticator.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas20ProxyCasAuthenticator.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/PropertiesCasRealm.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/ProxyCallbackValve.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/RegexUriLogoutValve.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Saml11Authenticator.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/SingleSignOutValve.java create mode 100644 cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/StaticUriLogoutValve.java diff --git a/README.md b/README.md index 03a63d2..65785ce 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,16 @@ files in the modules (`cas-client-integration-jboss` and `cas-client-support-dis ``` +- Tomcat 9.0.x is provided by this dependency: + +```xml + + org.jasig.cas.client + cas-client-integration-tomcat-v90 + ${java.cas.client.version} + +``` + - Spring Boot AutoConfiguration is provided by this dependency: ```xml @@ -983,7 +993,7 @@ If you have any trouble, you can enable the log of cas in `jboss-logging.xml` by ``` -## Tomcat 6/7/8 Integration +## Tomcat 6/7/8/9 Integration The client supports container-based CAS authentication and authorization support for the Tomcat servlet container. Suppose a single Tomcat container hosts multiple Web applications with similar authentication and authorization needs. Prior to Tomcat container support, each application would require a similar configuration of CAS servlet filters and authorization configuration in the `web.xml` servlet descriptor. Using the new container-based authentication/authorization feature, a single CAS configuration can be applied to the container and leveraged by all Web applications hosted by the container. @@ -993,8 +1003,8 @@ CAS authentication support for Tomcat is based on the Tomcat-specific Realm comp ### Component Overview In the following discussion of components, only the Tomcat 8.x components are mentioned. Tomcat 8.0.x components are housed inside -`org.jasig.cas.client.tomcat.v8` while Tomcat 8.5.x components are inside `org.jasig.cas.client.tomcat.v85`. You should be able to use -the same exact configuration between the two modules provided package names are adjusted for each release. +`org.jasig.cas.client.tomcat.v8` while Tomcat 8.5.x components are inside `org.jasig.cas.client.tomcat.v85`. Tomcat 9 packages are +available at `org.jasig.cas.client.tomcat.v90`. You should be able to use the same exact configuration between the two modules provided package names are adjusted for each release. The Tomcat 7.0.x and 6.0.x components have exactly the same name, but **are in the tomcat.v7 and tomcat.v6 packages**, e.g. `org.jasig.cas.client.tomcat.v7.Cas20CasAuthenticator` or `org.jasig.cas.client.tomcat.v6.Cas20CasAuthenticator`. diff --git a/cas-client-integration-tomcat-v90/pom.xml b/cas-client-integration-tomcat-v90/pom.xml new file mode 100644 index 0000000..66c0679 --- /dev/null +++ b/cas-client-integration-tomcat-v90/pom.xml @@ -0,0 +1,99 @@ + + + + + cas-client + org.jasig.cas.client + 3.6.0-SNAPSHOT + + 4.0.0 + + cas-client-integration-tomcat-v90 + jar + Jasig CAS Client for Java - Tomcat 9.0.x Integration + + + 9.0.22 + + + + org.jasig.cas.client + cas-client-integration-tomcat-common + ${project.version} + jar + compile + + + org.jasig.cas.client + cas-client-support-saml + ${project.version} + jar + compile + true + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat.version} + jar + provided + + + org.apache.tomcat + tomcat-catalina + ${tomcat.version} + jar + provided + + + org.apache.tomcat + tomcat-servlet-api + + + org.apache.tomcat + tomcat-juli + + + org.apache.tomcat + tomcat-annotations-api + + + org.apache.tomcat + tomcat-api + + + org.apache.tomcat + tomcat-util + + + + + + org.jasig.cas.client + cas-client-core + ${project.version} + jar + compile + + + + diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractAuthenticator.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractAuthenticator.java new file mode 100644 index 0000000..fe8aea1 --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractAuthenticator.java @@ -0,0 +1,208 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.LifecycleEvent; +import org.apache.catalina.LifecycleException; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.LifecycleState; +import org.apache.catalina.Realm; +import org.apache.catalina.authenticator.AuthenticatorBase; +import org.apache.catalina.connector.Request; +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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletResponse; + +import java.io.*; +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 Logger logger = LoggerFactory.getLogger(getClass()); + + private final AuthenticatorDelegate delegate = new AuthenticatorDelegate(); + + private String casServerUrlPrefix; + + private String encoding; + + private boolean encode; + + private boolean renew; + + protected abstract String getAuthenticationMethod(); + + /** + * Provided for Tomcat 7.0.8 support. + * + * @return the authentication method. + */ + @Override + protected String getAuthMethod() { + return getAuthenticationMethod(); + } + + /** + * Abstract method that subclasses should use to provide the name of the artifact parameter (i.e. ticket) + * + * @return the artifact parameter name. CANNOT be NULL. + */ + protected abstract String getArtifactParameterName(); + + /** + * Abstract method that subclasses should use to provide the name of the service parameter (i.e. service) + * + * @return the service parameter name. CANNOT be NULL. + */ + protected abstract String getServiceParameterName(); + + /** + * Returns the single instance of the ticket validator to use to validate tickets. Sub classes should include + * the one appropriate for the + * + * @return a fully configured ticket validator. CANNOT be NULL. + */ + protected abstract TicketValidator getTicketValidator(); + + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + logger.debug("{} starting.", getName()); + final Realm realm = this.context.getRealm(); + try { + CommonUtils.assertTrue(realm instanceof CasRealm, "Expected CasRealm but got " + realm.getClass()); + 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} */ + @Override + protected boolean doAuthenticate(final Request request, + final HttpServletResponse httpServletResponse) 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(), request.getResponse()); + if (principal != null) { + register(request, request.getResponse(), principal, getAuthenticationMethod(), null, null); + result = true; + } + } else { + result = true; + } + return result; + } + + /** {@inheritDoc} */ + @Override + public void lifecycleEvent(final LifecycleEvent event) { + if (AFTER_START_EVENT.equals(event.getType())) { + logger.debug("{} processing lifecycle event {}", getName(), AFTER_START_EVENT); + this.delegate.setTicketValidator(getTicketValidator()); + this.delegate.setArtifactParameterName(getArtifactParameterName()); + this.delegate.setServiceParameterName(getServiceParameterName()); + } + } + + /** {@inheritDoc} */ + public String getInfo() { + return getName() + "/1.0"; + } + + /** {@inheritDoc} + * @throws LifecycleException */ + @Override + protected synchronized void setState(final LifecycleState state, final Object data) throws LifecycleException { + super.setState(state, data); + if (LifecycleState.STARTED.equals(state)) { + logger.info("{} started.", getName()); + } + } + + /** + * @return Authenticator descriptive name. + */ + protected abstract String getName(); +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractCasAuthenticator.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractCasAuthenticator.java new file mode 100644 index 0000000..b29ff66 --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractCasAuthenticator.java @@ -0,0 +1,51 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +/** + * Base class for all CAS protocol authenticators. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public abstract class AbstractCasAuthenticator extends AbstractAuthenticator { + + private String proxyCallbackUrl; + + protected final String getProxyCallbackUrl() { + return this.proxyCallbackUrl; + } + + public final void setProxyCallbackUrl(final String proxyCallbackUrl) { + this.proxyCallbackUrl = proxyCallbackUrl; + } + + @Override + protected final String getArtifactParameterName() { + return "ticket"; + } + + @Override + protected final String getServiceParameterName() { + return "service"; + } + + +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractCasRealm.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractCasRealm.java new file mode 100644 index 0000000..d7f03c7 --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractCasRealm.java @@ -0,0 +1,76 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.Wrapper; +import org.apache.catalina.realm.RealmBase; +import org.jasig.cas.client.tomcat.CasRealm; + +import java.security.Principal; + +/** + * Base Realm implementation for all CAS realms. + * + * @author Marvin S. Addison + * @version $Revision$ + * + */ +public abstract class AbstractCasRealm extends RealmBase implements CasRealm { + + /** {@inheritDoc} */ + @Override + public Principal authenticate(final Principal p) { + return getDelegate().authenticate(p); + } + + /** {@inheritDoc} */ + @Override + public String[] getRoles(final Principal p) { + return getDelegate().getRoles(p); + } + + @Override + public boolean hasRole(final Principal principal, final String role) { + return getDelegate().hasRole(principal, role); + } + + @Override + public boolean hasRole(final Wrapper wrapper, final Principal principal, final String role) { + return hasRole(principal, role); + } + + public String getInfo() { + return getClass().getName() + "/1.0"; + } + + @Override + protected String getPassword(final String userName) { + throw new UnsupportedOperationException(); + } + + @Override + protected Principal getPrincipal(final String userName) { + throw new UnsupportedOperationException(); + } + + /** + * @return Delegate that all {@link CasRealm} operations are delegated to. + */ + protected abstract CasRealm getDelegate(); +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractLogoutValve.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractLogoutValve.java new file mode 100644 index 0000000..549a3af --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AbstractLogoutValve.java @@ -0,0 +1,58 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.jasig.cas.client.tomcat.LogoutHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; + +import java.io.*; + +/** + * Abstract base class for Container-managed log out. Removes the attributes + * from the session. + * + * @author Scott Battaglia + * @author Marvin S. Addison + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public abstract class AbstractLogoutValve extends ValveBase { + + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public final void invoke(final Request request, final Response response) throws IOException, ServletException { + if (getLogoutHandler().isLogoutRequest(request)) { + getLogoutHandler().logout(request, response); + // Do not proceed up valve chain + return; + } + + logger.debug("URI is not a logout request: {}", request.getRequestURI()); + getNext().invoke(request, response); + } + + protected abstract LogoutHandler getLogoutHandler(); +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AssertionCasRealm.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AssertionCasRealm.java new file mode 100644 index 0000000..5a8659b --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/AssertionCasRealm.java @@ -0,0 +1,50 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.jasig.cas.client.tomcat.AssertionCasRealmDelegate; +import org.jasig.cas.client.tomcat.CasRealm; + +/** + * Tomcat Realm that implements {@link CasRealm} for principal and + * role data backed by the CAS {@link org.jasig.cas.client.validation.Assertion}. + *

+ * 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} */ + @Override + protected CasRealm getDelegate() { + return delegate; + } +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas10CasAuthenticator.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas10CasAuthenticator.java new file mode 100644 index 0000000..d7d68a8 --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas10CasAuthenticator.java @@ -0,0 +1,60 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +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 protocol. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class Cas10CasAuthenticator extends AbstractCasAuthenticator { + + public static final String AUTH_METHOD = "CAS10"; + + private static final String NAME = Cas10CasAuthenticator.class.getName(); + + private Cas10TicketValidator ticketValidator; + + @Override + protected TicketValidator getTicketValidator() { + return this.ticketValidator; + } + + @Override + protected String getAuthenticationMethod() { + return AUTH_METHOD; + } + + @Override + protected String getName() { + return NAME; + } + + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.ticketValidator = new Cas10TicketValidator(getCasServerUrlPrefix()); + } +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas20CasAuthenticator.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas20CasAuthenticator.java new file mode 100644 index 0000000..3321f1c --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas20CasAuthenticator.java @@ -0,0 +1,66 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +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.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 static final String NAME = Cas20CasAuthenticator.class.getName(); + + private Cas20ServiceTicketValidator ticketValidator; + + @Override + protected TicketValidator getTicketValidator() { + return this.ticketValidator; + } + + @Override + protected String getAuthenticationMethod() { + return AUTH_METHOD; + } + + @Override + protected String getName() { + return NAME; + } + + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.ticketValidator = new Cas20ServiceTicketValidator(getCasServerUrlPrefix()); + if (getEncoding() != null) { + this.ticketValidator.setEncoding(getEncoding()); + } + this.ticketValidator.setProxyCallbackUrl(getProxyCallbackUrl()); + this.ticketValidator.setProxyGrantingTicketStorage(ProxyCallbackValve.getProxyGrantingTicketStorage()); + this.ticketValidator.setRenew(isRenew()); + } +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas20ProxyCasAuthenticator.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas20ProxyCasAuthenticator.java new file mode 100644 index 0000000..85a33c3 --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Cas20ProxyCasAuthenticator.java @@ -0,0 +1,81 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.util.CommonUtils; +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 static final String NAME = Cas20ProxyCasAuthenticator.class.getName(); + + private Cas20ProxyTicketValidator ticketValidator; + + private boolean acceptAnyProxy; + + private String allowedProxyChains; + + public void setAcceptAnyProxy(final boolean acceptAnyProxy) { + this.acceptAnyProxy = acceptAnyProxy; + } + + public void setAllowedProxyChains(final String allowedProxyChains) { + this.allowedProxyChains = allowedProxyChains; + } + + @Override + protected TicketValidator getTicketValidator() { + return this.ticketValidator; + } + + @Override + protected String getAuthenticationMethod() { + return AUTH_METHOD; + } + + @Override + protected String getName() { + return NAME; + } + + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.ticketValidator = new Cas20ProxyTicketValidator(getCasServerUrlPrefix()); + this.ticketValidator.setRenew(isRenew()); + this.ticketValidator.setProxyCallbackUrl(getProxyCallbackUrl()); + this.ticketValidator.setProxyGrantingTicketStorage(ProxyCallbackValve.getProxyGrantingTicketStorage()); + this.ticketValidator.setAcceptAnyProxy(this.acceptAnyProxy); + this.ticketValidator.setAllowedProxyChains(CommonUtils.createProxyList(this.allowedProxyChains)); + if (getEncoding() != null) { + this.ticketValidator.setEncoding(getEncoding()); + } + } +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/PropertiesCasRealm.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/PropertiesCasRealm.java new file mode 100644 index 0000000..973f4da --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/PropertiesCasRealm.java @@ -0,0 +1,65 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.tomcat.CasRealm; +import org.jasig.cas.client.tomcat.PropertiesCasRealmDelegate; + +/** + * Tomcat Realm that implements {@link CasRealm} backed by properties file + * containing usernames/and roles of the following format: + *

+ * username1=role1,role2,role3
+ * username2=role1
+ * username3=role2,role3
+ * 
+ * User authentication succeeds if the name of the given principal exists as + * a username in the properties file. + * + * @author Marvin S. Addison + * @version $Revision$ + * @since 3.1.12 + * + */ +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) { + this.delegate.setPropertiesFilePath(path); + } + + /** {@inheritDoc} */ + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.delegate.readProperties(); + } + + /** {@inheritDoc} */ + @Override + protected CasRealm getDelegate() { + return this.delegate; + } + +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/ProxyCallbackValve.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/ProxyCallbackValve.java new file mode 100644 index 0000000..2f1ad99 --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/ProxyCallbackValve.java @@ -0,0 +1,94 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.LifecycleException; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; +import org.jasig.cas.client.util.CommonUtils; +import org.jasig.cas.client.util.ReflectUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; + +import java.io.*; + +/** + * Handles watching a url for the proxy callback. + *

+ * Because its tough to share state between valves, we expose the storage mechanism via a static variable. + *

+ * This valve should be ordered before the authentication valves. + * + * @author Scott Battaglia + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class ProxyCallbackValve extends ValveBase { + + private static ProxyGrantingTicketStorage PROXY_GRANTING_TICKET_STORAGE; + + /** Logger instance */ + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private String proxyGrantingTicketStorageClass; + + private String proxyCallbackUrl; + + public static ProxyGrantingTicketStorage getProxyGrantingTicketStorage() { + return PROXY_GRANTING_TICKET_STORAGE; + } + + public void setProxyGrantingTicketStorageClass(final String proxyGrantingTicketStorageClass) { + this.proxyGrantingTicketStorageClass = proxyGrantingTicketStorageClass; + } + + public void setProxyCallbackUrl(final String proxyCallbackUrl) { + this.proxyCallbackUrl = proxyCallbackUrl; + } + + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + + try { + CommonUtils.assertNotNull(this.proxyCallbackUrl, "the proxy callback url cannot be null"); + CommonUtils.assertTrue(this.proxyCallbackUrl.startsWith("/"), "proxy callback url must start with \"/\""); + + PROXY_GRANTING_TICKET_STORAGE = ReflectUtils.newInstance(proxyGrantingTicketStorageClass); + } catch (final Exception e) { + throw new LifecycleException(e); + } + logger.info("Startup completed."); + } + + @Override + public void invoke(final Request request, final Response response) throws IOException, ServletException { + if (this.proxyCallbackUrl.equals(request.getRequestURI())) { + logger.debug("Processing proxy callback request."); + CommonUtils.readAndRespondToProxyReceptorRequest(request, response, PROXY_GRANTING_TICKET_STORAGE); + return; + } + + getNext().invoke(request, response); + } +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/RegexUriLogoutValve.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/RegexUriLogoutValve.java new file mode 100644 index 0000000..0447bbe --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/RegexUriLogoutValve.java @@ -0,0 +1,57 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.tomcat.LogoutHandler; +import org.jasig.cas.client.tomcat.RegexUriLogoutHandler; + +/** + * Performs CAS logout when the request URI matches a regular expression. + * + * @author Scott Battaglia + * @author Marvin S. Addison + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class RegexUriLogoutValve extends AbstractLogoutValve { + + private final RegexUriLogoutHandler logoutHandler = new RegexUriLogoutHandler(); + + public void setRedirectUrl(final String redirectUrl) { + this.logoutHandler.setRedirectUrl(redirectUrl); + } + + public void setLogoutUriRegex(final String regex) { + this.logoutHandler.setLogoutUriRegex(regex); + } + + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.logoutHandler.init(); + logger.info("Startup completed."); + } + + /** {@inheritDoc} */ + @Override + protected LogoutHandler getLogoutHandler() { + return this.logoutHandler; + } +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Saml11Authenticator.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Saml11Authenticator.java new file mode 100644 index 0000000..0004e5c --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/Saml11Authenticator.java @@ -0,0 +1,90 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +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$ + * @since 3.1.12 + * + */ +public final class Saml11Authenticator extends AbstractAuthenticator { + + public static final String AUTH_METHOD = "SAML11"; + + private static final String NAME = Saml11Authenticator.class.getName(); + + 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; + } + + @Override + 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()); + } + + @Override + protected TicketValidator getTicketValidator() { + return this.ticketValidator; + } + + @Override + protected String getAuthenticationMethod() { + return AUTH_METHOD; + } + + /** {@inheritDoc} */ + @Override + protected String getArtifactParameterName() { + return "SAMLart"; + } + + /** {@inheritDoc} */ + @Override + protected String getServiceParameterName() { + return "TARGET"; + } + + @Override + protected String getName() { + return NAME; + } +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/SingleSignOutValve.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/SingleSignOutValve.java new file mode 100644 index 0000000..04326f7 --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/SingleSignOutValve.java @@ -0,0 +1,98 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.LifecycleException; +import org.apache.catalina.Session; +import org.apache.catalina.SessionEvent; +import org.apache.catalina.SessionListener; +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; +import org.apache.catalina.valves.ValveBase; +import org.jasig.cas.client.session.SessionMappingStorage; +import org.jasig.cas.client.session.SingleSignOutHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; + +import java.io.*; + +/** + * Handles logout request messages sent from the CAS server by ending the current + * HTTP session. + * + * @author Marvin S. Addison + * @version $Revision$ $Date$ + * @since 3.1.12 + * + */ +public class SingleSignOutValve extends ValveBase implements SessionListener { + + /** Logger instance */ + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final SingleSignOutHandler handler = new SingleSignOutHandler(); + + public void setArtifactParameterName(final String name) { + this.handler.setArtifactParameterName(name); + } + + public void setLogoutParameterName(final String name) { + this.handler.setLogoutParameterName(name); + } + + public void setRelayStateParameterName(final String name) { + this.handler.setRelayStateParameterName(name); + } + + public void setLogoutCallbackPath(final String logoutCallbackPath) { + this.handler.setLogoutCallbackPath(logoutCallbackPath); + } + + public void setSessionMappingStorage(final SessionMappingStorage storage) { + this.handler.setSessionMappingStorage(storage); + } + + /** {@inheritDoc} */ + @Override + public void invoke(final Request request, final Response response) throws IOException, ServletException { + if (this.handler.process(request, response)) { + getNext().invoke(request, response); + } + } + + /** {@inheritDoc} */ + @Override + public void sessionEvent(final SessionEvent event) { + if (Session.SESSION_DESTROYED_EVENT.equals(event.getType())) { + logger.debug("Cleaning up SessionMappingStorage on destroySession event"); + this.handler.getSessionMappingStorage().removeBySessionById(event.getSession().getId()); + } + } + + /** {@inheritDoc} */ + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + logger.info("Starting..."); + this.handler.init(); + logger.info("Startup completed."); + } +} diff --git a/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/StaticUriLogoutValve.java b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/StaticUriLogoutValve.java new file mode 100644 index 0000000..5c28fe1 --- /dev/null +++ b/cas-client-integration-tomcat-v90/src/main/java/org/jasig/cas/client/tomcat/v90/StaticUriLogoutValve.java @@ -0,0 +1,57 @@ +/** + * Licensed to Apereo under one or more contributor license + * agreements. See the NOTICE file distributed with this work + * for additional information regarding copyright ownership. + * Apereo licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a + * copy of the License at the following location: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jasig.cas.client.tomcat.v90; + +import org.apache.catalina.LifecycleException; +import org.jasig.cas.client.tomcat.LogoutHandler; +import org.jasig.cas.client.tomcat.StaticUriLogoutHandler; + +/** + * Monitors a specific request URI for logout requests. + * + * @author Scott Battaglia + * @author Marvin S. Addison + * @version $Revision$ $Date$ + * @since 3.1.12 + */ +public final class StaticUriLogoutValve extends AbstractLogoutValve { + + private final StaticUriLogoutHandler logoutHandler = new StaticUriLogoutHandler(); + + public void setRedirectUrl(final String redirectUrl) { + this.logoutHandler.setRedirectUrl(redirectUrl); + } + + public void setLogoutUri(final String logoutUri) { + this.logoutHandler.setLogoutUri(logoutUri); + } + + @Override + protected void startInternal() throws LifecycleException { + super.startInternal(); + this.logoutHandler.init(); + logger.info("Startup completed."); + } + + /** {@inheritDoc} */ + @Override + protected LogoutHandler getLogoutHandler() { + return this.logoutHandler; + } +} diff --git a/pom.xml b/pom.xml index 9ec4330..b97fe99 100644 --- a/pom.xml +++ b/pom.xml @@ -304,6 +304,7 @@ cas-client-integration-tomcat-v7 cas-client-integration-tomcat-v8 cas-client-integration-tomcat-v85 + cas-client-integration-tomcat-v90 cas-client-integration-jetty