parent
74a8cff651
commit
9ffca231a0
|
|
@ -217,12 +217,10 @@ public final class CommonUtils {
|
|||
buffer.append(request.getRequestURI());
|
||||
|
||||
if (CommonUtils.isNotBlank(request.getQueryString())) {
|
||||
final int location = request.getQueryString().indexOf(
|
||||
artifactParameterName + "=");
|
||||
final int location = request.getQueryString().indexOf(artifactParameterName + "=");
|
||||
|
||||
if (location == 0) {
|
||||
final String returnValue = encode ? response.encodeURL(buffer
|
||||
.toString()): buffer.toString();
|
||||
final String returnValue = encode ? response.encodeURL(buffer.toString()): buffer.toString();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("serviceUrl generated: " + returnValue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
package org.jasig.cas.client.util;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
|
@ -104,4 +106,18 @@ public final class CommonUtilsTests extends TestCase {
|
|||
assertFalse(CommonUtils.isNotBlank(null));
|
||||
assertFalse(CommonUtils.isNotBlank(" "));
|
||||
}
|
||||
|
||||
public void testConstructServiceUrlWithTrailingSlash() {
|
||||
final String CONST_MY_URL = "https://www.myserver.com/hello/hithere/";
|
||||
final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hello/hithere/");
|
||||
request.setScheme("https");
|
||||
request.setSecure(true);
|
||||
final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
final String constructedUrl = CommonUtils.constructServiceUrl(request, response, null, "www.myserver.com", "ticket", false);
|
||||
|
||||
assertEquals(CONST_MY_URL, constructedUrl);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@ public final class Saml11TicketValidatorTests extends AbstractTicketValidatorTes
|
|||
" ResponseID=\"_3b62bece2e8da1c10279db04882012ac\"><Status><StatusCode\n" +
|
||||
" Value=\"samlp:Responder\"></StatusCode><StatusMessage>Success</StatusMessage></Status></Response></SOAP-ENV:Body></SOAP-ENV:Envelope>";
|
||||
|
||||
PublicTestHttpServer.instance().content = RESPONSE
|
||||
.getBytes(PublicTestHttpServer.instance().encoding);
|
||||
PublicTestHttpServer.instance().content = RESPONSE.getBytes(PublicTestHttpServer.instance().encoding);
|
||||
try {
|
||||
this.validator.validate("test", "test");
|
||||
fail("ValidationException expected due to 'no' response");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
package org.jasig.cas.client.tomcat;
|
||||
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.apache.catalina.valves.ValveBase;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
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 AbstractLogoutValveBase extends ValveBase {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -3,9 +3,13 @@ package org.jasig.cas.client.tomcat;
|
|||
import org.apache.catalina.authenticator.AuthenticatorBase;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.deploy.LoginConfig;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jasig.cas.client.util.AbstractCasFilter;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
import org.jasig.cas.client.validation.Assertion;
|
||||
import org.jasig.cas.client.validation.TicketValidationException;
|
||||
import org.jasig.cas.client.validation.TicketValidator;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
|
@ -21,6 +25,8 @@ public abstract class CasAuthenticator extends AuthenticatorBase {
|
|||
|
||||
private static final String INFO = "org.jasig.cas.client.tomcat.CasAuthenticator/1.0";
|
||||
|
||||
private static final Log log = LogFactory.getLog(CasAuthenticator.class);
|
||||
|
||||
private String serverName;
|
||||
|
||||
private String serviceUrl;
|
||||
|
|
@ -35,6 +41,8 @@ public abstract class CasAuthenticator extends AuthenticatorBase {
|
|||
|
||||
protected abstract String getServiceParameterName();
|
||||
|
||||
private TicketValidator ticketValidator;
|
||||
|
||||
public String getInfo() {
|
||||
return INFO;
|
||||
}
|
||||
|
|
@ -43,25 +51,38 @@ public abstract class CasAuthenticator extends AuthenticatorBase {
|
|||
final Assertion assertion = (Assertion) request.getSession(true).getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);
|
||||
|
||||
if (assertion != null) {
|
||||
return true;
|
||||
return isKnownUser(assertion);
|
||||
}
|
||||
|
||||
final String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName());
|
||||
|
||||
if (CommonUtils.isBlank(ticket)) {
|
||||
final String serviceUrl = CommonUtils.constructServiceUrl(request, httpServletResponse, this.serviceUrl, this.serverName, getArtifactParameterName(), this.encode);
|
||||
final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), serviceUrl, this.renew, false);
|
||||
|
||||
httpServletResponse.sendRedirect(urlToRedirectTo);
|
||||
return false;
|
||||
}
|
||||
|
||||
final Principal principal = this.context.getRealm().authenticate(null, ticket);
|
||||
|
||||
|
||||
|
||||
return false; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
protected boolean isKnownUser(final Assertion assertion) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isAuthenticatedRequest(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
|
||||
final String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName());
|
||||
final String serviceUrl = CommonUtils.constructServiceUrl(request, response, this.serviceUrl, this.serverName, getArtifactParameterName(), this.encode);
|
||||
|
||||
if (CommonUtils.isBlank(ticket)) {
|
||||
final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), serviceUrl, this.renew, false);
|
||||
response.sendRedirect(urlToRedirectTo);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
final Assertion assertion = this.ticketValidator.validate(ticket, serviceUrl);
|
||||
request.getSession(true).setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, assertion);
|
||||
return isKnownUser(assertion);
|
||||
} catch (final TicketValidationException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
package org.jasig.cas.client.tomcat;
|
||||
|
||||
import org.apache.catalina.LifecycleException;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.apache.catalina.valves.ValveBase;
|
||||
import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
|
||||
import org.jasig.cas.client.util.CommonUtils;
|
||||
|
||||
import 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 ValveBase {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected void startInternal() throws LifecycleException {
|
||||
super.startInternal();
|
||||
|
||||
try {
|
||||
CommonUtils.assertNotNull(this.proxyCallbackUrl, "the proxy callback url cannot be null");
|
||||
CommonUtils.assertTrue(this.proxyCallbackUrl.startsWith("/"), "proxy callback url must start with \"/\"");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.jasig.cas.client.tomcat;
|
||||
|
||||
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 AbstractLogoutValveBase {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected void startInternal() throws LifecycleException {
|
||||
super.startInternal();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
package org.jasig.cas.client.tomcat;
|
||||
|
||||
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 AbstractLogoutValveBase {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected void startInternal() throws LifecycleException {
|
||||
super.startInternal();
|
||||
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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue