Merge branch 'master' of https://github.com/jasig/java-cas-client into CASC-210
This commit is contained in:
commit
7ac4c7afb7
|
|
@ -1,7 +1,7 @@
|
|||
<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/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
<artifactId>cas-client</artifactId>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
|||
|
|
@ -19,10 +19,14 @@
|
|||
package org.jasig.cas.client.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.jasig.cas.client.util.AbstractCasFilter;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.util.ReflectUtils;
|
||||
|
|
@ -42,11 +46,10 @@ import org.jasig.cas.client.validation.Assertion;
|
|||
* <p>Please see AbstractCasFilter for additional properties.</p>
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11768 $ $Date: 2007-02-07 15:44:16 -0500 (Wed, 07 Feb 2007) $
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.0
|
||||
*/
|
||||
public class AuthenticationFilter extends AbstractCasFilter {
|
||||
|
||||
/**
|
||||
* The URL to the CAS Server login.
|
||||
*/
|
||||
|
|
@ -65,7 +68,18 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();
|
||||
|
||||
private AuthenticationRedirectStrategy authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();
|
||||
|
||||
|
||||
private UrlPatternMatcherStrategy ignoreUrlPatternMatcherStrategyClass = null;
|
||||
|
||||
private static final Map<String, Class<? extends UrlPatternMatcherStrategy>> PATTERN_MATCHER_TYPES =
|
||||
new HashMap<String, Class<? extends UrlPatternMatcherStrategy>>();
|
||||
|
||||
static {
|
||||
PATTERN_MATCHER_TYPES.put("CONTAINS", ContainsPatternUrlPatternMatcherStrategy.class);
|
||||
PATTERN_MATCHER_TYPES.put("REGEX", RegexUrlPatternMatcherStrategy.class);
|
||||
PATTERN_MATCHER_TYPES.put("EXACT", ExactUrlPatternMatcherStrategy.class);
|
||||
}
|
||||
|
||||
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
|
||||
if (!isIgnoreInitConfiguration()) {
|
||||
super.initInternal(filterConfig);
|
||||
|
|
@ -75,13 +89,36 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
logger.trace("Loaded renew parameter: {}", this.renew);
|
||||
setGateway(parseBoolean(getPropertyFromInitParams(filterConfig, "gateway", "false")));
|
||||
logger.trace("Loaded gateway parameter: {}", this.gateway);
|
||||
|
||||
|
||||
final String ignorePattern = getPropertyFromInitParams(filterConfig, "ignorePattern", null);
|
||||
logger.trace("Loaded ignorePattern parameter: {}", ignorePattern);
|
||||
|
||||
final String ignoreUrlPatternType = getPropertyFromInitParams(filterConfig, "ignoreUrlPatternType", "REGEX");
|
||||
logger.trace("Loaded ignoreUrlPatternType parameter: {}", ignoreUrlPatternType);
|
||||
|
||||
if (ignorePattern != null) {
|
||||
final Class<? extends UrlPatternMatcherStrategy> ignoreUrlMatcherClass = PATTERN_MATCHER_TYPES.get(ignoreUrlPatternType);
|
||||
if (ignoreUrlMatcherClass != null) {
|
||||
this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlMatcherClass.getName());
|
||||
} else {
|
||||
try {
|
||||
logger.trace("Assuming {} is a qualified class name...", ignoreUrlPatternType);
|
||||
this.ignoreUrlPatternMatcherStrategyClass = ReflectUtils.newInstance(ignoreUrlPatternType);
|
||||
} catch (final IllegalArgumentException e) {
|
||||
logger.error("Could not instantiate class [{}]", ignoreUrlPatternType, e);
|
||||
}
|
||||
}
|
||||
if (this.ignoreUrlPatternMatcherStrategyClass != null) {
|
||||
this.ignoreUrlPatternMatcherStrategyClass.setPattern(ignorePattern);
|
||||
}
|
||||
}
|
||||
|
||||
final String gatewayStorageClass = getPropertyFromInitParams(filterConfig, "gatewayStorageClass", null);
|
||||
|
||||
if (gatewayStorageClass != null) {
|
||||
this.gatewayStorage = ReflectUtils.newInstance(gatewayStorageClass);
|
||||
}
|
||||
|
||||
|
||||
final String authenticationRedirectStrategyClass = getPropertyFromInitParams(filterConfig,
|
||||
"authenticationRedirectStrategyClass", null);
|
||||
|
||||
|
|
@ -98,8 +135,16 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
|
||||
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
|
||||
final HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
final HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
if (isRequestUrlExcluded(request)) {
|
||||
logger.debug("Request is ignored.");
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
final HttpSession session = request.getSession(false);
|
||||
final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
|
||||
|
||||
|
|
@ -151,4 +196,17 @@ public class AuthenticationFilter extends AbstractCasFilter {
|
|||
public final void setGatewayStorage(final GatewayResolver gatewayStorage) {
|
||||
this.gatewayStorage = gatewayStorage;
|
||||
}
|
||||
|
||||
private boolean isRequestUrlExcluded(final HttpServletRequest request) {
|
||||
if (this.ignoreUrlPatternMatcherStrategyClass == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final StringBuffer urlBuffer = request.getRequestURL();
|
||||
if (request.getQueryString() != null) {
|
||||
urlBuffer.append("?").append(request.getQueryString());
|
||||
}
|
||||
final String requestUri = urlBuffer.toString();
|
||||
return this.ignoreUrlPatternMatcherStrategyClass.matches(requestUri);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig 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.authentication;
|
||||
|
||||
/**
|
||||
* A pattern matcher that looks inside the url to find the exact pattern specified.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public final class ContainsPatternUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
|
||||
|
||||
private String pattern;
|
||||
|
||||
public boolean matches(final String url) {
|
||||
return url.contains(this.pattern);
|
||||
}
|
||||
|
||||
public void setPattern(final String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig 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.authentication;
|
||||
|
||||
/**
|
||||
* A pattern matcher that produces a successful match if the pattern
|
||||
* specified matches the given url exactly and equally.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public final class ExactUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
|
||||
|
||||
private String pattern;
|
||||
|
||||
public boolean matches(final String url) {
|
||||
return url.equals(this.pattern);
|
||||
}
|
||||
|
||||
public void setPattern(final String pattern) {
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig 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.authentication;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A pattern matcher that looks inside the url to find the pattern,. that
|
||||
* is assumed to have been specified via regular expressions syntax.
|
||||
*
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public final class RegexUrlPatternMatcherStrategy implements UrlPatternMatcherStrategy {
|
||||
|
||||
private Pattern pattern;
|
||||
|
||||
public boolean matches(final String url) {
|
||||
return this.pattern.matcher(url).find();
|
||||
}
|
||||
|
||||
public void setPattern(final String pattern) {
|
||||
this.pattern = Pattern.compile(pattern);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig 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.authentication;
|
||||
/**
|
||||
* Defines an abstraction by which request urls can be matches against a given pattern.
|
||||
* New instances for all extensions for this strategy interface will be created per
|
||||
* each request. The client will ultimately invoke the {@link #matches(String)} method
|
||||
* having already applied and set the pattern via the {@link #setPattern(String)} method.
|
||||
* The pattern itself will be retrieved via the client configuration.
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public interface UrlPatternMatcherStrategy {
|
||||
/**
|
||||
* Execute the match between the given pattern and the url
|
||||
* @param url the request url typically with query strings included
|
||||
* @return true if match is successful
|
||||
*/
|
||||
boolean matches(String url);
|
||||
|
||||
/**
|
||||
* The pattern against which the url is compared
|
||||
* @param pattern
|
||||
*/
|
||||
void setPattern(String pattern);
|
||||
}
|
||||
|
|
@ -21,6 +21,8 @@ package org.jasig.cas.client.session;
|
|||
import java.io.IOException;
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.jasig.cas.client.util.AbstractConfigurationFilter;
|
||||
|
||||
/**
|
||||
|
|
@ -36,9 +38,15 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
|
|||
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
if (!isIgnoreInitConfiguration()) {
|
||||
handler.setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket"));
|
||||
handler.setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName",
|
||||
SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME));
|
||||
handler.setLogoutParameterName(getPropertyFromInitParams(filterConfig, "logoutParameterName",
|
||||
"logoutRequest"));
|
||||
SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME));
|
||||
handler.setFrontLogoutParameterName(getPropertyFromInitParams(filterConfig, "frontLogoutParameterName",
|
||||
SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME));
|
||||
handler.setRelayStateParameterName(getPropertyFromInitParams(filterConfig, "relayStateParameterName",
|
||||
SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME));
|
||||
handler.setCasServerUrlPrefix(getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null));
|
||||
handler.setArtifactParameterOverPost(parseBoolean(getPropertyFromInitParams(filterConfig,
|
||||
"artifactParameterOverPost", "false")));
|
||||
handler.setEagerlyCreateSessions(parseBoolean(getPropertyFromInitParams(filterConfig,
|
||||
|
|
@ -55,6 +63,18 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
|
|||
handler.setLogoutParameterName(name);
|
||||
}
|
||||
|
||||
public void setFrontLogoutParameterName(final String name) {
|
||||
handler.setFrontLogoutParameterName(name);
|
||||
}
|
||||
|
||||
public void setRelayStateParameterName(final String name) {
|
||||
handler.setRelayStateParameterName(name);
|
||||
}
|
||||
|
||||
public void setCasServerUrlPrefix(final String casServerUrlPrefix) {
|
||||
handler.setCasServerUrlPrefix(casServerUrlPrefix);
|
||||
}
|
||||
|
||||
public void setSessionMappingStorage(final SessionMappingStorage storage) {
|
||||
handler.setSessionMappingStorage(storage);
|
||||
}
|
||||
|
|
@ -62,18 +82,11 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
|
|||
public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
|
||||
final FilterChain filterChain) throws IOException, ServletException {
|
||||
final HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
final HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
if (handler.isTokenRequest(request)) {
|
||||
handler.recordSession(request);
|
||||
} else if (handler.isLogoutRequest(request)) {
|
||||
handler.destroySession(request);
|
||||
// Do not continue up filter chain
|
||||
return;
|
||||
} else {
|
||||
logger.trace("Ignoring URI {}", request.getRequestURI());
|
||||
if (handler.process(request, response)) {
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
|
|
|
|||
|
|
@ -20,12 +20,16 @@ package org.jasig.cas.client.session;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.util.ReflectUtils;
|
||||
import org.jasig.cas.client.util.XmlUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -40,6 +44,13 @@ import org.slf4j.LoggerFactory;
|
|||
*/
|
||||
public final class SingleSignOutHandler {
|
||||
|
||||
public final static String DEFAULT_ARTIFACT_PARAMETER_NAME = "ticket";
|
||||
public final static String DEFAULT_LOGOUT_PARAMETER_NAME = "logoutRequest";
|
||||
public final static String DEFAULT_FRONT_LOGOUT_PARAMETER_NAME = "SAMLRequest";
|
||||
public final static String DEFAULT_RELAY_STATE_PARAMETER_NAME = "RelayState";
|
||||
|
||||
private final static int DECOMPRESSION_FACTOR = 10;
|
||||
|
||||
/** Logger instance */
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
|
|
@ -47,10 +58,19 @@ public final class SingleSignOutHandler {
|
|||
private SessionMappingStorage sessionMappingStorage = new HashMapBackedSessionMappingStorage();
|
||||
|
||||
/** The name of the artifact parameter. This is used to capture the session identifier. */
|
||||
private String artifactParameterName = "ticket";
|
||||
private String artifactParameterName = DEFAULT_ARTIFACT_PARAMETER_NAME;
|
||||
|
||||
/** Parameter name that stores logout request */
|
||||
private String logoutParameterName = "logoutRequest";
|
||||
/** Parameter name that stores logout request for back channel SLO */
|
||||
private String logoutParameterName = DEFAULT_LOGOUT_PARAMETER_NAME;
|
||||
|
||||
/** Parameter name that stores logout request for front channel SLO */
|
||||
private String frontLogoutParameterName = DEFAULT_FRONT_LOGOUT_PARAMETER_NAME;
|
||||
|
||||
/** Parameter name that stores the state of the CAS server webflow for the callback */
|
||||
private String relayStateParameterName = DEFAULT_RELAY_STATE_PARAMETER_NAME;
|
||||
|
||||
/** The prefix url of the CAS server */
|
||||
private String casServerUrlPrefix;
|
||||
|
||||
private boolean artifactParameterOverPost = false;
|
||||
|
||||
|
|
@ -78,12 +98,33 @@ public final class SingleSignOutHandler {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param name Name of parameter containing CAS logout request message.
|
||||
* @param name Name of parameter containing CAS logout request message for back channel SLO.
|
||||
*/
|
||||
public void setLogoutParameterName(final String name) {
|
||||
this.logoutParameterName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param casServerUrlPrefix The prefix url of the CAS server.
|
||||
*/
|
||||
public void setCasServerUrlPrefix(final String casServerUrlPrefix) {
|
||||
this.casServerUrlPrefix = casServerUrlPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of parameter containing CAS logout request message for front channel SLO.
|
||||
*/
|
||||
public void setFrontLogoutParameterName(final String name) {
|
||||
this.frontLogoutParameterName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of parameter containing the state of the CAS server webflow.
|
||||
*/
|
||||
public void setRelayStateParameterName(final String name) {
|
||||
this.relayStateParameterName = name;
|
||||
}
|
||||
|
||||
public void setEagerlyCreateSessions(final boolean eagerlyCreateSessions) {
|
||||
this.eagerlyCreateSessions = eagerlyCreateSessions;
|
||||
}
|
||||
|
|
@ -94,7 +135,10 @@ public final class SingleSignOutHandler {
|
|||
public void init() {
|
||||
CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.logoutParameterName, "logoutParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.frontLogoutParameterName, "frontLogoutParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.sessionMappingStorage, "sessionMappingStorage cannot be null.");
|
||||
CommonUtils.assertNotNull(this.relayStateParameterName, "relayStateParameterName cannot be null.");
|
||||
CommonUtils.assertNotNull(this.casServerUrlPrefix, "casServerUrlPrefix cannot be null.");
|
||||
|
||||
if (this.artifactParameterOverPost) {
|
||||
this.safeParameters = Arrays.asList(this.logoutParameterName, this.artifactParameterName);
|
||||
|
|
@ -110,32 +154,78 @@ public final class SingleSignOutHandler {
|
|||
*
|
||||
* @return True if request contains authentication token, false otherwise.
|
||||
*/
|
||||
public boolean isTokenRequest(final HttpServletRequest request) {
|
||||
private boolean isTokenRequest(final HttpServletRequest request) {
|
||||
return CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.artifactParameterName,
|
||||
this.safeParameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given request is a CAS logout request.
|
||||
* Determines whether the given request is a CAS back channel logout request.
|
||||
*
|
||||
* @param request HTTP request.
|
||||
*
|
||||
* @return True if request is logout request, false otherwise.
|
||||
*/
|
||||
public boolean isLogoutRequest(final HttpServletRequest request) {
|
||||
private boolean isBackChannelLogoutRequest(final HttpServletRequest request) {
|
||||
return "POST".equals(request.getMethod())
|
||||
&& !isMultipartRequest(request)
|
||||
&& CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName,
|
||||
this.safeParameters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given request is a CAS front channel logout request.
|
||||
*
|
||||
* @param request HTTP request.
|
||||
*
|
||||
* @return True if request is logout request, false otherwise.
|
||||
*/
|
||||
private boolean isFrontChannelLogoutRequest(final HttpServletRequest request) {
|
||||
return "GET".equals(request.getMethod())
|
||||
&& CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.frontLogoutParameterName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a request regarding the SLO process: record the session or destroy it.
|
||||
*
|
||||
* @param request the incoming HTTP request.
|
||||
* @param response the HTTP response.
|
||||
* @return if the request should continue to be processed.
|
||||
*/
|
||||
public boolean process(final HttpServletRequest request, final HttpServletResponse response) {
|
||||
if (isTokenRequest(request)) {
|
||||
logger.trace("Received a token request");
|
||||
recordSession(request);
|
||||
return true;
|
||||
|
||||
} else if (isBackChannelLogoutRequest(request)) {
|
||||
logger.trace("Received a back channel logout request");
|
||||
destroySession(request);
|
||||
return false;
|
||||
|
||||
} else if (isFrontChannelLogoutRequest(request)) {
|
||||
logger.trace("Received a front channel logout request");
|
||||
destroySession(request);
|
||||
// redirection url to the CAS server
|
||||
final String redirectionUrl = computeRedirectionToServer(request);
|
||||
if (redirectionUrl != null) {
|
||||
CommonUtils.sendRedirect(response, redirectionUrl);
|
||||
}
|
||||
return false;
|
||||
|
||||
} else {
|
||||
logger.trace("Ignoring URI for logout: {}", request.getRequestURI());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a token request with the current HTTP session by recording the mapping
|
||||
* in the the configured {@link SessionMappingStorage} container.
|
||||
*
|
||||
* @param request HTTP request containing an authentication token.
|
||||
*/
|
||||
public void recordSession(final HttpServletRequest request) {
|
||||
private void recordSession(final HttpServletRequest request) {
|
||||
final HttpSession session = request.getSession(this.eagerlyCreateSessions);
|
||||
|
||||
if (session == null) {
|
||||
|
|
@ -154,14 +244,50 @@ public final class SingleSignOutHandler {
|
|||
sessionMappingStorage.addSessionById(token, session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uncompress a logout message (base64 + deflate).
|
||||
*
|
||||
* @param originalMessage the original logout message.
|
||||
* @return the uncompressed logout message.
|
||||
*/
|
||||
private String uncompressLogoutMessage(final String originalMessage) {
|
||||
final byte[] binaryMessage = Base64.decodeBase64(originalMessage);
|
||||
|
||||
Inflater decompresser = null;
|
||||
try {
|
||||
// decompress the bytes
|
||||
decompresser = new Inflater();
|
||||
decompresser.setInput(binaryMessage);
|
||||
final byte[] result = new byte[binaryMessage.length * DECOMPRESSION_FACTOR];
|
||||
|
||||
final int resultLength = decompresser.inflate(result);
|
||||
|
||||
// decode the bytes into a String
|
||||
return new String(result, 0, resultLength, "UTF-8");
|
||||
} catch (final Exception e) {
|
||||
logger.error("Unable to decompress logout message", e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (decompresser != null) {
|
||||
decompresser.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the current HTTP session for the given CAS logout request.
|
||||
*
|
||||
* @param request HTTP request containing a CAS logout message.
|
||||
*/
|
||||
public void destroySession(final HttpServletRequest request) {
|
||||
final String logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName,
|
||||
this.safeParameters);
|
||||
private void destroySession(final HttpServletRequest request) {
|
||||
final String logoutMessage;
|
||||
// front channel logout -> the message needs to be base64 decoded + decompressed
|
||||
if (isFrontChannelLogoutRequest(request)) {
|
||||
logoutMessage = uncompressLogoutMessage(CommonUtils.safeGetParameter(request,
|
||||
this.frontLogoutParameterName));
|
||||
} else {
|
||||
logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters);
|
||||
}
|
||||
logger.trace("Logout request:\n{}", logoutMessage);
|
||||
|
||||
final String token = XmlUtils.getTextForElement(logoutMessage, "SessionIndex");
|
||||
|
|
@ -187,6 +313,33 @@ public final class SingleSignOutHandler {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the redirection url to the CAS server when it's a front channel SLO
|
||||
* (depending on the relay state parameter).
|
||||
*
|
||||
* @param request The HTTP request.
|
||||
* @return the redirection url to the CAS server.
|
||||
*/
|
||||
private String computeRedirectionToServer(final HttpServletRequest request) {
|
||||
final String relayStateValue = CommonUtils.safeGetParameter(request, this.relayStateParameterName);
|
||||
// if we have a state value -> redirect to the CAS server to continue the logout process
|
||||
if (StringUtils.isNotBlank(relayStateValue)) {
|
||||
final StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(casServerUrlPrefix);
|
||||
if (!this.casServerUrlPrefix.endsWith("/")) {
|
||||
buffer.append("/");
|
||||
}
|
||||
buffer.append("logout?_eventId=next&");
|
||||
buffer.append(this.relayStateParameterName);
|
||||
buffer.append("=");
|
||||
buffer.append(CommonUtils.urlEncode(relayStateValue));
|
||||
final String redirectUrl = buffer.toString();
|
||||
logger.debug("Redirection url to the CAS server: {}", redirectUrl);
|
||||
return redirectUrl;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isMultipartRequest(final HttpServletRequest request) {
|
||||
return request.getContentType() != null && request.getContentType().toLowerCase().startsWith("multipart");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@ import javax.servlet.http.HttpServletResponse;
|
|||
* <p>Please note that one of the two above parameters must be set.</p>
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision$ $Date$
|
||||
* @author Misagh Moayyed
|
||||
* @since 3.1
|
||||
*/
|
||||
public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
||||
|
||||
|
||||
/** Represents the constant for where the assertion will be located in memory. */
|
||||
public static final String CONST_CAS_ASSERTION = "_const_cas_assertion_";
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
|
||||
/** Defines the parameter to look for for the service. */
|
||||
private String serviceParameterName = "service";
|
||||
|
||||
|
||||
/** Sets where response.encodeUrl should be called on service urls when constructed. */
|
||||
private boolean encodeServiceUrl = true;
|
||||
|
||||
|
|
@ -71,12 +71,13 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
logger.trace("Loading serviceParameterName property: {} ", this.serviceParameterName);
|
||||
setEncodeServiceUrl(parseBoolean(getPropertyFromInitParams(filterConfig, "encodeServiceUrl", "true")));
|
||||
logger.trace("Loading encodeServiceUrl property: {}", this.encodeServiceUrl);
|
||||
|
||||
|
||||
initInternal(filterConfig);
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/** Controls the ordering of filter initialization and checking by defining a method that runs before the init.
|
||||
* @param filterConfig the original filter configuration.
|
||||
* @throws ServletException if there is a problem.
|
||||
|
|
@ -147,7 +148,7 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
|
|||
public final String getServiceParameterName() {
|
||||
return this.serviceParameterName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Template method to allow you to change how you retrieve the ticket.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -160,10 +160,19 @@ public final class CommonUtils {
|
|||
*/
|
||||
public static String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName,
|
||||
final String serviceUrl, final boolean renew, final boolean gateway) {
|
||||
return casServerLoginUrl + (casServerLoginUrl.contains("?") ? "&" : "?") + serviceParameterName + "="
|
||||
+ urlEncode(serviceUrl) + (renew ? "&renew=true" : "") + (gateway ? "&gateway=true" : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Url encode a value using UTF-8 encoding.
|
||||
*
|
||||
* @param value the value to encode.
|
||||
* @return the encoded value.
|
||||
*/
|
||||
public static String urlEncode(String value) {
|
||||
try {
|
||||
return casServerLoginUrl + (casServerLoginUrl.contains("?") ? "&" : "?") + serviceParameterName + "="
|
||||
+ URLEncoder.encode(serviceUrl, "UTF-8") + (renew ? "&renew=true" : "")
|
||||
+ (gateway ? "&gateway=true" : "");
|
||||
return URLEncoder.encode(value, "UTF-8");
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
@ -225,6 +234,21 @@ public final class CommonUtils {
|
|||
return serverNames[0];
|
||||
}
|
||||
|
||||
private static boolean serverNameContainsPort(final boolean containsScheme, final String serverName) {
|
||||
if (!containsScheme && serverName.contains(":")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final int schemeIndex = serverName.indexOf(":");
|
||||
final int portIndex = serverName.lastIndexOf(":");
|
||||
return schemeIndex != portIndex;
|
||||
}
|
||||
|
||||
private static boolean requestIsOnStandardPort(final HttpServletRequest request) {
|
||||
final int serverPort = request.getServerPort();
|
||||
return serverPort == 80 || serverPort == 443;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a service url from the HttpServletRequest or from the given
|
||||
* serviceUrl. Prefers the serviceUrl provided if both a serviceUrl and a
|
||||
|
|
@ -250,11 +274,19 @@ public final class CommonUtils {
|
|||
|
||||
final String serverName = findMatchingServerName(request, serverNames);
|
||||
|
||||
boolean containsScheme = true;
|
||||
if (!serverName.startsWith("https://") && !serverName.startsWith("http://")) {
|
||||
buffer.append(request.isSecure() ? "https://" : "http://");
|
||||
containsScheme = false;
|
||||
}
|
||||
|
||||
buffer.append(serverName);
|
||||
|
||||
if (!serverNameContainsPort(containsScheme, serverName) && !requestIsOnStandardPort(request)) {
|
||||
buffer.append(":");
|
||||
buffer.append(request.getServerPort());
|
||||
}
|
||||
|
||||
buffer.append(request.getRequestURI());
|
||||
|
||||
if (CommonUtils.isNotBlank(request.getQueryString())) {
|
||||
|
|
|
|||
|
|
@ -254,4 +254,4 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
|
|||
public final void setUseSession(final boolean useSession) {
|
||||
this.useSession = useSession;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,13 +19,17 @@
|
|||
package org.jasig.cas.client.authentication;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.jasig.cas.client.util.AbstractCasFilter;
|
||||
import org.jasig.cas.client.validation.AssertionImpl;
|
||||
import org.junit.After;
|
||||
|
|
@ -37,7 +41,6 @@ import org.springframework.mock.web.*;
|
|||
* Tests for the AuthenticationFilter.
|
||||
*
|
||||
* @author Scott Battaglia
|
||||
* @version $Revision: 11753 $ $Date: 2007-01-03 13:37:26 -0500 (Wed, 03 Jan 2007) $
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class AuthenticationFilterTests {
|
||||
|
|
@ -50,11 +53,10 @@ public final class AuthenticationFilterTests {
|
|||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// TODO CAS_SERVICE_URL, false, CAS_LOGIN_URL
|
||||
this.filter = new AuthenticationFilter();
|
||||
final MockFilterConfig config = new MockFilterConfig();
|
||||
config.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
config.addInitParameter("service", "https://localhost:8443/service");
|
||||
config.addInitParameter("service", CAS_SERVICE_URL);
|
||||
this.filter.init(config);
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +186,7 @@ public final class AuthenticationFilterTests {
|
|||
final AuthenticationFilter f = new AuthenticationFilter();
|
||||
final MockFilterConfig config = new MockFilterConfig();
|
||||
config.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
config.addInitParameter("service", "https://localhost:8443/service");
|
||||
config.addInitParameter("service", CAS_SERVICE_URL);
|
||||
config.addInitParameter("renew", "true");
|
||||
try {
|
||||
f.init(config);
|
||||
|
|
@ -198,8 +200,8 @@ public final class AuthenticationFilterTests {
|
|||
public void testAllowsRenewContextParam() throws Exception {
|
||||
final AuthenticationFilter f = new AuthenticationFilter();
|
||||
final MockServletContext context = new MockServletContext();
|
||||
context.addInitParameter("casServerLoginUrl", "https://cas.example.com/login");
|
||||
context.addInitParameter("service", "https://localhost:8443/service");
|
||||
context.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
context.addInitParameter("service", CAS_SERVICE_URL);
|
||||
context.addInitParameter("renew", "true");
|
||||
f.init(new MockFilterConfig(context));
|
||||
final Field renewField = AuthenticationFilter.class.getDeclaredField("renew");
|
||||
|
|
@ -211,10 +213,159 @@ public final class AuthenticationFilterTests {
|
|||
public void customRedirectStrategy() throws Exception {
|
||||
final AuthenticationFilter f = new AuthenticationFilter();
|
||||
final MockServletContext context = new MockServletContext();
|
||||
context.addInitParameter("casServerLoginUrl", "https://cas.example.com/login");
|
||||
context.addInitParameter("service", "https://localhost:8443/service");
|
||||
context.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
context.addInitParameter("service", CAS_SERVICE_URL);
|
||||
context.addInitParameter("authenticationRedirectStrategyClass",
|
||||
"org.jasig.cas.client.authentication.FacesCompatibleAuthenticationRedirectStrategy");
|
||||
f.init(new MockFilterConfig(context));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnorePatterns() throws Exception {
|
||||
final AuthenticationFilter f = new AuthenticationFilter();
|
||||
final MockServletContext context = new MockServletContext();
|
||||
context.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
|
||||
context.addInitParameter("ignorePattern", "=valueTo(\\w+)");
|
||||
context.addInitParameter("service", CAS_SERVICE_URL);
|
||||
f.init(new MockFilterConfig(context));
|
||||
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final String URL = CAS_SERVICE_URL + "?param=valueToIgnore";
|
||||
request.setRequestURI(URL);
|
||||
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
final FilterChain filterChain = new FilterChain() {
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
}
|
||||
};
|
||||
|
||||
f.doFilter(request, response, filterChain);
|
||||
assertNull(response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnorePatternsWithContainsMatching() throws Exception {
|
||||
final AuthenticationFilter f = new AuthenticationFilter();
|
||||
final MockServletContext context = new MockServletContext();
|
||||
context.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
|
||||
context.addInitParameter("ignorePattern", "=valueToIgnore");
|
||||
context.addInitParameter("ignoreUrlPatternType", "CONTAINS");
|
||||
context.addInitParameter("service", CAS_SERVICE_URL);
|
||||
f.init(new MockFilterConfig(context));
|
||||
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final String URL = CAS_SERVICE_URL + "?param=valueToIgnore";
|
||||
request.setRequestURI(URL);
|
||||
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
final FilterChain filterChain = new FilterChain() {
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
}
|
||||
};
|
||||
|
||||
f.doFilter(request, response, filterChain);
|
||||
assertNull(response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnorePatternsWithExactMatching() throws Exception {
|
||||
final AuthenticationFilter f = new AuthenticationFilter();
|
||||
final MockServletContext context = new MockServletContext();
|
||||
context.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
|
||||
final URL url = new URL(CAS_SERVICE_URL + "?param=valueToIgnore");
|
||||
|
||||
context.addInitParameter("ignorePattern", url.toExternalForm());
|
||||
context.addInitParameter("ignoreUrlPatternType", "EXACT");
|
||||
context.addInitParameter("service", CAS_SERVICE_URL);
|
||||
f.init(new MockFilterConfig(context));
|
||||
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setScheme(url.getProtocol());
|
||||
request.setServerName(url.getHost());
|
||||
request.setServerPort(url.getPort());
|
||||
request.setQueryString(url.getQuery());
|
||||
request.setRequestURI(url.getPath());
|
||||
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
final FilterChain filterChain = new FilterChain() {
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
}
|
||||
};
|
||||
|
||||
f.doFilter(request, response, filterChain);
|
||||
assertNull(response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnorePatternsWithExactClassname() throws Exception {
|
||||
final AuthenticationFilter f = new AuthenticationFilter();
|
||||
final MockServletContext context = new MockServletContext();
|
||||
context.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
|
||||
context.addInitParameter("ignorePattern", "=valueToIgnore");
|
||||
context.addInitParameter("ignoreUrlPatternType", ContainsPatternUrlPatternMatcherStrategy.class.getName());
|
||||
context.addInitParameter("service", CAS_SERVICE_URL);
|
||||
f.init(new MockFilterConfig(context));
|
||||
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final String URL = CAS_SERVICE_URL + "?param=valueToIgnore";
|
||||
request.setRequestURI(URL);
|
||||
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
final FilterChain filterChain = new FilterChain() {
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
}
|
||||
};
|
||||
|
||||
f.doFilter(request, response, filterChain);
|
||||
assertNull(response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnorePatternsWithInvalidClassname() throws Exception {
|
||||
final AuthenticationFilter f = new AuthenticationFilter();
|
||||
final MockServletContext context = new MockServletContext();
|
||||
context.addInitParameter("casServerLoginUrl", CAS_LOGIN_URL);
|
||||
|
||||
context.addInitParameter("ignorePattern", "=valueToIgnore");
|
||||
context.addInitParameter("ignoreUrlPatternType", "unknown.class.name");
|
||||
context.addInitParameter("service", CAS_SERVICE_URL);
|
||||
f.init(new MockFilterConfig(context));
|
||||
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
final String URL = CAS_SERVICE_URL + "?param=valueToIgnore";
|
||||
request.setRequestURI(URL);
|
||||
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
|
||||
final FilterChain filterChain = new FilterChain() {
|
||||
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
|
||||
}
|
||||
};
|
||||
|
||||
f.doFilter(request, response, filterChain);
|
||||
System.out.println(response.getRedirectedUrl());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package org.jasig.cas.client.session;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Date;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
/**
|
||||
* Logout message generator to perform tests on Single Sign Out feature.
|
||||
* Greatly inspired by the source code in the CAS server itself.
|
||||
*
|
||||
* @author Jerome Leleu
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public final class LogoutMessageGenerator {
|
||||
|
||||
private static final String LOGOUT_REQUEST_TEMPLATE =
|
||||
"<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"00000001\" Version=\"2.0\" "
|
||||
+ "IssueInstant=\"%s\"><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">@NOT_USED@"
|
||||
+ "</saml:NameID><samlp:SessionIndex>%s</samlp:SessionIndex></samlp:LogoutRequest>";
|
||||
|
||||
public static String generateBackChannelLogoutMessage(final String sessionIndex) {
|
||||
return String.format(LOGOUT_REQUEST_TEMPLATE, new Date(), sessionIndex);
|
||||
}
|
||||
|
||||
public static String generateFrontChannelLogoutMessage(final String sessionIndex) {
|
||||
final String logoutMessage = generateBackChannelLogoutMessage(sessionIndex);
|
||||
final Deflater deflater = new Deflater();
|
||||
deflater.setInput(logoutMessage.getBytes(Charset.forName("ASCII")));
|
||||
deflater.finish();
|
||||
final byte[] buffer = new byte[logoutMessage.length()];
|
||||
final int resultSize = deflater.deflate(buffer);
|
||||
final byte[] output = new byte[resultSize];
|
||||
System.arraycopy(buffer, 0, output, 0, resultSize);
|
||||
return Base64.encodeBase64String(output);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig 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.session;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockFilterChain;
|
||||
import org.springframework.mock.web.MockFilterConfig;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
/**
|
||||
* Tests {@link SingleSignOutFilter}.
|
||||
*
|
||||
* @author Jerome Leleu
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public class SingleSignOutFilterTests {
|
||||
|
||||
private final static String CAS_SERVER_URL_PREFIX = "http://myhost.com/mycasserver";
|
||||
private final static String TICKET = "ST-yyyyy";
|
||||
private final static String RELAY_STATE = "e1s1";
|
||||
|
||||
private SingleSignOutFilter filter = new SingleSignOutFilter();
|
||||
private MockHttpServletRequest request;
|
||||
private MockHttpServletResponse response;
|
||||
private MockFilterChain filterChain;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
filter = new SingleSignOutFilter();
|
||||
filter.setCasServerUrlPrefix(CAS_SERVER_URL_PREFIX);
|
||||
filter.setIgnoreInitConfiguration(true);
|
||||
filter.init(new MockFilterConfig());
|
||||
request = new MockHttpServletRequest();
|
||||
response = new MockHttpServletResponse();
|
||||
filterChain = new MockFilterChain();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void initWithoutCasServerUrlPrefix() throws ServletException {
|
||||
filter = new SingleSignOutFilter();
|
||||
filter.init(new MockFilterConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tokenRequest() throws IOException, ServletException {
|
||||
request.setParameter(SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME, TICKET);
|
||||
request.setQueryString(SingleSignOutHandler.DEFAULT_ARTIFACT_PARAMETER_NAME + "=" + TICKET);
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
assertEquals(session, SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().removeSessionByMappingId(TICKET));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backChannelRequest() throws IOException, ServletException {
|
||||
request.setParameter(SingleSignOutHandler.DEFAULT_LOGOUT_PARAMETER_NAME,
|
||||
LogoutMessageGenerator.generateBackChannelLogoutMessage(TICKET));
|
||||
request.setMethod("POST");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
assertNull(SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().removeSessionByMappingId(TICKET));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void frontChannelRequest() throws IOException, ServletException {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(TICKET);
|
||||
request.setParameter(SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME, logoutMessage);
|
||||
request.setQueryString(SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage);
|
||||
request.setMethod("GET");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
assertNull(SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().removeSessionByMappingId(TICKET));
|
||||
assertNull(response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void frontChannelRequestRelayState() throws IOException, ServletException {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(TICKET);
|
||||
request.setParameter(SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME, logoutMessage);
|
||||
request.setParameter(SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME, RELAY_STATE);
|
||||
request.setQueryString(SingleSignOutHandler.DEFAULT_FRONT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage + "&" +
|
||||
SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME + "=" + RELAY_STATE);
|
||||
request.setMethod("GET");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
filter.doFilter(request, response, filterChain);
|
||||
assertNull(SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage().removeSessionByMappingId(TICKET));
|
||||
assertEquals(CAS_SERVER_URL_PREFIX + "/logout?_eventId=next&" +
|
||||
SingleSignOutHandler.DEFAULT_RELAY_STATE_PARAMETER_NAME + "=" + RELAY_STATE, response.getRedirectedUrl());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig 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.session;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
/**
|
||||
* @author Matt Brown <matt.brown@citrix.com>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 3.2.1
|
||||
*/
|
||||
public final class SingleSignOutHandlerTests {
|
||||
|
||||
private final static String ANOTHER_PARAMETER = "anotherParameter";
|
||||
private final static String TICKET = "ST-xxxxxxxx";
|
||||
private final static String URL = "http://mycasserver";
|
||||
private final static String LOGOUT_PARAMETER_NAME = "logoutRequest2";
|
||||
private final static String FRONT_LOGOUT_PARAMETER_NAME = "SAMLRequest2";
|
||||
private final static String RELAY_STATE_PARAMETER_NAME = "RelayState2";
|
||||
private final static String ARTIFACT_PARAMETER_NAME = "ticket2";
|
||||
|
||||
private SingleSignOutHandler handler;
|
||||
private MockHttpServletRequest request;
|
||||
private MockHttpServletResponse response;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
handler = new SingleSignOutHandler();
|
||||
handler.setLogoutParameterName(LOGOUT_PARAMETER_NAME);
|
||||
handler.setFrontLogoutParameterName(FRONT_LOGOUT_PARAMETER_NAME);
|
||||
handler.setRelayStateParameterName(RELAY_STATE_PARAMETER_NAME);
|
||||
handler.setArtifactParameterName(ARTIFACT_PARAMETER_NAME);
|
||||
handler.setCasServerUrlPrefix(URL);
|
||||
handler.init();
|
||||
request = new MockHttpServletRequest();
|
||||
response = new MockHttpServletResponse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tokenRequestFailsIfNoSession() {
|
||||
handler.setEagerlyCreateSessions(false);
|
||||
request.setSession(null);
|
||||
request.setParameter(ARTIFACT_PARAMETER_NAME, TICKET);
|
||||
request.setQueryString(ARTIFACT_PARAMETER_NAME + "=" + TICKET);
|
||||
assertTrue(handler.process(request, response));
|
||||
final SessionMappingStorage storage = handler.getSessionMappingStorage();
|
||||
assertNull(storage.removeSessionByMappingId(TICKET));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tokenRequestFailsIfBadParameter() {
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
request.setParameter(ANOTHER_PARAMETER, TICKET);
|
||||
request.setQueryString(ANOTHER_PARAMETER + "=" + TICKET);
|
||||
assertTrue(handler.process(request, response));
|
||||
final SessionMappingStorage storage = handler.getSessionMappingStorage();
|
||||
assertNull(storage.removeSessionByMappingId(TICKET));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tokenRequestOK() {
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
request.setSession(session);
|
||||
request.setParameter(ARTIFACT_PARAMETER_NAME, TICKET);
|
||||
request.setQueryString(ARTIFACT_PARAMETER_NAME + "=" + TICKET);
|
||||
assertTrue(handler.process(request, response));
|
||||
final SessionMappingStorage storage = handler.getSessionMappingStorage();
|
||||
assertEquals(session, storage.removeSessionByMappingId(TICKET));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backChannelLogoutFailsIfMultipart() {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateBackChannelLogoutMessage(TICKET);
|
||||
request.setParameter(LOGOUT_PARAMETER_NAME, logoutMessage);
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
handler.getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
assertTrue(handler.process(request, response));
|
||||
assertFalse(session.isInvalid());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backChannelLogoutFailsIfNoSessionIndex() {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateBackChannelLogoutMessage("");
|
||||
request.setParameter(LOGOUT_PARAMETER_NAME, logoutMessage);
|
||||
request.setMethod("POST");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
handler.getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
assertFalse(handler.process(request, response));
|
||||
assertFalse(session.isInvalid());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backChannelLogoutOK() {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateBackChannelLogoutMessage(TICKET);
|
||||
request.setParameter(LOGOUT_PARAMETER_NAME, logoutMessage);
|
||||
request.setMethod("POST");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
handler.getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
assertFalse(handler.process(request, response));
|
||||
assertTrue(session.isInvalid());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void frontChannelLogoutFailsIfBadParameter() {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(TICKET);
|
||||
request.setParameter(ANOTHER_PARAMETER, logoutMessage);
|
||||
request.setMethod("GET");
|
||||
request.setQueryString(ANOTHER_PARAMETER + "=" + logoutMessage);
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
handler.getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
assertTrue(handler.process(request, response));
|
||||
assertFalse(session.isInvalid());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void frontChannelLogoutFailsIfNoSessionIndex() {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage("");
|
||||
request.setParameter(FRONT_LOGOUT_PARAMETER_NAME, logoutMessage);
|
||||
request.setQueryString(FRONT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage);
|
||||
request.setMethod("GET");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
handler.getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
assertFalse(handler.process(request, response));
|
||||
assertFalse(session.isInvalid());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void frontChannelLogoutOK() {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(TICKET);
|
||||
request.setParameter(FRONT_LOGOUT_PARAMETER_NAME, logoutMessage);
|
||||
request.setQueryString(FRONT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage);
|
||||
request.setMethod("GET");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
handler.getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
assertFalse(handler.process(request, response));
|
||||
assertTrue(session.isInvalid());
|
||||
assertNull(response.getRedirectedUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void frontChannelLogoutRelayStateOK() {
|
||||
final String logoutMessage = LogoutMessageGenerator.generateFrontChannelLogoutMessage(TICKET);
|
||||
request.setParameter(FRONT_LOGOUT_PARAMETER_NAME, logoutMessage);
|
||||
request.setParameter(RELAY_STATE_PARAMETER_NAME, TICKET);
|
||||
request.setQueryString(FRONT_LOGOUT_PARAMETER_NAME + "=" + logoutMessage + "&" + RELAY_STATE_PARAMETER_NAME + "=" + TICKET);
|
||||
request.setMethod("GET");
|
||||
final MockHttpSession session = new MockHttpSession();
|
||||
handler.getSessionMappingStorage().addSessionById(TICKET, session);
|
||||
assertFalse(handler.process(request, response));
|
||||
assertTrue(session.isInvalid());
|
||||
assertEquals(URL + "/logout?_eventId=next&" + RELAY_STATE_PARAMETER_NAME + "=" + TICKET,
|
||||
response.getRedirectedUrl());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Licensed to Jasig under one or more contributor license
|
||||
* agreements. See the NOTICE file distributed with this work
|
||||
* for additional information regarding copyright ownership.
|
||||
* Jasig 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.session;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author Matt Brown <matt.brown@citrix.com>
|
||||
* @version $Revision$ $Date$
|
||||
* @since 3.2.1
|
||||
*/
|
||||
public final class SingleSignoutHandlerTests {
|
||||
|
||||
private SingleSignOutHandler handler;
|
||||
private MockHttpServletRequest request;
|
||||
private final static String logoutParameterName = "logoutRequest";
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
handler = new SingleSignOutHandler();
|
||||
handler.setLogoutParameterName(logoutParameterName);
|
||||
handler.init();
|
||||
request = new MockHttpServletRequest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLogoutRequest() throws Exception {
|
||||
request.setParameter(logoutParameterName, "true");
|
||||
request.setMethod("POST");
|
||||
|
||||
assertTrue(handler.isLogoutRequest(request));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a multipart request is not considered logoutRequest. Verifies issue CASC-147.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void isLogoutRequestMultipart() throws Exception {
|
||||
request.setParameter(logoutParameterName, "true");
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
|
||||
assertFalse(handler.isLogoutRequest(request));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -136,6 +136,27 @@ public final class CommonUtilsTests extends TestCase {
|
|||
assertEquals(CONST_MY_URL, constructedUrl);
|
||||
}
|
||||
|
||||
private void constructUrlNonStandardPortAndNoPortInConfigTest(final String serverNameList) {
|
||||
final String CONST_MY_URL = "https://www.myserver.com:555/hello/hithere/";
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hello/hithere/");
|
||||
request.addHeader("Host", "www.myserver.com");
|
||||
request.setScheme("https");
|
||||
request.setSecure(true);
|
||||
request.setServerPort(555);
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null,
|
||||
serverNameList, "ticket", false);
|
||||
assertEquals(CONST_MY_URL, constructedUrl);
|
||||
}
|
||||
|
||||
public void testConstructUrlNonStandardPortAndNoScheme() {
|
||||
constructUrlNonStandardPortAndNoPortInConfigTest("www.myserver.com");
|
||||
}
|
||||
|
||||
public void testConstructUrlNonStandardPortAndScheme() {
|
||||
constructUrlNonStandardPortAndNoPortInConfigTest("https://www.myserver.com");
|
||||
}
|
||||
|
||||
public void testConstructUrlWithMultipleHostsNoPortsOrProtocol() {
|
||||
final String CONST_MY_URL = "https://www.myserver.com/hello/hithere/";
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hello/hithere/");
|
||||
|
|
@ -167,4 +188,8 @@ public final class CommonUtilsTests extends TestCase {
|
|||
final String responsedContent = CommonUtils.getResponseFromServer(new URL("http://localhost:8090"), new HttpsURLConnectionFactory(), null);
|
||||
assertEquals(RESPONSE, responsedContent);
|
||||
}
|
||||
|
||||
public void testUrlEncode() {
|
||||
assertEquals("this+is+a+very+special+parameter+with+%3D%25%2F", CommonUtils.urlEncode("this is a very special parameter with =%/"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,4 +54,4 @@ public class Cas10TicketValidationFilterTests {
|
|||
assertTrue(validator instanceof Cas10TicketValidator);
|
||||
assertTrue(((Cas10TicketValidator) validator).isRenew());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -54,4 +54,4 @@ public class Saml11TicketValidationFilterTests {
|
|||
assertTrue(validator instanceof Saml11TicketValidator);
|
||||
assertTrue(((Saml11TicketValidator) validator).isRenew());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -141,4 +141,4 @@ public final class Saml11TicketValidatorTests extends AbstractTicketValidatorTes
|
|||
private Interval currentTimeRangeInterval() {
|
||||
return new Interval(new DateTime(DateTimeZone.UTC).minus(5000), new DateTime(DateTimeZone.UTC).plus(200000000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<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/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
<artifactId>cas-client</artifactId>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<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/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
<artifactId>cas-client</artifactId>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>cas-client</artifactId>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>cas-client</artifactId>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
|||
|
|
@ -45,37 +45,41 @@ public class SingleSignOutValve extends AbstractLifecycleValve implements Sessio
|
|||
private final SingleSignOutHandler handler = new SingleSignOutHandler();
|
||||
|
||||
public void setArtifactParameterName(final String name) {
|
||||
handler.setArtifactParameterName(name);
|
||||
this.handler.setArtifactParameterName(name);
|
||||
}
|
||||
|
||||
public void setLogoutParameterName(final String name) {
|
||||
handler.setLogoutParameterName(name);
|
||||
this.handler.setLogoutParameterName(name);
|
||||
}
|
||||
|
||||
public void setFrontLogoutParameterName(final String name) {
|
||||
this.handler.setFrontLogoutParameterName(name);
|
||||
}
|
||||
|
||||
public void setRelayStateParameterName(final String name) {
|
||||
this.handler.setRelayStateParameterName(name);
|
||||
}
|
||||
|
||||
public void setCasServerUrlPrefix(final String casServerUrlPrefix) {
|
||||
this.handler.setCasServerUrlPrefix(casServerUrlPrefix);
|
||||
}
|
||||
|
||||
public void setSessionMappingStorage(final SessionMappingStorage storage) {
|
||||
handler.setSessionMappingStorage(storage);
|
||||
this.handler.setSessionMappingStorage(storage);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void start() throws LifecycleException {
|
||||
super.start();
|
||||
handler.init();
|
||||
this.handler.init();
|
||||
logger.info("Startup completed.");
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void invoke(final Request request, final Response response) throws IOException, ServletException {
|
||||
if (this.handler.isTokenRequest(request)) {
|
||||
this.handler.recordSession(request);
|
||||
request.getSessionInternal(true).addSessionListener(this);
|
||||
} else if (this.handler.isLogoutRequest(request)) {
|
||||
this.handler.destroySession(request);
|
||||
// Do not proceed up valve chain
|
||||
return;
|
||||
} else {
|
||||
logger.debug("Ignoring URI {}", request.getRequestURI());
|
||||
if (this.handler.process(request, response)) {
|
||||
getNext().invoke(request, response);
|
||||
}
|
||||
getNext().invoke(request, response);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
@ -90,5 +94,4 @@ public class SingleSignOutValve extends AbstractLifecycleValve implements Sessio
|
|||
protected String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>cas-client</artifactId>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
|||
|
|
@ -49,30 +49,34 @@ public class SingleSignOutValve extends ValveBase implements SessionListener {
|
|||
private final SingleSignOutHandler handler = new SingleSignOutHandler();
|
||||
|
||||
public void setArtifactParameterName(final String name) {
|
||||
handler.setArtifactParameterName(name);
|
||||
this.handler.setArtifactParameterName(name);
|
||||
}
|
||||
|
||||
public void setLogoutParameterName(final String name) {
|
||||
handler.setLogoutParameterName(name);
|
||||
this.handler.setLogoutParameterName(name);
|
||||
}
|
||||
|
||||
public void setFrontLogoutParameterName(final String name) {
|
||||
this.handler.setFrontLogoutParameterName(name);
|
||||
}
|
||||
|
||||
public void setRelayStateParameterName(final String name) {
|
||||
this.handler.setRelayStateParameterName(name);
|
||||
}
|
||||
|
||||
public void setCasServerUrlPrefix(final String casServerUrlPrefix) {
|
||||
this.handler.setCasServerUrlPrefix(casServerUrlPrefix);
|
||||
}
|
||||
|
||||
public void setSessionMappingStorage(final SessionMappingStorage storage) {
|
||||
handler.setSessionMappingStorage(storage);
|
||||
this.handler.setSessionMappingStorage(storage);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void invoke(final Request request, final Response response) throws IOException, ServletException {
|
||||
if (this.handler.isTokenRequest(request)) {
|
||||
this.handler.recordSession(request);
|
||||
request.getSessionInternal(true).addSessionListener(this);
|
||||
} else if (this.handler.isLogoutRequest(request)) {
|
||||
this.handler.destroySession(request);
|
||||
// Do not proceed up valve chain
|
||||
return;
|
||||
} else {
|
||||
logger.debug("Ignoring URI {}", request.getRequestURI());
|
||||
if (this.handler.process(request, response)) {
|
||||
getNext().invoke(request, response);
|
||||
}
|
||||
getNext().invoke(request, response);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
|
|
@ -87,7 +91,7 @@ public class SingleSignOutValve extends ValveBase implements SessionListener {
|
|||
protected void startInternal() throws LifecycleException {
|
||||
super.startInternal();
|
||||
logger.info("Starting...");
|
||||
handler.init();
|
||||
this.handler.init();
|
||||
logger.info("Startup completed.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>cas-client</artifactId>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<name>Jasig CAS Client for Java - Distributed Proxy Storage Support: EhCache
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<artifactId>cas-client</artifactId>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
|||
18
pom.xml
18
pom.xml
|
|
@ -2,17 +2,17 @@
|
|||
<parent>
|
||||
<groupId>org.jasig.parent</groupId>
|
||||
<artifactId>jasig-parent</artifactId>
|
||||
<version>38</version>
|
||||
<version>39</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.jasig.cas.client</groupId>
|
||||
<version>3.3.1-SNAPSHOT</version>
|
||||
<version>3.3.2-SNAPSHOT</version>
|
||||
<artifactId>cas-client</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Jasig CAS Client for Java</name>
|
||||
<description>
|
||||
Jasig CAS Client for Java is the integration point forapplications that want to speak with a CAS
|
||||
Jasig CAS Client for Java is the integration point for applications that want to speak with a CAS
|
||||
server, either via the CAS 1.0 or CAS 2.0 protocol.
|
||||
</description>
|
||||
<url>http://www.jasig.org/cas</url>
|
||||
|
|
@ -26,7 +26,8 @@
|
|||
<connection>scm:git:git@github.com:Jasig/java-cas-client.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:Jasig/java-cas-client.git</developerConnection>
|
||||
<url>https://github.com/Jasig/java-cas-client</url>
|
||||
</scm>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<inceptionYear>2006</inceptionYear>
|
||||
|
||||
|
|
@ -103,15 +104,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<configuration>
|
||||
<mavenExecutorId>forked-path</mavenExecutorId>
|
||||
<tagNameFormat>v@{project.version}</tagNameFormat>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
|
|
|
|||
Loading…
Reference in New Issue