Fix botched commit of Tomcat 6.x container authentication.
This commit is contained in:
Marvin S. Addison 2010-09-21 15:07:13 +00:00
parent a1b9031416
commit b99b45d1ba
14 changed files with 851 additions and 0 deletions

View File

@ -0,0 +1,154 @@
/*
* 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.v6;
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.connector.Response;
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 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();
public void start() throws LifecycleException {
super.start();
this.log.debug("Starting...");
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 Response 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 (AFTER_START_EVENT.equals(event.getType())) {
this.log.debug("Processing lifecycle event " + AFTER_START_EVENT);
this.delegate.setTicketValidator(getTicketValidator());
this.delegate.setArtifactParameterName(getArtifactParameterName());
this.delegate.setServiceParameterName(getServiceParameterName());
}
}
/** {@inheritDoc} */
public String getInfo() {
return getClass().getName() + "/1.0";
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.v6;
/**
* 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;
}
protected final String getArtifactParameterName() {
return "ticket";
}
protected final String getServiceParameterName() {
return "service";
}
}

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.v6;
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

@ -0,0 +1,57 @@
/*
* 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.v6;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.util.LifecycleSupport;
import org.apache.catalina.valves.ValveBase;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Base <code>Valve</code> implementation for valves that need Catalina lifecycle
* management, including {@link #start()} and {@link #stop()} methods.
*
* @author Marvin S. Addison
* @version $Revision$
*
*/
public abstract class AbstractLifecycleValve extends ValveBase implements Lifecycle {
/** Logger instance */
protected final Log log = LogFactory.getLog(getClass());
/** Lifecycle listeners */
private LifecycleSupport lifecycle = new LifecycleSupport(this);
/** {@inheritDoc} */
public void addLifecycleListener(final LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
/** {@inheritDoc} */
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
/** {@inheritDoc} */
public void removeLifecycleListener(final LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
/** {@inheritDoc} */
public void start() throws LifecycleException {
log.debug("Valve starting.");
}
/** {@inheritDoc} */
public void stop() throws LifecycleException {
log.debug("Valve stopping.");
}
}

View File

@ -0,0 +1,62 @@
/*
* 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.v6;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.jasig.cas.client.util.AbstractCasFilter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Abstract base class for Container-managed log out. Removes the attributes
* from the session.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public abstract class AbstractLogoutValve extends AbstractLifecycleValve {
public final void invoke(final Request request, final Response response) throws IOException, ServletException {
if (!isLogoutRequest(request)) {
log.debug("Current request URI [ " + request.getRequestURI() + "] is not a logout request.");
getNext().invoke(request, response);
return;
}
final HttpSession httpSession = request.getSession(false);
if (httpSession != null) {
httpSession.removeAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
}
final String redirectUrl = constructRedirectUrl(request);
if (redirectUrl != null) {
response.sendRedirect(redirectUrl);
}
}
/**
* Determines if this is a request to destroy the container-managed single sign on session.
*
* @param request the request. CANNOT be NULL.
* @return true if it is a logout request, false otherwise.
*/
protected abstract boolean isLogoutRequest(Request request);
/**
* Constructs a url to redirect to.
*
* @param request the original request.
* @return the url to redirect to. CAN be NULL.
*/
protected abstract String constructRedirectUrl(Request request);
}

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.v6;
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

@ -0,0 +1,38 @@
/*
* 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.v6;
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 class Cas10CasAuthenticator extends AbstractCasAuthenticator {
public static final String AUTH_METHOD = "CAS10";
private Cas10TicketValidator ticketValidator;
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}
protected String getAuthenticationMethod() {
return AUTH_METHOD;
}
public void start() throws LifecycleException {
super.start();
this.ticketValidator = new Cas10TicketValidator(getCasServerUrlPrefix());
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
this.log.debug("Startup completed.");
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.v6;
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 Cas20ServiceTicketValidator ticketValidator;
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}
protected String getAuthenticationMethod() {
return AUTH_METHOD;
}
public void start() throws LifecycleException {
super.start();
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());
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
this.log.debug("Startup completed.");
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.v6;
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 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;
}
protected TicketValidator getTicketValidator() {
return this.ticketValidator;
}
protected String getAuthenticationMethod() {
return AUTH_METHOD;
}
public void start() throws LifecycleException {
super.start();
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());
}
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
this.log.debug("Startup completed.");
}
}

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.v6;
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} */
public void start() throws LifecycleException {
super.start();
delegate.readProperties();
}
/** {@inheritDoc} */
protected CasRealm getDelegate() {
return delegate;
}
}

View File

@ -0,0 +1,70 @@
/*
* 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.v6;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
import org.jasig.cas.client.util.CommonUtils;
import javax.servlet.ServletException;
import java.io.IOException;
/**
* Handles watching a url for the proxy callback.
* <p>
* Because its tough to share state between valves, we expose the storage mechanism via a static variable.
* <p>
* This valve should be ordered before the authentication valves.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public final class ProxyCallbackValve extends AbstractLifecycleValve {
private static ProxyGrantingTicketStorage PROXY_GRANTING_TICKET_STORAGE;
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;
}
public void start() throws LifecycleException {
super.start();
try {
CommonUtils.assertNotNull(this.proxyCallbackUrl, "the proxy callback url cannot be null");
CommonUtils.assertTrue(this.proxyCallbackUrl.startsWith("/"), "proxy callback url must start with \"/\"");
final Class proxyGrantingTicketStorage = Class.forName(proxyGrantingTicketStorageClass);
PROXY_GRANTING_TICKET_STORAGE = (ProxyGrantingTicketStorage) proxyGrantingTicketStorage.newInstance();
} catch (final Exception e) {
throw new LifecycleException(e);
}
}
public void invoke(final Request request, final Response response) throws IOException, ServletException {
if (this.proxyCallbackUrl.equals(request.getRequestURI())) {
CommonUtils.readAndRespondToProxyReceptorRequest(request, response, PROXY_GRANTING_TICKET_STORAGE);
return;
}
getNext().invoke(request, response);
}
}

View File

@ -0,0 +1,57 @@
/*
* 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.v6;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Request;
import org.jasig.cas.client.util.CommonUtils;
import java.util.regex.Pattern;
/**
* Matches a number of urls (based on the regular expression) for handling
* log out.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public final class RegExpBasedLogoutValue extends AbstractLogoutValve {
private String regexpUri;
private Pattern regexpUriPattern;
private String redirectUrl;
public void setRegexpUri(final String regexpUri) {
this.regexpUri = regexpUri;
}
public void setRedirectUrl(final String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public void start() throws LifecycleException {
super.start();
try {
CommonUtils.assertNotNull(this.regexpUri, "A Regular Expression must be provided.");
this.regexpUriPattern = Pattern.compile(this.regexpUri);
} catch (final Exception e) {
throw new LifecycleException(e);
}
}
protected boolean isLogoutRequest(final Request request) {
return this.regexpUriPattern.matcher(request.getRequestURI()).matches();
}
protected String constructRedirectUrl(final Request request) {
return this.redirectUrl;
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.v6;
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;
}
public void start() throws LifecycleException {
super.start();
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());
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
this.log.debug("Startup completed.");
}
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

@ -0,0 +1,60 @@
/*
* 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.v6;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Request;
import org.jasig.cas.client.util.CommonUtils;
/**
* Monitors a specific url for logout requests.
*
* @author Scott Battaglia
* @version $Revision$ $Date$
* @since 3.1.12
*/
public final class UrlBasedLogoutValve extends AbstractLogoutValve {
private String logoutUri;
private String redirectUrl;
/**
* The logout url to watch for logout requests.
*
* @param logoutUri the url. CANNOT be null. MUST be relative and start with "/"
*/
public void setLogoutUri(final String logoutUri) {
this.logoutUri = logoutUri;
}
/**
* Optional url to redirect to after logout is complete.
*
* @param redirectUrl the url. CAN be NULL.
*/
public void setRedirectUrl(final String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public void start() throws LifecycleException {
super.start();
try {
CommonUtils.assertNotNull(this.logoutUri, "logoutUri cannot be null.");
CommonUtils.assertTrue(this.logoutUri.startsWith("/"), "logoutUri must start with \"/\"");
} catch (final IllegalArgumentException e) {
throw new LifecycleException(e);
}
}
protected boolean isLogoutRequest(final Request request) {
return this.logoutUri.equals(request.getRequestURI());
}
protected String constructRedirectUrl(final Request request) {
return redirectUrl;
}
}