diff --git a/.gitignore b/.gitignore
index c9f4a19fa..7c1ccf4cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
!/.project
.project
.settings
+bin
target
*.ipr
*.iml
diff --git a/assembly.xml b/assembly.xml
index 26f7cab12..3bf2928eb 100644
--- a/assembly.xml
+++ b/assembly.xml
@@ -5,81 +5,80 @@
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:
+ 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
+ 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
+ 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.
-->
-
- release
-
- zip
- tar.gz
-
- true
-
-
- unix
- true
- false
- ${basedir}
-
-
- *.xml
- *.txt
-
-
-
-
-
-
-
-
-
- src
- src
- unix
- true
-
+ release
+
+ zip
+ tar.gz
+
+ true
+
+
+ unix
+ true
+ false
+ ${basedir}
+
+
+ *.xml
+ *.txt
+
+
+
+
+
+
+
+
+
+ src
+ src
+ unix
+ true
+
-
- unix
- true
-
- *.xml
-
-
+
+ unix
+ true
+
+ *.xml
+
+
-
- unix
- target/site/apidocs/
- true
- docs
-
- **/*
-
-
-
+
+ unix
+ target/site/apidocs/
+ true
+ docs
+
+ **/*
+
+
+
- true
- true
-
-
- modules
- true
- false
- true
-
-
-
-
+ true
+ true
+
+
+ modules
+ true
+ false
+ true
+
+
+
+
\ No newline at end of file
diff --git a/cas-client-core/pom.xml b/cas-client-core/pom.xml
index 2b25337bb..ffea8c697 100644
--- a/cas-client-core/pom.xml
+++ b/cas-client-core/pom.xml
@@ -1,94 +1,106 @@
-
+
+ org.jasig.cas.client
+ 3.3-SNAPSHOT
+ cas-client
+
+ 4.0.0org.jasig.cas.client
- 3.3-SNAPSHOT
- cas-client
-
- 4.0.0
- org.jasig.cas.client
- cas-client-core
- jar
- Jasig CAS Client for Java - Core
+ cas-client-core
+ jar
+ Jasig CAS Client for Java - Core
-
-
- xml-security
- xmlsec
- 1.3.0
- runtime
- true
-
+
+
+ xml-security
+ xmlsec
+ 1.3.0
+ runtime
+ true
+
-
- org.opensaml
- opensaml
- 1.1
- jar
- provided
- true
-
+
+ org.opensaml
+ opensaml
+ ${opensaml.version}
+ jar
+ compile
+
+
+ org.slf4j
+ jcl-over-slf4j
+
+
+
-
- commons-codec
- commons-codec
- 1.4
- jar
- true
-
+
+ commons-codec
+ commons-codec
+ 1.4
+ jar
+ true
+
-
- org.springframework
- spring-beans
- ${spring.version}
- provided
-
+
+ org.springframework
+ spring-beans
+ ${spring.version}
+ provided
+
-
- org.springframework
- spring-test
- ${spring.version}
- test
-
+
+ org.springframework
+ spring-test
+ ${spring.version}
+ test
+
-
- org.springframework
- spring-core
- ${spring.version}
- test
-
+
+ org.springframework
+ spring-core
+ ${spring.version}
+ test
+
+
+ commons-logging
+ commons-logging
+
+
+
-
- org.springframework
- spring-context
- ${spring.version}
- test
-
+
+ org.springframework
+ spring-context
+ ${spring.version}
+ test
+
-
- log4j
- log4j
- test
- 1.2.15
-
-
- jmxri
- com.sun.jmx
-
-
- com.sun.jdmk
- jmxtools
-
-
- javax.jms
- jms
-
-
-
-
+
+ log4j
+ log4j
+ test
+ 1.2.15
+
+
+ jmxri
+ com.sun.jmx
+
+
+ com.sun.jdmk
+ jmxtools
+
+
+ javax.jms
+ jms
+
+
+
+
-
- 2.5.6.SEC01
-
+
+ 3.1.3.RELEASE
+ 2.5.1-1
+
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipal.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipal.java
index d17c97fd6..3a454501b 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipal.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipal.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.io.Serializable;
@@ -48,6 +47,6 @@ public interface AttributePrincipal extends Principal, Serializable {
* The Map of key/value pairs associated with this principal.
* @return the map of key/value pairs associated with this principal.
*/
- Map getAttributes();
+ Map getAttributes();
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipalImpl.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipalImpl.java
index e93978b39..d4f7d61f1 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipalImpl.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AttributePrincipalImpl.java
@@ -1,48 +1,45 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jasig.cas.client.proxy.ProxyRetriever;
-import org.jasig.cas.client.util.CommonUtils;
-
import java.util.Collections;
import java.util.Map;
+import org.jasig.cas.client.proxy.ProxyRetriever;
+import org.jasig.cas.client.util.CommonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Concrete implementation of the AttributePrincipal interface.
*
* @author Scott Battaglia
- * @version $Revision$ $Date$
* @since 3.1
*/
public class AttributePrincipalImpl extends SimplePrincipal implements AttributePrincipal {
-
- private static final Log LOG = LogFactory.getLog(AttributePrincipalImpl.class);
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AttributePrincipalImpl.class);
/** Unique Id for Serialization */
private static final long serialVersionUID = -1443182634624927187L;
/** Map of key/value pairs about this principal. */
- private final Map attributes;
+ private final Map attributes;
/** The CAS 2 ticket used to retrieve a proxy ticket. */
private final String proxyGrantingTicket;
@@ -56,7 +53,7 @@ public class AttributePrincipalImpl extends SimplePrincipal implements Attribute
* @param name the unique identifier for the principal.
*/
public AttributePrincipalImpl(final String name) {
- this(name, Collections.emptyMap());
+ this(name, Collections. emptyMap());
}
/**
@@ -65,8 +62,8 @@ public AttributePrincipalImpl(final String name) {
* @param name the unique identifier for the principal.
* @param attributes the key/value pairs for this principal.
*/
- public AttributePrincipalImpl(final String name, final Map attributes) {
- this(name, attributes, null, null);
+ public AttributePrincipalImpl(final String name, final Map attributes) {
+ this(name, attributes, null, null);
}
/**
@@ -76,19 +73,21 @@ public AttributePrincipalImpl(final String name, final Map attrib
* @param proxyGrantingTicket the ticket associated with this principal.
* @param proxyRetriever the ProxyRetriever implementation to call back to the CAS server.
*/
- public AttributePrincipalImpl(final String name, final String proxyGrantingTicket, final ProxyRetriever proxyRetriever) {
- this(name, Collections.emptyMap(), proxyGrantingTicket, proxyRetriever);
+ public AttributePrincipalImpl(final String name, final String proxyGrantingTicket,
+ final ProxyRetriever proxyRetriever) {
+ this(name, Collections. emptyMap(), proxyGrantingTicket, proxyRetriever);
}
/**
- * Constructs a new principal witht he supplied name, attributes, and proxying capabilities.
+ * Constructs a new principal with the supplied name, attributes, and proxying capabilities.
*
* @param name the unique identifier for the principal.
* @param attributes the key/value pairs for this principal.
* @param proxyGrantingTicket the ticket associated with this principal.
* @param proxyRetriever the ProxyRetriever implementation to call back to the CAS server.
*/
- public AttributePrincipalImpl(final String name, final Map attributes, final String proxyGrantingTicket, final ProxyRetriever proxyRetriever) {
+ public AttributePrincipalImpl(final String name, final Map attributes,
+ final String proxyGrantingTicket, final ProxyRetriever proxyRetriever) {
super(name);
this.attributes = attributes;
this.proxyGrantingTicket = proxyGrantingTicket;
@@ -97,7 +96,7 @@ public AttributePrincipalImpl(final String name, final Map attrib
CommonUtils.assertNotNull(this.attributes, "attributes cannot be null.");
}
- public Map getAttributes() {
+ public Map getAttributes() {
return this.attributes;
}
@@ -105,8 +104,8 @@ public String getProxyTicketFor(String service) {
if (proxyGrantingTicket != null) {
return this.proxyRetriever.getProxyTicketIdFor(this.proxyGrantingTicket, service);
}
-
- LOG.debug("No ProxyGrantingTicket was supplied, so no Proxy Ticket can be retrieved.");
+
+ LOGGER.debug("No ProxyGrantingTicket was supplied, so no Proxy Ticket can be retrieved.");
return null;
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationFilter.java
index 67f36332b..2e7355655 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationFilter.java
@@ -1,37 +1,32 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 org.jasig.cas.client.util.AbstractCasFilter;
-import org.jasig.cas.client.util.CommonUtils;
-import org.jasig.cas.client.validation.Assertion;
-
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import java.io.IOException;
+import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import java.io.IOException;
+import org.jasig.cas.client.util.AbstractCasFilter;
+import org.jasig.cas.client.util.CommonUtils;
+import org.jasig.cas.client.util.ReflectUtils;
+import org.jasig.cas.client.validation.Assertion;
/**
* Filter implementation to intercept all requests and attempt to authenticate
@@ -66,28 +61,32 @@ public class AuthenticationFilter extends AbstractCasFilter {
* Whether to send the gateway request or not.
*/
private boolean gateway = false;
-
+
private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();
+ private AuthenticationRedirectStrategy authenticationRedirectStrategy = new DefaultAuthenticationRedirectStrategy();
+
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
if (!isIgnoreInitConfiguration()) {
super.initInternal(filterConfig);
setCasServerLoginUrl(getPropertyFromInitParams(filterConfig, "casServerLoginUrl", null));
- log.trace("Loaded CasServerLoginUrl parameter: " + this.casServerLoginUrl);
+ logger.trace("Loaded CasServerLoginUrl parameter: {}", this.casServerLoginUrl);
setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
- log.trace("Loaded renew parameter: " + this.renew);
+ logger.trace("Loaded renew parameter: {}", this.renew);
setGateway(parseBoolean(getPropertyFromInitParams(filterConfig, "gateway", "false")));
- log.trace("Loaded gateway parameter: " + this.gateway);
+ logger.trace("Loaded gateway parameter: {}", this.gateway);
final String gatewayStorageClass = getPropertyFromInitParams(filterConfig, "gatewayStorageClass", null);
if (gatewayStorageClass != null) {
- try {
- this.gatewayStorage = (GatewayResolver) Class.forName(gatewayStorageClass).newInstance();
- } catch (final Exception e) {
- log.error(e,e);
- throw new ServletException(e);
- }
+ this.gatewayStorage = ReflectUtils.newInstance(gatewayStorageClass);
+ }
+
+ final String authenticationRedirectStrategyClass = getPropertyFromInitParams(filterConfig,
+ "authenticationRedirectStrategyClass", null);
+
+ if (authenticationRedirectStrategyClass != null) {
+ this.authenticationRedirectStrategy = ReflectUtils.newInstance(authenticationRedirectStrategyClass);
}
}
}
@@ -97,7 +96,8 @@ public void init() {
CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null.");
}
- public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+ 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;
final HttpSession session = request.getSession(false);
@@ -119,25 +119,21 @@ public final void doFilter(final ServletRequest servletRequest, final ServletRes
final String modifiedServiceUrl;
- log.debug("no ticket and no assertion found");
+ logger.debug("no ticket and no assertion found");
if (this.gateway) {
- log.debug("setting gateway attribute in session");
+ logger.debug("setting gateway attribute in session");
modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
} else {
modifiedServiceUrl = serviceUrl;
}
- if (log.isDebugEnabled()) {
- log.debug("Constructed service url: " + modifiedServiceUrl);
- }
+ logger.debug("Constructed service url: {}", modifiedServiceUrl);
- final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
+ final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
+ getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
- if (log.isDebugEnabled()) {
- log.debug("redirecting to \"" + urlToRedirectTo + "\"");
- }
-
- response.sendRedirect(urlToRedirectTo);
+ logger.debug("redirecting to \"{}\"", urlToRedirectTo);
+ this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo);
}
public final void setRenew(final boolean renew) {
@@ -151,8 +147,8 @@ public final void setGateway(final boolean gateway) {
public final void setCasServerLoginUrl(final String casServerLoginUrl) {
this.casServerLoginUrl = casServerLoginUrl;
}
-
+
public final void setGatewayStorage(final GatewayResolver gatewayStorage) {
- this.gatewayStorage = gatewayStorage;
+ this.gatewayStorage = gatewayStorage;
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationRedirectStrategy.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationRedirectStrategy.java
new file mode 100644
index 000000000..01219b2fe
--- /dev/null
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/AuthenticationRedirectStrategy.java
@@ -0,0 +1,28 @@
+package org.jasig.cas.client.authentication;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Interface to abstract the authentication strategy for redirecting. The traditional method was to always just redirect,
+ * but due to AJAX, etc. we may need to support other strategies. This interface is designed to hold that logic such that
+ * authentication filter class does not get crazily complex.
+ *
+ * @author Scott Battaglia
+ * @since 3.3.0
+ */
+public interface AuthenticationRedirectStrategy {
+
+ /**
+ * Method name is a bit of a misnomer. This method handles "redirection" for a localized version of redirection (i.e. AJAX might mean an XML fragment that contains the url to go to).
+ *
+ * @param request the original HttpServletRequest. MAY NOT BE NULL.
+ * @param response the original HttpServletResponse. MAY NOT BE NULL.
+ * @param potentialRedirectUrl the url that might be used (there are no guarantees of course!)
+ * @throws IOException the exception to throw if there is some type of error. This will bubble up through the filter.
+ */
+ void redirect(HttpServletRequest request, HttpServletResponse response, String potentialRedirectUrl)
+ throws IOException;
+
+}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/DefaultAuthenticationRedirectStrategy.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/DefaultAuthenticationRedirectStrategy.java
new file mode 100644
index 000000000..994b0bc6b
--- /dev/null
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/DefaultAuthenticationRedirectStrategy.java
@@ -0,0 +1,19 @@
+package org.jasig.cas.client.authentication;
+
+import java.io.IOException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Implementation of the {@link AuthenticationRedirectStrategy} class that preserves the original behavior that existed prior to 3.3.0.
+ *
+ * @author Scott Battaglia
+ * @since 3.3.0
+ */
+public final class DefaultAuthenticationRedirectStrategy implements AuthenticationRedirectStrategy {
+
+ public void redirect(final HttpServletRequest request, final HttpServletResponse response,
+ final String potentialRedirectUrl) throws IOException {
+ response.sendRedirect(potentialRedirectUrl);
+ }
+}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/DefaultGatewayResolverImpl.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/DefaultGatewayResolverImpl.java
index 7b363690f..d0d24756d 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/DefaultGatewayResolverImpl.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/DefaultGatewayResolverImpl.java
@@ -1,47 +1,44 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public final class DefaultGatewayResolverImpl implements GatewayResolver {
-
+
public static final String CONST_CAS_GATEWAY = "_const_cas_gateway_";
- public boolean hasGatewayedAlready(final HttpServletRequest request,
- final String serviceUrl) {
- final HttpSession session = request.getSession(false);
-
- if (session == null) {
- return false;
- }
-
- final boolean result = session.getAttribute(CONST_CAS_GATEWAY) != null;
- session.removeAttribute(CONST_CAS_GATEWAY);
- return result;
- }
+ public boolean hasGatewayedAlready(final HttpServletRequest request, final String serviceUrl) {
+ final HttpSession session = request.getSession(false);
+
+ if (session == null) {
+ return false;
+ }
+
+ final boolean result = session.getAttribute(CONST_CAS_GATEWAY) != null;
+ session.removeAttribute(CONST_CAS_GATEWAY);
+ return result;
+ }
- public String storeGatewayInformation(final HttpServletRequest request,
- final String serviceUrl) {
- request.getSession(true).setAttribute(CONST_CAS_GATEWAY, "yes");
- return serviceUrl;
- }
+ public String storeGatewayInformation(final HttpServletRequest request, final String serviceUrl) {
+ request.getSession(true).setAttribute(CONST_CAS_GATEWAY, "yes");
+ return serviceUrl;
+ }
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/FacesCompatibleAuthenticationRedirectStrategy.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/FacesCompatibleAuthenticationRedirectStrategy.java
new file mode 100644
index 000000000..4666bf196
--- /dev/null
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/FacesCompatibleAuthenticationRedirectStrategy.java
@@ -0,0 +1,35 @@
+package org.jasig.cas.client.authentication;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.jasig.cas.client.util.CommonUtils;
+
+/**
+ * Implementation of the redirect strategy that can handle a Faces Ajax request in addition to the standard redirect style.
+ *
+ * @author Scott Battaglia
+ * @since 3.3.0
+ */
+public final class FacesCompatibleAuthenticationRedirectStrategy implements AuthenticationRedirectStrategy {
+
+ private static final String FACES_PARTIAL_AJAX_PARAMETER = "javax.faces.partial.ajax";
+
+ public void redirect(final HttpServletRequest request, final HttpServletResponse response,
+ final String potentialRedirectUrl) throws IOException {
+
+ if (CommonUtils.isNotBlank(request.getParameter(FACES_PARTIAL_AJAX_PARAMETER))) {
+ // this is an ajax request - redirect ajaxly
+ response.setContentType("text/xml");
+ response.setStatus(200);
+
+ final PrintWriter writer = response.getWriter();
+ writer.write("");
+ writer.write(String.format("",
+ potentialRedirectUrl));
+ } else {
+ response.sendRedirect(potentialRedirectUrl);
+ }
+ }
+}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/GatewayResolver.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/GatewayResolver.java
index 9c587fb93..9499a1947 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/GatewayResolver.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/GatewayResolver.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 javax.servlet.http.HttpServletRequest;
@@ -32,21 +31,21 @@
*/
public interface GatewayResolver {
- /**
- * Determines if the request has been gatewayed already. Should also do gateway clean up.
- *
- * @param request the Http Servlet Request
- * @param serviceUrl the service url
- * @return true if yes, false otherwise.
- */
- boolean hasGatewayedAlready(HttpServletRequest request, String serviceUrl);
-
- /**
- * Storage the request for gatewaying and return the service url, which can be modified.
- *
- * @param request the HttpServletRequest.
- * @param serviceUrl the service url
- * @return the potentially modified service url to redirect to
- */
- String storeGatewayInformation(HttpServletRequest request, String serviceUrl);
+ /**
+ * Determines if the request has been gatewayed already. Should also do gateway clean up.
+ *
+ * @param request the Http Servlet Request
+ * @param serviceUrl the service url
+ * @return true if yes, false otherwise.
+ */
+ boolean hasGatewayedAlready(HttpServletRequest request, String serviceUrl);
+
+ /**
+ * Storage the request for gatewaying and return the service url, which can be modified.
+ *
+ * @param request the HttpServletRequest.
+ * @param serviceUrl the service url
+ * @return the potentially modified service url to redirect to
+ */
+ String storeGatewayInformation(HttpServletRequest request, String serviceUrl);
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/Saml11AuthenticationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/Saml11AuthenticationFilter.java
index b0db0c223..6c853ec6a 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/Saml11AuthenticationFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/Saml11AuthenticationFilter.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 javax.servlet.FilterConfig;
@@ -36,8 +35,8 @@ public class Saml11AuthenticationFilter extends AuthenticationFilter {
protected final void initInternal(final FilterConfig filterConfig) throws ServletException {
super.initInternal(filterConfig);
- log.warn("SAML1.1 compliance requires the [artifactParameterName] and [serviceParameterName] to be set to specified values.");
- log.warn("This filter will overwrite any user-provided values (if any are provided)");
+ logger.warn("SAML1.1 compliance requires the [artifactParameterName] and [serviceParameterName] to be set to specified values.");
+ logger.warn("This filter will overwrite any user-provided values (if any are provided)");
setArtifactParameterName("SAMLart");
setServiceParameterName("TARGET");
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/SimpleGroup.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/SimpleGroup.java
index 0abe6029a..37e7f5930 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/SimpleGroup.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/SimpleGroup.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.security.Principal;
@@ -65,7 +64,7 @@ public Enumeration extends Principal> members() {
public boolean removeMember(final Principal user) {
return this.members.remove(user);
}
-
+
public String toString() {
return super.toString() + ": " + members.toString();
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/SimplePrincipal.java b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/SimplePrincipal.java
index fba5e09aa..4f73a7340 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/authentication/SimplePrincipal.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/authentication/SimplePrincipal.java
@@ -1,27 +1,25 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.io.Serializable;
import java.security.Principal;
-
import org.jasig.cas.client.util.CommonUtils;
/**
@@ -63,7 +61,7 @@ public boolean equals(final Object o) {
} else if (!(o instanceof SimplePrincipal)) {
return false;
} else {
- return getName().equals(((SimplePrincipal)o).getName());
+ return getName().equals(((SimplePrincipal) o).getName());
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/jaas/AssertionPrincipal.java b/cas-client-core/src/main/java/org/jasig/cas/client/jaas/AssertionPrincipal.java
index 6abeff65b..8ae58947c 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/jaas/AssertionPrincipal.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/jaas/AssertionPrincipal.java
@@ -1,26 +1,24 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.jaas;
import java.io.Serializable;
-
import org.jasig.cas.client.authentication.SimplePrincipal;
import org.jasig.cas.client.validation.Assertion;
@@ -33,7 +31,7 @@
*
*/
public class AssertionPrincipal extends SimplePrincipal implements Serializable {
-
+
/** AssertionPrincipal.java */
private static final long serialVersionUID = 2288520214366461693L;
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/jaas/CasLoginModule.java b/cas-client-core/src/main/java/org/jasig/cas/client/jaas/CasLoginModule.java
index 58a3e0e36..d181dd97f 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/jaas/CasLoginModule.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/jaas/CasLoginModule.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.jaas;
import java.beans.BeanInfo;
@@ -27,26 +26,19 @@
import java.security.Principal;
import java.security.acl.Group;
import java.util.*;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
+import java.util.concurrent.TimeUnit;
import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.callback.*;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.authentication.SimpleGroup;
import org.jasig.cas.client.authentication.SimplePrincipal;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;
import org.jasig.cas.client.validation.Assertion;
import org.jasig.cas.client.validation.TicketValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* JAAS login module that delegates to a CAS {@link TicketValidator} component
@@ -79,6 +71,8 @@
* for JAAS providers that attempt to periodically reauthenticate to renew principal.
* Since CAS tickets are one-time-use, a cached assertion must be provided on reauthentication.
*
cacheTimeout (optional) - Assertion cache timeout in minutes.
+ *
cacheTimeoutUnit (optional) - Assertion cache timeout unit. Must be one of {@link TimeUnit} enumeration
+ * names, e.g. DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS. Default unit is MINUTES.
*
*
*
@@ -109,14 +103,14 @@
public class CasLoginModule implements LoginModule {
/** Constant for login name stored in shared state. */
public static final String LOGIN_NAME = "javax.security.auth.login.name";
-
+
/**
* Default group name for storing caller principal.
* The default value supports JBoss, but is configurable to hopefully
* support other JEE containers.
*/
public static final String DEFAULT_PRINCIPAL_GROUP_NAME = "CallerPrincipal";
-
+
/**
* Default group name for storing role membership data.
* The default value supports JBoss, but is configurable to hopefully
@@ -129,50 +123,50 @@ public class CasLoginModule implements LoginModule {
*/
public static final int DEFAULT_CACHE_TIMEOUT = 480;
+ /** Default assertion cache timeout unit is minutes. */
+ public static final TimeUnit DEFAULT_CACHE_TIMEOUT_UNIT = TimeUnit.MINUTES;
+
/**
* Stores mapping of ticket to assertion to support JAAS providers that
* attempt to periodically re-authenticate to renew principal. Since
* CAS tickets are one-time-use, a cached assertion must be provided on
* re-authentication.
*/
- protected static final Map ASSERTION_CACHE = new HashMap();
+ protected static final Map ASSERTION_CACHE = new HashMap();
- /** Executor responsible for assertion cache cleanup */
- protected static Executor cacheCleanerExecutor = Executors.newSingleThreadExecutor();
-
/** Logger instance */
- protected final Log log = LogFactory.getLog(getClass());
-
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
+
/** JAAS authentication subject */
protected Subject subject;
-
+
/** JAAS callback handler */
protected CallbackHandler callbackHandler;
-
+
/** CAS ticket validator */
protected TicketValidator ticketValidator;
-
+
/** CAS service parameter used if no service is provided via TextCallback on login */
protected String service;
-
+
/** CAS assertion */
protected Assertion assertion;
-
+
/** CAS ticket credential */
protected TicketCredential ticket;
-
+
/** Login module shared state */
- protected Map sharedState;
-
+ protected Map sharedState;
+
/** Roles to be added to all authenticated principals by default */
protected String[] defaultRoles;
-
+
/** Names of attributes in the CAS assertion that should be used for role data */
protected Set roleAttributeNames = new HashSet();
-
+
/** Name of JAAS Group containing caller principal */
protected String principalGroupName = DEFAULT_PRINCIPAL_GROUP_NAME;
-
+
/** Name of JAAS Group containing role data */
protected String roleGroupName = DEFAULT_ROLE_GROUP_NAME;
@@ -182,8 +176,12 @@ public class CasLoginModule implements LoginModule {
/** Assertion cache timeout in minutes */
protected int cacheTimeout = DEFAULT_CACHE_TIMEOUT;
+ /** Units of cache timeout. */
+ protected TimeUnit cacheTimeoutUnit = DEFAULT_CACHE_TIMEOUT_UNIT;
+
/**
* Initializes the CAS login module.
+ *
* @param subject Authentication subject.
* @param handler Callback handler.
* @param state Shared state map.
@@ -201,55 +199,60 @@ public class CasLoginModule implements LoginModule {
* which by default are single use, reauthentication fails. Assertion caching addresses this
* behavior.
*
cacheTimeout (optional) - assertion cache timeout in minutes.
+ *
cacheTimeoutUnit (optional) - Assertion cache timeout unit. Must be one of {@link TimeUnit} enumeration
+ * names, e.g. DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS. Default unit is MINUTES.
*
*/
+ public final void initialize(final Subject subject, final CallbackHandler handler, final Map state,
+ final Map options) {
-
- public final void initialize(final Subject subject, final CallbackHandler handler, final Map state, final Map options) {
this.assertion = null;
this.callbackHandler = handler;
this.subject = subject;
- this.sharedState = (Map) state;
+ this.sharedState = (Map) state;
this.sharedState = new HashMap(state);
-
+
String ticketValidatorClass = null;
for (final String key : options.keySet()) {
- log.trace("Processing option " + key);
+ logger.trace("Processing option {}", key);
if ("service".equals(key)) {
this.service = (String) options.get(key);
- log.debug("Set service=" + this.service);
+ logger.debug("Set service={}", this.service);
} else if ("ticketValidatorClass".equals(key)) {
ticketValidatorClass = (String) options.get(key);
- log.debug("Set ticketValidatorClass=" + ticketValidatorClass);
+ logger.debug("Set ticketValidatorClass={}", ticketValidatorClass);
} else if ("defaultRoles".equals(key)) {
final String roles = (String) options.get(key);
- log.trace("Got defaultRoles value " + roles);
+ logger.trace("Got defaultRoles value {}", roles);
this.defaultRoles = roles.split(",\\s*");
- log.debug("Set defaultRoles=" + Arrays.asList(this.defaultRoles));
+ logger.debug("Set defaultRoles={}", Arrays.asList(this.defaultRoles));
} else if ("roleAttributeNames".equals(key)) {
final String attrNames = (String) options.get(key);
- log.trace("Got roleAttributeNames value " + attrNames);
+ logger.trace("Got roleAttributeNames value {}", attrNames);
final String[] attributes = attrNames.split(",\\s*");
this.roleAttributeNames.addAll(Arrays.asList(attributes));
- log.debug("Set roleAttributeNames=" + this.roleAttributeNames);
+ logger.debug("Set roleAttributeNames={}", this.roleAttributeNames);
} else if ("principalGroupName".equals(key)) {
this.principalGroupName = (String) options.get(key);
- log.debug("Set principalGroupName=" + this.principalGroupName);
+ logger.debug("Set principalGroupName={}", this.principalGroupName);
} else if ("roleGroupName".equals(key)) {
this.roleGroupName = (String) options.get(key);
- log.debug("Set roleGroupName=" + this.roleGroupName);
+ logger.debug("Set roleGroupName={}", this.roleGroupName);
} else if ("cacheAssertions".equals(key)) {
this.cacheAssertions = Boolean.parseBoolean((String) options.get(key));
- log.debug("Set cacheAssertions=" + this.cacheAssertions);
+ logger.debug("Set cacheAssertions={}", this.cacheAssertions);
} else if ("cacheTimeout".equals(key)) {
this.cacheTimeout = Integer.parseInt((String) options.get(key));
- log.debug("Set cacheTimeout=" + this.cacheTimeout);
+ logger.debug("Set cacheTimeout={}", this.cacheTimeout);
+ } else if ("cacheTimeoutUnit".equals(key)) {
+ this.cacheTimeoutUnit = Enum.valueOf(TimeUnit.class, (String) options.get(key));
+ logger.debug("Set cacheTimeoutUnit={}", this.cacheTimeoutUnit);
}
}
if (this.cacheAssertions) {
- cacheCleanerExecutor.execute(new CacheCleaner());
+ cleanCache();
}
CommonUtils.assertNotNull(ticketValidatorClass, "ticketValidatorClass is required.");
@@ -275,10 +278,10 @@ protected void postLogin(final boolean result) {
}
public final boolean login() throws LoginException {
- log.debug("Performing login.");
+ logger.debug("Performing login.");
if (!preLogin()) {
- log.debug("preLogin failed.");
+ logger.debug("preLogin failed.");
return false;
}
@@ -289,46 +292,46 @@ public final boolean login() throws LoginException {
try {
this.callbackHandler.handle(new Callback[] { ticketCallback, serviceCallback });
} catch (final IOException e) {
- log.info("Login failed due to IO exception in callback handler: " + e);
+ logger.info("Login failed due to IO exception in callback handler: {}", e);
throw (LoginException) new LoginException("IO exception in callback handler: " + e).initCause(e);
} catch (final UnsupportedCallbackException e) {
- log.info("Login failed due to unsupported callback: " + e);
- throw (LoginException) new LoginException("Callback handler does not support PasswordCallback and TextInputCallback.").initCause(e);
+ logger.info("Login failed due to unsupported callback: {}", e);
+ throw (LoginException) new LoginException(
+ "Callback handler does not support PasswordCallback and TextInputCallback.").initCause(e);
}
if (ticketCallback.getPassword() != null) {
this.ticket = new TicketCredential(new String(ticketCallback.getPassword()));
- final String service = CommonUtils.isNotBlank(serviceCallback.getName()) ? serviceCallback.getName() : this.service;
+ final String service = CommonUtils.isNotBlank(serviceCallback.getName()) ? serviceCallback.getName()
+ : this.service;
if (this.cacheAssertions) {
- synchronized(ASSERTION_CACHE) {
- if (ASSERTION_CACHE.get(ticket) != null) {
- log.debug("Assertion found in cache.");
- this.assertion = ASSERTION_CACHE.get(ticket);
- }
+ this.assertion = ASSERTION_CACHE.get(ticket);
+ if (this.assertion != null) {
+ logger.debug("Assertion found in cache.");
}
}
if (this.assertion == null) {
- log.debug("CAS assertion is null; ticket validation required.");
+ logger.debug("CAS assertion is null; ticket validation required.");
if (CommonUtils.isBlank(service)) {
- log.info("Login failed because required CAS service parameter not provided.");
- throw new LoginException("Neither login module nor callback handler provided required service parameter.");
+ logger.info("Login failed because required CAS service parameter not provided.");
+ throw new LoginException(
+ "Neither login module nor callback handler provided required service parameter.");
}
try {
- if (log.isDebugEnabled()) {
- log.debug("Attempting ticket validation with service=" + service + " and ticket=" + ticket);
- }
+ logger.debug("Attempting ticket validation with service={} and ticket={}", service,
+ this.ticket);
this.assertion = this.ticketValidator.validate(this.ticket.getName(), service);
} catch (final Exception e) {
- log.info("Login failed due to CAS ticket validation failure: " + e);
+ logger.info("Login failed due to CAS ticket validation failure: {}", e);
throw (LoginException) new LoginException("CAS ticket validation failed: " + e).initCause(e);
}
}
- log.info("Login succeeded.");
+ logger.info("Login succeeded.");
} else {
- log.info("Login failed because callback handler did not provide CAS ticket.");
+ logger.info("Login failed because callback handler did not provide CAS ticket.");
throw new LoginException("Callback handler did not provide CAS ticket.");
}
result = true;
@@ -380,7 +383,8 @@ public final boolean commit() throws LoginException {
throw new LoginException("Ticket credential not found.");
}
- final AssertionPrincipal casPrincipal = new AssertionPrincipal(this.assertion.getPrincipal().getName(), this.assertion);
+ final AssertionPrincipal casPrincipal = new AssertionPrincipal(this.assertion.getPrincipal().getName(),
+ this.assertion);
this.subject.getPrincipals().add(casPrincipal);
// Add group containing principal as sole member
@@ -396,7 +400,7 @@ public final boolean commit() throws LoginException {
roleGroup.addMember(new SimplePrincipal(defaultRole));
}
- final Map attributes = this.assertion.getPrincipal().getAttributes();
+ final Map attributes = this.assertion.getPrincipal().getAttributes();
for (final String key : attributes.keySet()) {
if (this.roleAttributeNames.contains(key)) {
// Attribute value is Object if singular or Collection if plural
@@ -415,16 +419,10 @@ public final boolean commit() throws LoginException {
// Place principal name in shared state for downstream JAAS modules (module chaining use case)
this.sharedState.put(LOGIN_NAME, assertion.getPrincipal().getName());
- if (log.isDebugEnabled()) {
- if (log.isDebugEnabled()) {
- log.debug("Created JAAS subject with principals: " + subject.getPrincipals());
- }
- }
+ logger.debug("Created JAAS subject with principals: {}", subject.getPrincipals());
if (this.cacheAssertions) {
- if (log.isDebugEnabled()) {
- log.debug("Caching assertion for principal " + this.assertion.getPrincipal());
- }
+ logger.debug("Caching assertion for principal {}", this.assertion.getPrincipal());
ASSERTION_CACHE.put(this.ticket, this.assertion);
}
} else {
@@ -442,7 +440,7 @@ public final boolean commit() throws LoginException {
}
public final boolean logout() throws LoginException {
- log.debug("Performing logout.");
+ logger.debug("Performing logout.");
if (!preLogout()) {
return false;
@@ -452,11 +450,11 @@ public final boolean logout() throws LoginException {
removePrincipalsOfType(AssertionPrincipal.class);
removePrincipalsOfType(SimplePrincipal.class);
removePrincipalsOfType(SimpleGroup.class);
-
+
// Remove all CAS credentials
removeCredentialsOfType(TicketCredential.class);
- log.info("Logout succeeded.");
+ logger.info("Logout succeeded.");
postLogout();
return true;
@@ -478,39 +476,40 @@ protected void postLogout() {
// template method
}
-
/**
* Creates a {@link TicketValidator} instance from a class name and map of property name/value pairs.
* @param className Fully-qualified name of {@link TicketValidator} concrete class.
* @param propertyMap Map of property name/value pairs to set on validator instance.
* @return Ticket validator with properties set.
*/
- private TicketValidator createTicketValidator(final String className, final Map propertyMap) {
- CommonUtils.assertTrue(propertyMap.containsKey("casServerUrlPrefix"), "Required property casServerUrlPrefix not found.");
+ private TicketValidator createTicketValidator(final String className, final Map propertyMap) {
+ CommonUtils.assertTrue(propertyMap.containsKey("casServerUrlPrefix"),
+ "Required property casServerUrlPrefix not found.");
final Class validatorClass = ReflectUtils.loadClass(className);
- final TicketValidator validator = ReflectUtils.newInstance(validatorClass, propertyMap.get("casServerUrlPrefix"));
+ final TicketValidator validator = ReflectUtils.newInstance(validatorClass,
+ propertyMap.get("casServerUrlPrefix"));
try {
final BeanInfo info = Introspector.getBeanInfo(validatorClass);
for (final String property : propertyMap.keySet()) {
if (!"casServerUrlPrefix".equals(property)) {
- log.debug("Attempting to set TicketValidator property " + property);
+ logger.debug("Attempting to set TicketValidator property {}", property);
final String value = (String) propertyMap.get(property);
final PropertyDescriptor pd = ReflectUtils.getPropertyDescriptor(info, property);
if (pd != null) {
- ReflectUtils.setProperty(property, convertIfNecessary(pd, value), validator, info);
- log.debug("Set " + property + "=" + value);
+ ReflectUtils.setProperty(property, convertIfNecessary(pd, value), validator, info);
+ logger.debug("Set {} = {}", property, value);
} else {
- log.warn("Cannot find property " + property + " on " + className);
+ logger.warn("Cannot find property {} on {}", property, className);
}
}
}
} catch (final IntrospectionException e) {
throw new RuntimeException("Error getting bean info for " + validatorClass, e);
}
-
+
return validator;
}
@@ -534,7 +533,8 @@ private static Object convertIfNecessary(final PropertyDescriptor pd, final Stri
} else if (long.class.equals(pd.getPropertyType())) {
return new Long(value);
} else {
- throw new IllegalArgumentException("No conversion strategy exists for property " + pd.getName() + " of type " + pd.getPropertyType());
+ throw new IllegalArgumentException("No conversion strategy exists for property " + pd.getName()
+ + " of type " + pd.getPropertyType());
}
}
@@ -554,26 +554,21 @@ private void removeCredentialsOfType(final Class extends Principal> clazz) {
this.subject.getPrivateCredentials().removeAll(this.subject.getPrivateCredentials(clazz));
}
- /** Removes expired entries from the assertion cache. */
- private class CacheCleaner implements Runnable {
- public void run() {
- if (log.isDebugEnabled()) {
- log.debug("Cleaning assertion cache of size " + CasLoginModule.ASSERTION_CACHE.size());
- }
- final Iterator> iter =
- CasLoginModule.ASSERTION_CACHE.entrySet().iterator();
- final Calendar cutoff = Calendar.getInstance();
- cutoff.add(Calendar.MINUTE, -CasLoginModule.this.cacheTimeout);
- while (iter.hasNext()) {
- final Assertion assertion = iter.next().getValue();
- final Calendar created = Calendar.getInstance();
- created.setTime(assertion.getValidFromDate());
- if (created.before(cutoff)) {
- if (log.isDebugEnabled()) {
- log.debug("Removing expired assertion for principal " + assertion.getPrincipal());
- }
- iter.remove();
- }
+ /**
+ * Removes expired entries from the assertion cache.
+ */
+ private void cleanCache() {
+ logger.debug("Cleaning assertion cache of size {}", ASSERTION_CACHE.size());
+ final Iterator> iter = ASSERTION_CACHE.entrySet().iterator();
+ final Calendar cutoff = Calendar.getInstance();
+ cutoff.setTimeInMillis(System.currentTimeMillis() - this.cacheTimeoutUnit.toMillis(this.cacheTimeout));
+ while (iter.hasNext()) {
+ final Assertion assertion = iter.next().getValue();
+ final Calendar created = Calendar.getInstance();
+ created.setTime(assertion.getValidFromDate());
+ if (created.before(cutoff)) {
+ logger.debug("Removing expired assertion for principal {}", assertion.getPrincipal());
+ iter.remove();
}
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/jaas/ServiceAndTicketCallbackHandler.java b/cas-client-core/src/main/java/org/jasig/cas/client/jaas/ServiceAndTicketCallbackHandler.java
index 62bced724..7fc88ef4f 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/jaas/ServiceAndTicketCallbackHandler.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/jaas/ServiceAndTicketCallbackHandler.java
@@ -1,31 +1,25 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.jaas;
import java.io.IOException;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.callback.*;
/**
* Callback handler that provides the CAS service and ticket to a
@@ -41,10 +35,10 @@ public class ServiceAndTicketCallbackHandler implements CallbackHandler {
/** CAS service URL */
private final String service;
-
+
/** CAS service ticket */
private final String ticket;
-
+
/**
* Creates a new instance with the given service and ticket.
*
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/jaas/TicketCredential.java b/cas-client-core/src/main/java/org/jasig/cas/client/jaas/TicketCredential.java
index 2f7e92e5f..621da53fd 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/jaas/TicketCredential.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/jaas/TicketCredential.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.jaas;
import java.security.Principal;
@@ -33,7 +32,7 @@ public final class TicketCredential implements Principal {
/** Hash code seed value */
private static final int HASHCODE_SEED = 17;
-
+
/** Ticket ID string */
private String ticket;
@@ -54,12 +53,15 @@ public String toString() {
}
public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
final TicketCredential that = (TicketCredential) o;
- if (ticket != null ? !ticket.equals(that.ticket) : that.ticket != null) return false;
+ if (ticket != null ? !ticket.equals(that.ticket) : that.ticket != null)
+ return false;
return true;
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/AbstractEncryptedProxyGrantingTicketStorageImpl.java b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/AbstractEncryptedProxyGrantingTicketStorageImpl.java
index 7842ac33d..69cc75dcf 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/AbstractEncryptedProxyGrantingTicketStorageImpl.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/AbstractEncryptedProxyGrantingTicketStorageImpl.java
@@ -1,12 +1,30 @@
+/*
+ * 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.proxy;
-import javax.crypto.Cipher;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.DESedeKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESedeKeySpec;
/**
* Provides encryption capabilities. Not entirely safe to configure since we have no way of controlling the
@@ -24,7 +42,8 @@ public abstract class AbstractEncryptedProxyGrantingTicketStorageImpl implements
private String cipherAlgorithm = DEFAULT_ENCRYPTION_ALGORITHM;
- public final void setSecretKey(final String key) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException {
+ public final void setSecretKey(final String key) throws NoSuchAlgorithmException, InvalidKeyException,
+ InvalidKeySpecException {
this.key = SecretKeyFactory.getInstance(this.cipherAlgorithm).generateSecret(new DESedeKeySpec(key.getBytes()));
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/Cas20ProxyRetriever.java b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/Cas20ProxyRetriever.java
index 45adbaed4..1146b48c2 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/Cas20ProxyRetriever.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/Cas20ProxyRetriever.java
@@ -1,54 +1,49 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.proxy;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import java.net.URL;
+import java.net.URLEncoder;
+import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Implementation of a ProxyRetriever that follows the CAS 2.0 specification.
* For more information on the CAS 2.0 specification, please see the specification
+ * href="http://www.jasig.org/cas/protocol">specification
* document.
*
* In general, this class will make a call to the CAS server with some specified
* parameters and receive an XML response to parse.
*
* @author Scott Battaglia
- * @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $
* @since 3.0
*/
public final class Cas20ProxyRetriever implements ProxyRetriever {
/** Unique Id for serialization. */
- private static final long serialVersionUID = 560409469568911791L;
+ private static final long serialVersionUID = 560409469568911792L;
- /**
- * Instance of Commons Logging.
- */
- private final Log log = LogFactory.getLog(this.getClass());
+ private static final Logger logger = LoggerFactory.getLogger(Cas20ProxyRetriever.class);
/**
* Url to CAS server.
@@ -57,39 +52,45 @@ public final class Cas20ProxyRetriever implements ProxyRetriever {
private final String encoding;
+ /** Url connection factory to use when communicating with the server **/
+ private final HttpURLConnectionFactory urlConnectionFactory;
+
/**
* Main Constructor.
*
* @param casServerUrl the URL to the CAS server (i.e. http://localhost/cas/)
* @param encoding the encoding to use.
+ * @param urlFactory url connection factory use when retrieving proxy responses from the server
*/
- public Cas20ProxyRetriever(final String casServerUrl, final String encoding) {
+ public Cas20ProxyRetriever(final String casServerUrl, final String encoding,
+ final HttpURLConnectionFactory urlFactory) {
CommonUtils.assertNotNull(casServerUrl, "casServerUrl cannot be null.");
this.casServerUrl = casServerUrl;
this.encoding = encoding;
+ this.urlConnectionFactory = urlFactory;
}
- public String getProxyTicketIdFor(final String proxyGrantingTicketId,
- final String targetService) {
+ public String getProxyTicketIdFor(final String proxyGrantingTicketId, final String targetService) {
+ CommonUtils.assertNotNull(proxyGrantingTicketId, "proxyGrantingTicketId cannot be null.");
+ CommonUtils.assertNotNull(targetService, "targetService cannot be null.");
- final String url = constructUrl(proxyGrantingTicketId, targetService);
- final String response = CommonUtils.getResponseFromServer(url, this.encoding);
+ final URL url = constructUrl(proxyGrantingTicketId, targetService);
+ final String response = CommonUtils.getResponseFromServer(url, this.urlConnectionFactory, this.encoding);
final String error = XmlUtils.getTextForElement(response, "proxyFailure");
if (CommonUtils.isNotEmpty(error)) {
- log.debug(error);
+ logger.debug(error);
return null;
}
return XmlUtils.getTextForElement(response, "proxyTicket");
}
- private String constructUrl(final String proxyGrantingTicketId, final String targetService) {
+ private URL constructUrl(final String proxyGrantingTicketId, final String targetService) {
try {
- return this.casServerUrl + (this.casServerUrl.endsWith("/") ? "" : "/") + "proxy" + "?pgt="
- + proxyGrantingTicketId + "&targetService="
- + URLEncoder.encode(targetService, "UTF-8");
- } catch (final UnsupportedEncodingException e) {
+ return new URL(this.casServerUrl + (this.casServerUrl.endsWith("/") ? "" : "/") + "proxy" + "?pgt="
+ + proxyGrantingTicketId + "&targetService=" + URLEncoder.encode(targetService, "UTF-8"));
+ } catch (final Exception e) {
throw new RuntimeException(e);
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/CleanUpTimerTask.java b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/CleanUpTimerTask.java
index e48986c4e..ce31b4b24 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/CleanUpTimerTask.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/CleanUpTimerTask.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.proxy;
import java.util.TimerTask;
@@ -39,6 +38,7 @@ public final class CleanUpTimerTask extends TimerTask {
public CleanUpTimerTask(final ProxyGrantingTicketStorage proxyGrantingTicketStorage) {
this.proxyGrantingTicketStorage = proxyGrantingTicketStorage;
}
+
public void run() {
this.proxyGrantingTicketStorage.cleanUp();
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyGrantingTicketStorage.java b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyGrantingTicketStorage.java
index d4bf58ae9..0dc15c611 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyGrantingTicketStorage.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyGrantingTicketStorage.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.proxy;
/**
@@ -47,7 +46,7 @@ public interface ProxyGrantingTicketStorage {
* @return the ProxyGrantingTicket Id or null if it can't be found
*/
public String retrieve(String proxyGrantingTicketIou);
-
+
/**
* Called on a regular basis by an external timer,
* giving implementations a chance to remove stale data.
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyGrantingTicketStorageImpl.java b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyGrantingTicketStorageImpl.java
index a1d13941e..727eedef5 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyGrantingTicketStorageImpl.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyGrantingTicketStorageImpl.java
@@ -1,30 +1,29 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.proxy;
-import java.util.*;
+import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.jasig.cas.client.util.CommonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Implementation of {@link ProxyGrantingTicketStorage} that is backed by a
@@ -39,8 +38,8 @@
* @since 3.0
*/
public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicketStorage {
-
- private final Log log = LogFactory.getLog(getClass());
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* Default timeout in milliseconds.
@@ -50,7 +49,7 @@ public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicket
/**
* Map that stores the PGTIOU to PGT mappings.
*/
- private final ConcurrentMap cache = new ConcurrentHashMap();
+ private final ConcurrentMap cache = new ConcurrentHashMap();
/**
* time, in milliseconds, before a {@link ProxyGrantingTicketHolder}
@@ -58,7 +57,7 @@ public final class ProxyGrantingTicketStorageImpl implements ProxyGrantingTicket
*
* @see ProxyGrantingTicketStorageImpl#DEFAULT_TIMEOUT
*/
- private long timeout;
+ private long timeout;
/**
* Constructor set the timeout to the default value.
@@ -74,7 +73,7 @@ public ProxyGrantingTicketStorageImpl() {
* @param timeout the time to hold on to the ProxyGrantingTicket
*/
public ProxyGrantingTicketStorageImpl(final long timeout) {
- this.timeout = timeout;
+ this.timeout = timeout;
}
/**
@@ -82,27 +81,28 @@ public ProxyGrantingTicketStorageImpl(final long timeout) {
* Its removed after retrieval.
*/
public String retrieve(final String proxyGrantingTicketIou) {
+ if (CommonUtils.isBlank(proxyGrantingTicketIou)) {
+ return null;
+ }
+
final ProxyGrantingTicketHolder holder = this.cache.get(proxyGrantingTicketIou);
if (holder == null) {
- log.info("No Proxy Ticket found for [" + proxyGrantingTicketIou + "].");
+ logger.info("No Proxy Ticket found for [{}].", proxyGrantingTicketIou);
return null;
}
this.cache.remove(proxyGrantingTicketIou);
- if (log.isDebugEnabled()) {
- log.debug("Returned ProxyGrantingTicket of [" + holder.getProxyGrantingTicket() + "]");
- }
+ logger.debug("Returned ProxyGrantingTicket of [{}]", holder.getProxyGrantingTicket());
return holder.getProxyGrantingTicket();
}
public void save(final String proxyGrantingTicketIou, final String proxyGrantingTicket) {
final ProxyGrantingTicketHolder holder = new ProxyGrantingTicketHolder(proxyGrantingTicket);
- if (log.isDebugEnabled()) {
- log.debug("Saving ProxyGrantingTicketIOU and ProxyGrantingTicket combo: [" + proxyGrantingTicketIou + ", " + proxyGrantingTicket + "]");
- }
+ logger.debug("Saving ProxyGrantingTicketIOU and ProxyGrantingTicket combo: [{}, {}]", proxyGrantingTicketIou,
+ proxyGrantingTicket);
this.cache.put(proxyGrantingTicketIou, holder);
}
@@ -111,13 +111,13 @@ public void save(final String proxyGrantingTicketIou, final String proxyGranting
* called regularly via an external thread or timer.
*/
public void cleanUp() {
- for (final Map.Entry holder : this.cache.entrySet()) {
+ for (final Map.Entry holder : this.cache.entrySet()) {
if (holder.getValue().isExpired(this.timeout)) {
this.cache.remove(holder.getKey());
}
}
}
-
+
private static final class ProxyGrantingTicketHolder {
private final String proxyGrantingTicket;
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyRetriever.java b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyRetriever.java
index 14c006f7b..07e01a48d 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyRetriever.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/ProxyRetriever.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.proxy;
import java.io.Serializable;
@@ -38,6 +37,5 @@ public interface ProxyRetriever extends Serializable {
* @param targetService the service we want to proxy.
* @return the ProxyTicket Id if Granted, null otherwise.
*/
- String getProxyTicketIdFor(String proxyGrantingTicketId,
- String targetService);
+ String getProxyTicketIdFor(String proxyGrantingTicketId, String targetService);
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/package.html b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/package.html
index fa0cb0635..17c3c9c5c 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/proxy/package.html
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/proxy/package.html
@@ -5,20 +5,19 @@
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:
+ 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
+ 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
+ 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.
-->
-
The proxy package includes a servlet to act as a proxy receptor,
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/HashMapBackedSessionMappingStorage.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/HashMapBackedSessionMappingStorage.java
index c58e3a47b..27a6c6018 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/session/HashMapBackedSessionMappingStorage.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/HashMapBackedSessionMappingStorage.java
@@ -1,31 +1,28 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import java.util.HashMap;
import java.util.Map;
-
import javax.servlet.http.HttpSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* HashMap backed implementation of SessionMappingStorage.
@@ -36,50 +33,48 @@
*
*/
public final class HashMapBackedSessionMappingStorage implements SessionMappingStorage {
-
+
/**
* Maps the ID from the CAS server to the Session.
*/
- private final Map MANAGED_SESSIONS = new HashMap();
+ private final Map MANAGED_SESSIONS = new HashMap();
/**
* Maps the Session ID to the key from the CAS Server.
*/
- private final Map ID_TO_SESSION_KEY_MAPPING = new HashMap();
+ private final Map ID_TO_SESSION_KEY_MAPPING = new HashMap();
- private final Log log = LogFactory.getLog(getClass());
+ private final Logger logger = LoggerFactory.getLogger(getClass());
- public synchronized void addSessionById(String mappingId, HttpSession session) {
+ public synchronized void addSessionById(String mappingId, HttpSession session) {
ID_TO_SESSION_KEY_MAPPING.put(session.getId(), mappingId);
MANAGED_SESSIONS.put(mappingId, session);
- }
+ }
- public synchronized void removeBySessionById(String sessionId) {
- if (log.isDebugEnabled()) {
- log.debug("Attempting to remove Session=[" + sessionId + "]");
- }
+ public synchronized void removeBySessionById(final String sessionId) {
+ logger.debug("Attempting to remove Session=[{}]", sessionId);
final String key = ID_TO_SESSION_KEY_MAPPING.get(sessionId);
- if (log.isDebugEnabled()) {
+ if (logger.isDebugEnabled()) {
if (key != null) {
- log.debug("Found mapping for session. Session Removed.");
+ logger.debug("Found mapping for session. Session Removed.");
} else {
- log.debug("No mapping for session found. Ignoring.");
+ logger.debug("No mapping for session found. Ignoring.");
}
}
MANAGED_SESSIONS.remove(key);
ID_TO_SESSION_KEY_MAPPING.remove(sessionId);
- }
+ }
- public synchronized HttpSession removeSessionByMappingId(String mappingId) {
- final HttpSession session = MANAGED_SESSIONS.get(mappingId);
+ public synchronized HttpSession removeSessionByMappingId(String mappingId) {
+ final HttpSession session = MANAGED_SESSIONS.get(mappingId);
if (session != null) {
- removeBySessionById(session.getId());
+ removeBySessionById(session.getId());
}
return session;
- }
+ }
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SessionMappingStorage.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SessionMappingStorage.java
index 32e53a133..ab0dce4b0 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SessionMappingStorage.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SessionMappingStorage.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 javax.servlet.http.HttpSession;
@@ -30,26 +29,26 @@
*
*/
public interface SessionMappingStorage {
-
- /**
- * Remove the HttpSession based on the mappingId.
- *
- * @param mappingId the id the session is keyed under.
- * @return the HttpSession if it exists.
- */
- HttpSession removeSessionByMappingId(String mappingId);
-
- /**
- * Remove a session by its Id.
- * @param sessionId the id of the session.
- */
- void removeBySessionById(String sessionId);
-
- /**
- * Add a session by its mapping Id.
- * @param mappingId the id to map the session to.
- * @param session the HttpSession.
- */
- void addSessionById(String mappingId, HttpSession session);
+
+ /**
+ * Remove the HttpSession based on the mappingId.
+ *
+ * @param mappingId the id the session is keyed under.
+ * @return the HttpSession if it exists.
+ */
+ HttpSession removeSessionByMappingId(String mappingId);
+
+ /**
+ * Remove a session by its Id.
+ * @param sessionId the id of the session.
+ */
+ void removeBySessionById(String sessionId);
+
+ /**
+ * Add a session by its mapping Id.
+ * @param mappingId the id to map the session to.
+ * @param session the HttpSession.
+ */
+ void addSessionById(String mappingId, HttpSession session);
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java
index a9b439026..109791d2b 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutFilter.java
@@ -1,33 +1,27 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 org.jasig.cas.client.util.AbstractConfigurationFilter;
-
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import org.jasig.cas.client.util.AbstractConfigurationFilter;
/**
* Implements the Single Sign Out protocol. It handles registering the session and destroying the session.
@@ -43,8 +37,12 @@ public final class SingleSignOutFilter extends AbstractConfigurationFilter {
public void init(final FilterConfig filterConfig) throws ServletException {
if (!isIgnoreInitConfiguration()) {
handler.setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket"));
- handler.setLogoutParameterName(getPropertyFromInitParams(filterConfig, "logoutParameterName", "logoutRequest"));
- handler.setArtifactParameterOverPost(parseBoolean(getPropertyFromInitParams(filterConfig, "artifactParameterOverPost", "false")));
+ handler.setLogoutParameterName(getPropertyFromInitParams(filterConfig, "logoutParameterName",
+ "logoutRequest"));
+ handler.setArtifactParameterOverPost(parseBoolean(getPropertyFromInitParams(filterConfig,
+ "artifactParameterOverPost", "false")));
+ handler.setEagerlyCreateSessions(parseBoolean(getPropertyFromInitParams(filterConfig,
+ "eagerlyCreateSessions", "true")));
}
handler.init();
}
@@ -52,7 +50,7 @@ public void init(final FilterConfig filterConfig) throws ServletException {
public void setArtifactParameterName(final String name) {
handler.setArtifactParameterName(name);
}
-
+
public void setLogoutParameterName(final String name) {
handler.setLogoutParameterName(name);
}
@@ -60,8 +58,9 @@ public void setLogoutParameterName(final String name) {
public void setSessionMappingStorage(final SessionMappingStorage storage) {
handler.setSessionMappingStorage(storage);
}
-
- public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+
+ public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
+ final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
if (handler.isTokenRequest(request)) {
@@ -71,7 +70,7 @@ public void doFilter(final ServletRequest servletRequest, final ServletResponse
// Do not continue up filter chain
return;
} else {
- log.trace("Ignoring URI " + request.getRequestURI());
+ logger.trace("Ignoring URI {}", request.getRequestURI());
}
filterChain.doFilter(servletRequest, servletResponse);
@@ -80,7 +79,7 @@ public void doFilter(final ServletRequest servletRequest, final ServletResponse
public void destroy() {
// nothing to do
}
-
+
protected static SingleSignOutHandler getSingleSignOutHandler() {
return handler;
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java
index 31f3e24d7..ebd3323e0 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHandler.java
@@ -1,34 +1,31 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 java.util.Arrays;
+import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
-
-import java.util.Arrays;
-import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Performs CAS single sign-out operations in an API-agnostic fashion.
@@ -41,11 +38,11 @@
public final class SingleSignOutHandler {
/** Logger instance */
- private final Log log = LogFactory.getLog(getClass());
+ private final Logger logger = LoggerFactory.getLogger(getClass());
/** Mapping of token IDs and session IDs to HTTP sessions */
private SessionMappingStorage sessionMappingStorage = new HashMapBackedSessionMappingStorage();
-
+
/** The name of the artifact parameter. This is used to capture the session identifier. */
private String artifactParameterName = "ticket";
@@ -54,8 +51,9 @@ public final class SingleSignOutHandler {
private boolean artifactParameterOverPost = false;
- private List safeParameters;
+ private boolean eagerlyCreateSessions = true;
+ private List safeParameters;
public void setSessionMappingStorage(final SessionMappingStorage storage) {
this.sessionMappingStorage = storage;
@@ -83,6 +81,10 @@ public void setLogoutParameterName(final String name) {
this.logoutParameterName = name;
}
+ public void setEagerlyCreateSessions(final boolean eagerlyCreateSessions) {
+ this.eagerlyCreateSessions = eagerlyCreateSessions;
+ }
+
/**
* Initializes the component for use.
*/
@@ -97,7 +99,7 @@ public void init() {
this.safeParameters = Arrays.asList(this.logoutParameterName);
}
}
-
+
/**
* Determines whether the given request contains an authentication token.
*
@@ -106,7 +108,8 @@ public void init() {
* @return True if request contains authentication token, false otherwise.
*/
public boolean isTokenRequest(final HttpServletRequest request) {
- return CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.artifactParameterName, this.safeParameters));
+ return CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.artifactParameterName,
+ this.safeParameters));
}
/**
@@ -117,8 +120,10 @@ public boolean isTokenRequest(final HttpServletRequest request) {
* @return True if request is logout request, false otherwise.
*/
public boolean isLogoutRequest(final HttpServletRequest request) {
- return "POST".equals(request.getMethod()) && !isMultipartRequest(request) &&
- CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName, this.safeParameters));
+ return "POST".equals(request.getMethod())
+ && !isMultipartRequest(request)
+ && CommonUtils.isNotBlank(CommonUtils.safeGetParameter(request, this.logoutParameterName,
+ this.safeParameters));
}
/**
@@ -128,13 +133,16 @@ public boolean isLogoutRequest(final HttpServletRequest request) {
* @param request HTTP request containing an authentication token.
*/
public void recordSession(final HttpServletRequest request) {
- final HttpSession session = request.getSession(true);
+ final HttpSession session = request.getSession(this.eagerlyCreateSessions);
- final String token = CommonUtils.safeGetParameter(request, this.artifactParameterName, this.safeParameters);
- if (log.isDebugEnabled()) {
- log.debug("Recording session for token " + token);
+ if (session == null) {
+ logger.debug("No session currently exists (and none created). Cannot record session information for single sign out.");
+ return;
}
+ final String token = CommonUtils.safeGetParameter(request, this.artifactParameterName, this.safeParameters);
+ logger.debug("Recording session for token {}", token);
+
try {
this.sessionMappingStorage.removeBySessionById(session.getId());
} catch (final Exception e) {
@@ -142,18 +150,17 @@ public void recordSession(final HttpServletRequest request) {
}
sessionMappingStorage.addSessionById(token, session);
}
-
+
/**
* 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);
- if (log.isTraceEnabled()) {
- log.trace ("Logout request:\n" + logoutMessage);
- }
-
+ final String logoutMessage = CommonUtils.safeGetParameter(request, this.logoutParameterName,
+ this.safeParameters);
+ logger.trace("Logout request:\n{}", logoutMessage);
+
final String token = XmlUtils.getTextForElement(logoutMessage, "SessionIndex");
if (CommonUtils.isNotBlank(token)) {
final HttpSession session = this.sessionMappingStorage.removeSessionByMappingId(token);
@@ -161,13 +168,12 @@ public void destroySession(final HttpServletRequest request) {
if (session != null) {
String sessionID = session.getId();
- if (log.isDebugEnabled()) {
- log.debug ("Invalidating session [" + sessionID + "] for token [" + token + "]");
- }
+ logger.debug("Invalidating session [{}] for token [{}]", sessionID, token);
+
try {
session.invalidate();
} catch (final IllegalStateException e) {
- log.debug("Error invalidating session.", e);
+ logger.debug("Error invalidating session.", e);
}
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHttpSessionListener.java b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHttpSessionListener.java
index 7d28bd16c..d1f3b5d11 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHttpSessionListener.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/session/SingleSignOutHttpSessionListener.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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 javax.servlet.http.HttpSession;
@@ -35,16 +34,16 @@
*/
public final class SingleSignOutHttpSessionListener implements HttpSessionListener {
- private SessionMappingStorage sessionMappingStorage;
-
+ private SessionMappingStorage sessionMappingStorage;
+
public void sessionCreated(final HttpSessionEvent event) {
// nothing to do at the moment
}
public void sessionDestroyed(final HttpSessionEvent event) {
- if (sessionMappingStorage == null) {
- sessionMappingStorage = getSessionMappingStorage();
- }
+ if (sessionMappingStorage == null) {
+ sessionMappingStorage = getSessionMappingStorage();
+ }
final HttpSession session = event.getSession();
sessionMappingStorage.removeBySessionById(session.getId());
}
@@ -56,6 +55,6 @@ public void sessionDestroyed(final HttpSessionEvent event) {
* @return the SessionMappingStorage
*/
protected static SessionMappingStorage getSessionMappingStorage() {
- return SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage();
+ return SingleSignOutFilter.getSingleSignOutHandler().getSessionMappingStorage();
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/AnyHostnameVerifier.java b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/AnyHostnameVerifier.java
index 14fe4ec99..c9672ce27 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/AnyHostnameVerifier.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/AnyHostnameVerifier.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.ssl;
import javax.net.ssl.HostnameVerifier;
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpURLConnectionFactory.java b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpURLConnectionFactory.java
new file mode 100644
index 000000000..e280b7a62
--- /dev/null
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpURLConnectionFactory.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ssl;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * A factory to prepare and configure {@link java.net.URLConnection} instances.
+ *
+ * @author Misagh Moayyed
+ * @since 3.3
+ */
+public interface HttpURLConnectionFactory {
+
+ /**
+ * Receives a {@link URLConnection} instance typically as a result of a {@link URL}
+ * opening a connection to a remote resource. The received url connection is then
+ * configured and prepared appropriately depending on its type and is then returned to the caller
+ * to accommodate method chaining.
+ *
+ * @param url The url connection that needs to be configured
+ * @return The configured {@link HttpURLConnection} instance
+ *
+ * @see {@link HttpsURLConnectionFactory}
+ */
+ HttpURLConnection buildHttpURLConnection(final URLConnection url);
+}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpsURLConnectionFactory.java b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpsURLConnectionFactory.java
new file mode 100644
index 000000000..3b27c0ed2
--- /dev/null
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/HttpsURLConnectionFactory.java
@@ -0,0 +1,131 @@
+package org.jasig.cas.client.ssl;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URLConnection;
+import java.security.KeyStore;
+import java.util.Properties;
+import javax.net.ssl.*;
+import org.jasig.cas.client.util.CommonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An implementation of the {@link HttpURLConnectionFactory} whose responsible to configure
+ * the underlying https connection, if needed, with a given hostname and SSL socket factory based on the
+ * configuration provided.
+ *
+ * @author Misagh Moayyed
+ * @since 3.3
+ * @see #setHostnameVerifier(HostnameVerifier)
+ * @see #setSSLConfiguration(Properties)
+ */
+public final class HttpsURLConnectionFactory implements HttpURLConnectionFactory {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(HttpsURLConnectionFactory.class);
+
+ /**
+ * Hostname verifier used when making an SSL request to the CAS server.
+ * Defaults to {@link HttpsURLConnection#getDefaultHostnameVerifier()}
+ */
+ private HostnameVerifier hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
+
+ /**
+ * Properties file that can contains key/trust info for Client Side Certificates
+ */
+ private Properties sslConfiguration = new Properties();
+
+ public HttpsURLConnectionFactory() {
+ }
+
+ public HttpsURLConnectionFactory(final HostnameVerifier verifier, final Properties config) {
+ setHostnameVerifier(verifier);
+ setSSLConfiguration(config);
+ }
+
+ public final void setSSLConfiguration(final Properties config) {
+ this.sslConfiguration = config;
+ }
+
+ /**
+ * Set the host name verifier for the https connection received.
+ *
+ * @see AnyHostnameVerifier
+ * @see RegexHostnameVerifier
+ * @see WhitelistHostnameVerifier
+ */
+ public final void setHostnameVerifier(final HostnameVerifier verifier) {
+ this.hostnameVerifier = verifier;
+ }
+
+ public HttpURLConnection buildHttpURLConnection(final URLConnection url) {
+ return this.configureHttpsConnectionIfNeeded(url);
+ }
+
+ /**
+ * Configures the connection with specific settings for secure http connections
+ * If the connection instance is not a {@link HttpsURLConnection},
+ * no additional changes will be made and the connection itself is simply returned.
+ *
+ * @param conn the http connection
+ */
+ private HttpURLConnection configureHttpsConnectionIfNeeded(final URLConnection conn) {
+ if (conn instanceof HttpsURLConnection) {
+ final HttpsURLConnection httpsConnection = (HttpsURLConnection) conn;
+ final SSLSocketFactory socketFactory = this.createSSLSocketFactory();
+ if (socketFactory != null) {
+ httpsConnection.setSSLSocketFactory(socketFactory);
+ }
+
+ if (this.hostnameVerifier != null) {
+ httpsConnection.setHostnameVerifier(this.hostnameVerifier);
+ }
+ }
+ return (HttpURLConnection) conn;
+ }
+
+ /**
+ * Creates a {@link SSLSocketFactory} based on the configuration specified
+ *
+ * @return the {@link SSLSocketFactory}
+ */
+ private SSLSocketFactory createSSLSocketFactory() {
+ InputStream keyStoreIS = null;
+ try {
+ final SSLContext sslContext = SSLContext.getInstance(this.sslConfiguration.getProperty("protocol", "SSL"));
+
+ if (this.sslConfiguration.getProperty("keyStoreType") != null) {
+ final KeyStore keyStore = KeyStore.getInstance(this.sslConfiguration.getProperty("keyStoreType"));
+ if (this.sslConfiguration.getProperty("keyStorePath") != null) {
+ keyStoreIS = new FileInputStream(this.sslConfiguration.getProperty("keyStorePath"));
+ if (this.sslConfiguration.getProperty("keyStorePass") != null) {
+ keyStore.load(keyStoreIS, this.sslConfiguration.getProperty("keyStorePass").toCharArray());
+ LOGGER.debug("Keystore has {} keys", keyStore.size());
+ final KeyManagerFactory keyManager = KeyManagerFactory.getInstance(this.sslConfiguration
+ .getProperty("keyManagerType", "SunX509"));
+ keyManager.init(keyStore, this.sslConfiguration.getProperty("certificatePassword")
+ .toCharArray());
+ sslContext.init(keyManager.getKeyManagers(), null, null);
+ return sslContext.getSocketFactory();
+ }
+ }
+ }
+
+ } catch (final Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ } finally {
+ CommonUtils.closeQuietly(keyStoreIS);
+ }
+ return null;
+ }
+
+}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/RegexHostnameVerifier.java b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/RegexHostnameVerifier.java
index 6bb707406..15763644b 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/RegexHostnameVerifier.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/RegexHostnameVerifier.java
@@ -1,25 +1,25 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.ssl;
import java.util.regex.Pattern;
-
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
@@ -36,8 +36,7 @@ public final class RegexHostnameVerifier implements HostnameVerifier {
/** Allowed hostname pattern */
private Pattern pattern;
-
-
+
/**
* Creates a new instance using the given regular expression.
*
@@ -47,7 +46,6 @@ public RegexHostnameVerifier(final String regex) {
this.pattern = Pattern.compile(regex);
}
-
/** {@inheritDoc} */
public boolean verify(final String hostname, final SSLSession session) {
return pattern.matcher(hostname).matches();
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/WhitelistHostnameVerifier.java b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/WhitelistHostnameVerifier.java
index c09002a70..db9abb5ab 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/ssl/WhitelistHostnameVerifier.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/ssl/WhitelistHostnameVerifier.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.ssl;
import javax.net.ssl.HostnameVerifier;
@@ -35,7 +34,6 @@ public final class WhitelistHostnameVerifier implements HostnameVerifier {
/** Allowed hosts */
private String[] allowedHosts;
-
/**
* Creates a new instance using the given array of allowed hosts.
*
@@ -45,7 +43,6 @@ public WhitelistHostnameVerifier(final String[] allowed) {
this.allowedHosts = allowed;
}
-
/**
* Creates a new instance using the given list of allowed hosts.
*
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractCasFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractCasFilter.java
index 79c94b327..78f5f7bae 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractCasFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractCasFilter.java
@@ -1,27 +1,23 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -46,15 +42,12 @@ 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_";
- /** Instance of commons logging for logging purposes. */
- protected final Log log = LogFactory.getLog(getClass());
-
/** Defines the parameter to look for for the artifact. */
private String artifactParameterName = "ticket";
/** 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;
@@ -69,15 +62,15 @@ public abstract class AbstractCasFilter extends AbstractConfigurationFilter {
public final void init(final FilterConfig filterConfig) throws ServletException {
if (!isIgnoreInitConfiguration()) {
setServerName(getPropertyFromInitParams(filterConfig, "serverName", null));
- log.trace("Loading serverName property: " + this.serverName);
+ logger.trace("Loading serverName property: {}", this.serverName);
setService(getPropertyFromInitParams(filterConfig, "service", null));
- log.trace("Loading service property: " + this.service);
+ logger.trace("Loading service property: {}", this.service);
setArtifactParameterName(getPropertyFromInitParams(filterConfig, "artifactParameterName", "ticket"));
- log.trace("Loading artifact parameter name property: " + this.artifactParameterName);
+ logger.trace("Loading artifact parameter name property: {}", this.artifactParameterName);
setServiceParameterName(getPropertyFromInitParams(filterConfig, "serviceParameterName", "service"));
- log.trace("Loading serviceParameterName property: " + this.serviceParameterName);
+ logger.trace("Loading serviceParameterName property: {} ", this.serviceParameterName);
setEncodeServiceUrl(parseBoolean(getPropertyFromInitParams(filterConfig, "encodeServiceUrl", "true")));
- log.trace("Loading encodeServiceUrl property: " + this.encodeServiceUrl);
+ logger.trace("Loading encodeServiceUrl property: {}", this.encodeServiceUrl);
initInternal(filterConfig);
}
@@ -100,8 +93,10 @@ protected void initInternal(final FilterConfig filterConfig) throws ServletExcep
public void init() {
CommonUtils.assertNotNull(this.artifactParameterName, "artifactParameterName cannot be null.");
CommonUtils.assertNotNull(this.serviceParameterName, "serviceParameterName cannot be null.");
- CommonUtils.assertTrue(CommonUtils.isNotEmpty(this.serverName) || CommonUtils.isNotEmpty(this.service), "serverName or service must be set.");
- CommonUtils.assertTrue(CommonUtils.isBlank(this.serverName) || CommonUtils.isBlank(this.service), "serverName and service cannot both be set. You MUST ONLY set one.");
+ CommonUtils.assertTrue(CommonUtils.isNotEmpty(this.serverName) || CommonUtils.isNotEmpty(this.service),
+ "serverName or service must be set.");
+ CommonUtils.assertTrue(CommonUtils.isBlank(this.serverName) || CommonUtils.isBlank(this.service),
+ "serverName and service cannot both be set. You MUST ONLY set one.");
}
// empty implementation as most filters won't need this.
@@ -110,7 +105,8 @@ public void destroy() {
}
protected final String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response) {
- return CommonUtils.constructServiceUrl(request, response, this.service, this.serverName, this.artifactParameterName, this.encodeServiceUrl);
+ return CommonUtils.constructServiceUrl(request, response, this.service, this.serverName,
+ this.artifactParameterName, this.encodeServiceUrl);
}
/**
@@ -121,8 +117,8 @@ protected final String constructServiceUrl(final HttpServletRequest request, fin
*/
public final void setServerName(final String serverName) {
if (serverName != null && serverName.endsWith("/")) {
- this.serverName = serverName.substring(0, serverName.length()-1);
- log.info(String.format("Eliminated extra slash from serverName [%s]. It is now [%s]", serverName, this.serverName));
+ this.serverName = serverName.substring(0, serverName.length() - 1);
+ logger.info("Eliminated extra slash from serverName [{}]. It is now [{}]", serverName, this.serverName);
} else {
this.serverName = serverName;
}
@@ -139,9 +135,9 @@ public final void setArtifactParameterName(final String artifactParameterName) {
public final void setServiceParameterName(final String serviceParameterName) {
this.serviceParameterName = serviceParameterName;
}
-
+
public final void setEncodeServiceUrl(final boolean encodeServiceUrl) {
- this.encodeServiceUrl = encodeServiceUrl;
+ this.encodeServiceUrl = encodeServiceUrl;
}
public final String getArtifactParameterName() {
@@ -159,6 +155,6 @@ public final String getServiceParameterName() {
* @return the ticket if its found, null otherwise.
*/
protected String retrieveTicketFromRequest(final HttpServletRequest request) {
- return CommonUtils.safeGetParameter(request,getArtifactParameterName());
+ return CommonUtils.safeGetParameter(request, getArtifactParameterName());
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java
index de6dca7e1..708b7bf63 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/AbstractConfigurationFilter.java
@@ -1,31 +1,29 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Abstracts out the ability to configure the filters from the initial properties provided.
@@ -35,8 +33,8 @@
* @since 3.1
*/
public abstract class AbstractConfigurationFilter implements Filter {
-
- protected final Log log = LogFactory.getLog(getClass());
+
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
private boolean ignoreInitConfiguration = false;
@@ -64,58 +62,63 @@ public abstract class AbstractConfigurationFilter implements Filter {
* @return the property value, following the above conventions. It will always return the more specific value (i.e.
* filter vs. context).
*/
- protected final String getPropertyFromInitParams(final FilterConfig filterConfig, final String propertyName, final String defaultValue) {
+ protected final String getPropertyFromInitParams(final FilterConfig filterConfig, final String propertyName,
+ final String defaultValue) {
final String value = filterConfig.getInitParameter(propertyName);
if (CommonUtils.isNotBlank(value)) {
- log.info("Property [" + propertyName + "] loaded from FilterConfig.getInitParameter with value [" + value + "]");
+ if ("renew".equals(propertyName)) {
+ throw new IllegalArgumentException(
+ "Renew MUST be specified via context parameter or JNDI environment to avoid misconfiguration.");
+ }
+ logger.info("Property [{}] loaded from FilterConfig.getInitParameter with value [{}]", propertyName, value);
return value;
}
final String value2 = filterConfig.getServletContext().getInitParameter(propertyName);
if (CommonUtils.isNotBlank(value2)) {
- log.info("Property [" + propertyName + "] loaded from ServletContext.getInitParameter with value [" + value2 + "]");
+ logger.info("Property [{}] loaded from ServletContext.getInitParameter with value [{}]", propertyName,
+ value2);
return value2;
}
InitialContext context;
try {
- context = new InitialContext();
+ context = new InitialContext();
} catch (final NamingException e) {
- log.warn(e,e);
- return defaultValue;
+ logger.warn(e.getMessage(), e);
+ return defaultValue;
}
-
-
- final String shortName = this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".")+1);
+
+ final String shortName = this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".") + 1);
final String value3 = loadFromContext(context, "java:comp/env/cas/" + shortName + "/" + propertyName);
-
+
if (CommonUtils.isNotBlank(value3)) {
- log.info("Property [" + propertyName + "] loaded from JNDI Filter Specific Property with value [" + value3 + "]");
- return value3;
+ logger.info("Property [{}] loaded from JNDI Filter Specific Property with value [{}]", propertyName, value3);
+ return value3;
}
-
- final String value4 = loadFromContext(context, "java:comp/env/cas/" + propertyName);
-
+
+ final String value4 = loadFromContext(context, "java:comp/env/cas/" + propertyName);
+
if (CommonUtils.isNotBlank(value4)) {
- log.info("Property [" + propertyName + "] loaded from JNDI with value [" + value4 + "]");
- return value4;
+ logger.info("Property [{}] loaded from JNDI with value [{}]", propertyName, value4);
+ return value4;
}
- log.info("Property [" + propertyName + "] not found. Using default value [" + defaultValue + "]");
+ logger.info("Property [{}] not found. Using default value [{}]", propertyName, defaultValue);
return defaultValue;
}
-
+
protected final boolean parseBoolean(final String value) {
- return ((value != null) && value.equalsIgnoreCase("true"));
+ return ((value != null) && value.equalsIgnoreCase("true"));
}
-
+
protected final String loadFromContext(final InitialContext context, final String path) {
- try {
- return (String) context.lookup(path);
- } catch (final NamingException e) {
- return null;
- }
+ try {
+ return (String) context.lookup(path);
+ } catch (final NamingException e) {
+ return null;
+ }
}
public final void setIgnoreInitConfiguration(boolean ignoreInitConfiguration) {
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/AssertionHolder.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/AssertionHolder.java
index 7959ca0ec..842a2686d 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/AssertionHolder.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/AssertionHolder.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
import org.jasig.cas.client.validation.Assertion;
@@ -35,7 +34,6 @@ public class AssertionHolder {
*/
private static final ThreadLocal threadLocal = new ThreadLocal();
-
/**
* Retrieve the assertion from the ThreadLocal.
*
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/AssertionThreadLocalFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/AssertionThreadLocalFilter.java
index d0af95e58..9cae17dce 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/AssertionThreadLocalFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/AssertionThreadLocalFilter.java
@@ -1,35 +1,28 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
-import org.jasig.cas.client.validation.Assertion;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import java.io.IOException;
+import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
-import java.io.IOException;
+import org.jasig.cas.client.validation.Assertion;
/**
* Places the assertion in a ThreadLocal such that other resources can access it that do not have access to the web tier session.
@@ -44,10 +37,13 @@ public void init(final FilterConfig filterConfig) throws ServletException {
// nothing to do here
}
- public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+ public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
+ final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpSession session = request.getSession(false);
- final Assertion assertion = (Assertion) (session == null ? request.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION));
+ final Assertion assertion = (Assertion) (session == null ? request
+ .getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : session
+ .getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION));
try {
AssertionHolder.setAssertion(assertion);
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java
index 733393f3d..594239ac9 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/CommonUtils.java
@@ -1,47 +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:
+ * 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
+ * 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
+ * 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.util;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
-import org.jasig.cas.client.validation.ProxyList;
-import org.jasig.cas.client.validation.ProxyListEditor;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.URLConnection;
-import java.net.URLEncoder;
-import java.net.URL;
+import java.io.*;
import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage;
+import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
+import org.jasig.cas.client.validation.ProxyList;
+import org.jasig.cas.client.validation.ProxyListEditor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Common utilities so that we don't need to include Commons Lang.
@@ -52,9 +43,8 @@
*/
public final class CommonUtils {
- /** Instance of Commons Logging. */
- private static final Log LOG = LogFactory.getLog(CommonUtils.class);
-
+ private static final Logger LOGGER = LoggerFactory.getLogger(CommonUtils.class);
+
/**
* Constant representing the ProxyGrantingTicket IOU Request Parameter.
*/
@@ -168,43 +158,39 @@ public static boolean isNotBlank(final String string) {
* @param gateway where we should send gateway or not.
* @return the fully constructed redirect url.
*/
- public static String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName, final String serviceUrl, final boolean renew, final boolean gateway) {
+ public static String constructRedirectUrl(final String casServerLoginUrl, final String serviceParameterName,
+ final String serviceUrl, final boolean renew, final boolean gateway) {
try {
return casServerLoginUrl + (casServerLoginUrl.contains("?") ? "&" : "?") + serviceParameterName + "="
- + URLEncoder.encode(serviceUrl, "UTF-8")
- + (renew ? "&renew=true" : "")
+ + URLEncoder.encode(serviceUrl, "UTF-8") + (renew ? "&renew=true" : "")
+ (gateway ? "&gateway=true" : "");
} catch (final UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
-
- public static void readAndRespondToProxyReceptorRequest(final HttpServletRequest request, final HttpServletResponse response, final ProxyGrantingTicketStorage proxyGrantingTicketStorage) throws IOException {
+
+ public static void readAndRespondToProxyReceptorRequest(final HttpServletRequest request,
+ final HttpServletResponse response, final ProxyGrantingTicketStorage proxyGrantingTicketStorage)
+ throws IOException {
final String proxyGrantingTicketIou = request.getParameter(PARAM_PROXY_GRANTING_TICKET_IOU);
- final String proxyGrantingTicket = request.getParameter(PARAM_PROXY_GRANTING_TICKET);
+ final String proxyGrantingTicket = request.getParameter(PARAM_PROXY_GRANTING_TICKET);
+
+ if (CommonUtils.isBlank(proxyGrantingTicket) || CommonUtils.isBlank(proxyGrantingTicketIou)) {
+ response.getWriter().write("");
+ return;
+ }
- if (CommonUtils.isBlank(proxyGrantingTicket) || CommonUtils.isBlank(proxyGrantingTicketIou)) {
- response.getWriter().write("");
- return;
- }
+ LOGGER.debug("Received proxyGrantingTicketId [{}] for proxyGrantingTicketIou [{}]", proxyGrantingTicket,
+ proxyGrantingTicketIou);
- if (LOG.isDebugEnabled()) {
- LOG.debug("Received proxyGrantingTicketId ["
- + proxyGrantingTicket + "] for proxyGrantingTicketIou ["
- + proxyGrantingTicketIou + "]");
- }
+ proxyGrantingTicketStorage.save(proxyGrantingTicketIou, proxyGrantingTicket);
- proxyGrantingTicketStorage.save(proxyGrantingTicketIou, proxyGrantingTicket);
+ LOGGER.debug("Successfully saved proxyGrantingTicketId [{}] for proxyGrantingTicketIou [{}]",
+ proxyGrantingTicket, proxyGrantingTicketIou);
- if (LOG.isDebugEnabled()) {
- LOG.debug("Successfully saved proxyGrantingTicketId ["
- + proxyGrantingTicket + "] for proxyGrantingTicketIou ["
- + proxyGrantingTicketIou + "]");
- }
-
- response.getWriter().write("");
- response.getWriter().write("");
+ response.getWriter().write("");
+ response.getWriter().write("");
}
protected static String findMatchingServerName(final HttpServletRequest request, final String serverName) {
@@ -216,12 +202,12 @@ protected static String findMatchingServerName(final HttpServletRequest request,
final String host = request.getHeader("Host");
final String xHost = request.getHeader("X-Forwarded-Host");
-
+
final String comparisonHost;
if (xHost != null && host == "localhost") {
- comparisonHost = xHost;
+ comparisonHost = xHost;
} else {
- comparisonHost = host;
+ comparisonHost = host;
}
if (comparisonHost == null) {
@@ -238,23 +224,24 @@ protected static String findMatchingServerName(final HttpServletRequest request,
return serverNames[0];
}
-
-/**
- * Constructs a service url from the HttpServletRequest or from the given
- * serviceUrl. Prefers the serviceUrl provided if both a serviceUrl and a
- * serviceName.
- *
- * @param request the HttpServletRequest
- * @param response the HttpServletResponse
- * @param service the configured service url (this will be used if not null)
- * @param serverNames the server name to use to constuct the service url if the service param is empty. Note, prior to CAS Client 3.3, this was a single value.
- * As of 3.3, it can be a space-separated value. We keep it as a single value, but will convert it to an array internally to get the matching value. This keeps backward compatability with anything using this public
- * method.
- * @param artifactParameterName the artifact parameter name to remove (i.e. ticket)
- * @param encode whether to encode the url or not (i.e. Jsession).
- * @return the service url to use.
- */
- public static String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response, final String service, final String serverNames, final String artifactParameterName, final boolean encode) {
+
+ /**
+ * Constructs a service url from the HttpServletRequest or from the given
+ * serviceUrl. Prefers the serviceUrl provided if both a serviceUrl and a
+ * serviceName.
+ *
+ * @param request the HttpServletRequest
+ * @param response the HttpServletResponse
+ * @param service the configured service url (this will be used if not null)
+ * @param serverNames the server name to use to constuct the service url if the service param is empty. Note, prior to CAS Client 3.3, this was a single value.
+ * As of 3.3, it can be a space-separated value. We keep it as a single value, but will convert it to an array internally to get the matching value. This keeps backward compatability with anything using this public
+ * method.
+ * @param artifactParameterName the artifact parameter name to remove (i.e. ticket)
+ * @param encode whether to encode the url or not (i.e. Jsession).
+ * @return the service url to use.
+ */
+ public static String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response,
+ final String service, final String serverNames, final String artifactParameterName, final boolean encode) {
if (CommonUtils.isNotBlank(service)) {
return encode ? response.encodeURL(service) : service;
}
@@ -274,10 +261,8 @@ public static String constructServiceUrl(final HttpServletRequest request, final
final int location = request.getQueryString().indexOf(artifactParameterName + "=");
if (location == 0) {
- final String returnValue = encode ? response.encodeURL(buffer.toString()): buffer.toString();
- if (LOG.isDebugEnabled()) {
- LOG.debug("serviceUrl generated: " + returnValue);
- }
+ final String returnValue = encode ? response.encodeURL(buffer.toString()) : buffer.toString();
+ LOGGER.debug("serviceUrl generated: {}", returnValue);
return returnValue;
}
@@ -286,22 +271,18 @@ public static String constructServiceUrl(final HttpServletRequest request, final
if (location == -1) {
buffer.append(request.getQueryString());
} else if (location > 0) {
- final int actualLocation = request.getQueryString()
- .indexOf("&" + artifactParameterName + "=");
+ final int actualLocation = request.getQueryString().indexOf("&" + artifactParameterName + "=");
if (actualLocation == -1) {
buffer.append(request.getQueryString());
} else if (actualLocation > 0) {
- buffer.append(request.getQueryString().substring(0,
- actualLocation));
+ buffer.append(request.getQueryString().substring(0, actualLocation));
}
}
}
final String returnValue = encode ? response.encodeURL(buffer.toString()) : buffer.toString();
- if (LOG.isDebugEnabled()) {
- LOG.debug("serviceUrl generated: " + returnValue);
- }
+ LOGGER.debug("serviceUrl generated: {}", returnValue);
return returnValue;
}
@@ -321,12 +302,14 @@ public static String constructServiceUrl(final HttpServletRequest request, final
* @param parameter the parameter to look for.
* @return the value of the parameter.
*/
- public static String safeGetParameter(final HttpServletRequest request, final String parameter, final List parameters) {
+ public static String safeGetParameter(final HttpServletRequest request, final String parameter,
+ final List parameters) {
if ("POST".equals(request.getMethod()) && parameters.contains(parameter)) {
- LOG.debug("safeGetParameter called on a POST HttpServletRequest for Restricted Parameters. Cannot complete check safely. Reverting to standard behavior for this Parameter");
+ LOGGER.debug("safeGetParameter called on a POST HttpServletRequest for Restricted Parameters. Cannot complete check safely. Reverting to standard behavior for this Parameter");
return request.getParameter(parameter);
}
- return request.getQueryString() == null || !request.getQueryString().contains(parameter) ? null : request.getParameter(parameter);
+ return request.getQueryString() == null || !request.getQueryString().contains(parameter) ? null : request
+ .getParameter(parameter);
}
public static String safeGetParameter(final HttpServletRequest request, final String parameter) {
@@ -337,28 +320,17 @@ public static String safeGetParameter(final HttpServletRequest request, final St
* Contacts the remote URL and returns the response.
*
* @param constructedUrl the url to contact.
+ * @param factory connection factory to prepare the URL connection instance
* @param encoding the encoding to use.
* @return the response.
*/
- public static String getResponseFromServer(final URL constructedUrl, final String encoding) {
- return getResponseFromServer(constructedUrl, HttpsURLConnection.getDefaultHostnameVerifier(), encoding);
- }
+ public static String getResponseFromServer(final URL constructedUrl, final HttpURLConnectionFactory factory,
+ final String encoding) {
- /**
- * Contacts the remote URL and returns the response.
- *
- * @param constructedUrl the url to contact.
- * @param hostnameVerifier Host name verifier to use for HTTPS connections.
- * @param encoding the encoding to use.
- * @return the response.
- */
- public static String getResponseFromServer(final URL constructedUrl, final HostnameVerifier hostnameVerifier, final String encoding) {
- URLConnection conn = null;
+ HttpURLConnection conn = null;
try {
- conn = constructedUrl.openConnection();
- if (conn instanceof HttpsURLConnection) {
- ((HttpsURLConnection)conn).setHostnameVerifier(hostnameVerifier);
- }
+ conn = factory.buildHttpURLConnection(constructedUrl.openConnection());
+
final BufferedReader in;
if (CommonUtils.isEmpty(encoding)) {
@@ -376,28 +348,13 @@ public static String getResponseFromServer(final URL constructedUrl, final Hostn
}
return stringBuffer.toString();
} catch (final Exception e) {
- LOG.error(e.getMessage(), e);
+ LOGGER.error(e.getMessage(), e);
throw new RuntimeException(e);
} finally {
- if (conn != null && conn instanceof HttpURLConnection) {
- ((HttpURLConnection)conn).disconnect();
+ if (conn != null) {
+ conn.disconnect();
}
}
-
- }
- /**
- * Contacts the remote URL and returns the response.
- *
- * @param url the url to contact.
- * @param encoding the encoding to use.
- * @return the response.
- */
- public static String getResponseFromServer(final String url, String encoding) {
- try {
- return getResponseFromServer(new URL(url), encoding);
- } catch (final MalformedURLException e) {
- throw new IllegalArgumentException(e);
- }
}
public static ProxyList createProxyList(final String proxies) {
@@ -408,7 +365,7 @@ public static ProxyList createProxyList(final String proxies) {
final ProxyListEditor editor = new ProxyListEditor();
editor.setAsText(proxies);
return (ProxyList) editor.getValue();
- }
+ }
/**
* Sends the redirect message and captures the exceptions that we can't possibly do anything with.
@@ -420,8 +377,23 @@ public static void sendRedirect(final HttpServletResponse response, final String
try {
response.sendRedirect(url);
} catch (final Exception e) {
- LOG.warn(e.getMessage(), e);
+ LOGGER.warn(e.getMessage(), e);
}
}
+
+ /**
+ * Unconditionally close a {@link Closeable}. Equivalent to {@link java.io.Closeable#close()}close(), except any exceptions
+ * will be ignored. This is typically used in finally blocks.
+ * @param resource
+ */
+ public static void closeQuietly(final Closeable resource) {
+ try {
+ if (resource != null) {
+ resource.close();
+ }
+ } catch (final IOException e) {
+ //ignore
+ }
+ }
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/DelegatingFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/DelegatingFilter.java
index 6c71ef831..c25ff0caf 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/DelegatingFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/DelegatingFilter.java
@@ -1,36 +1,29 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A Delegating Filter looks up a parameter in the request object and matches
@@ -46,7 +39,7 @@ public final class DelegatingFilter implements Filter {
/**
* Instance of Commons Logging.
*/
- private final Log log = LogFactory.getLog(this.getClass());
+ private final Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* The request parameter to look for in the Request object.
@@ -56,7 +49,7 @@ public final class DelegatingFilter implements Filter {
/**
* The map of filters to delegate to and the criteria (as key).
*/
- private final Map delegators;
+ private final Map delegators;
/**
* The default filter to use if there is no match.
@@ -69,11 +62,13 @@ public final class DelegatingFilter implements Filter {
*/
private final boolean exactMatch;
- public DelegatingFilter(final String requestParameterName, final Map delegators, final boolean exactMatch) {
+ public DelegatingFilter(final String requestParameterName, final Map delegators,
+ final boolean exactMatch) {
this(requestParameterName, delegators, exactMatch, null);
}
- public DelegatingFilter(final String requestParameterName, final Map delegators, final boolean exactMatch, final Filter defaultFilter) {
+ public DelegatingFilter(final String requestParameterName, final Map delegators,
+ final boolean exactMatch, final Filter defaultFilter) {
CommonUtils.assertNotNull(requestParameterName, "requestParameterName cannot be null.");
CommonUtils.assertTrue(!delegators.isEmpty(), "delegators cannot be empty.");
@@ -87,7 +82,8 @@ public void destroy() {
// nothing to do here
}
- public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException {
+ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain)
+ throws IOException, ServletException {
final String parameter = CommonUtils.safeGetParameter((HttpServletRequest) request, this.requestParameterName);
@@ -95,19 +91,15 @@ public void doFilter(final ServletRequest request, final ServletResponse respons
for (final String key : this.delegators.keySet()) {
if ((parameter.equals(key) && this.exactMatch) || (parameter.matches(key) && !this.exactMatch)) {
final Filter filter = this.delegators.get(key);
- if (log.isDebugEnabled()) {
- log.debug("Match found for parameter ["
- + this.requestParameterName + "] with value ["
- + parameter + "]. Delegating to filter ["
- + filter.getClass().getName() + "]");
- }
+ logger.debug("Match found for parameter [{}] with value [{}]. Delegating to filter [{}]",
+ this.requestParameterName, parameter, filter.getClass().getName());
filter.doFilter(request, response, filterChain);
return;
}
}
}
- log.debug("No match found for parameter [" + this.requestParameterName + "] with value [" + parameter + "]");
+ logger.debug("No match found for parameter [{}] with value [{}]", this.requestParameterName, parameter);
if (this.defaultFilter != null) {
this.defaultFilter.doFilter(request, response, filterChain);
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/ErrorRedirectFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/ErrorRedirectFilter.java
index 9ad2862fb..74496c030 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/ErrorRedirectFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/ErrorRedirectFilter.java
@@ -1,39 +1,31 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Filters that redirects to the supplied url based on an exception. Exceptions and the urls are configured via
@@ -51,78 +43,78 @@
*/
public final class ErrorRedirectFilter implements Filter {
- private final Log log = LogFactory.getLog(getClass());
-
- private final List errors = new ArrayList();
-
- private String defaultErrorRedirectPage;
-
- public void destroy() {
- // nothing to do here
- }
-
- public void doFilter(final ServletRequest request, final ServletResponse response,
- final FilterChain filterChain) throws IOException, ServletException {
- final HttpServletResponse httpResponse = (HttpServletResponse) response;
- try {
- filterChain.doFilter(request, response);
- } catch (final ServletException e) {
- final Throwable t = e.getCause();
- ErrorHolder currentMatch = null;
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ private final List errors = new ArrayList();
+
+ private String defaultErrorRedirectPage;
+
+ public void destroy() {
+ // nothing to do here
+ }
+
+ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain)
+ throws IOException, ServletException {
+ final HttpServletResponse httpResponse = (HttpServletResponse) response;
+ try {
+ filterChain.doFilter(request, response);
+ } catch (final ServletException e) {
+ final Throwable t = e.getCause();
+ ErrorHolder currentMatch = null;
for (final ErrorHolder errorHolder : this.errors) {
- if (errorHolder.exactMatch(t)) {
- currentMatch = errorHolder;
- break;
- } else if (errorHolder.inheritanceMatch(t)) {
- currentMatch = errorHolder;
- }
- }
-
- if (currentMatch != null) {
- httpResponse.sendRedirect(currentMatch.getUrl());
- } else {
- httpResponse.sendRedirect(defaultErrorRedirectPage);
- }
- }
- }
-
- public void init(final FilterConfig filterConfig) throws ServletException {
- this.defaultErrorRedirectPage = filterConfig.getInitParameter("defaultErrorRedirectPage");
-
- final Enumeration> enumeration = filterConfig.getInitParameterNames();
- while (enumeration.hasMoreElements()) {
- final String className = (String) enumeration.nextElement();
- try {
- if (!className.equals("defaultErrorRedirectPage")) {
- this.errors.add(new ErrorHolder(className, filterConfig.getInitParameter(className)));
- }
- } catch (final ClassNotFoundException e) {
- log.warn("Class [" + className + "] cannot be found in ClassLoader. Ignoring.");
- }
- }
- }
-
- protected final class ErrorHolder {
-
- private Class> className;
-
- private String url;
-
- protected ErrorHolder(final String className, final String url) throws ClassNotFoundException {
- this.className = Class.forName(className);
- this.url = url;
- }
-
- public boolean exactMatch(final Throwable e) {
- return this.className.equals(e.getClass());
- }
-
- public boolean inheritanceMatch(final Throwable e) {
- return className.isAssignableFrom(e.getClass());
- }
-
- public String getUrl() {
- return this.url;
- }
- }
+ if (errorHolder.exactMatch(t)) {
+ currentMatch = errorHolder;
+ break;
+ } else if (errorHolder.inheritanceMatch(t)) {
+ currentMatch = errorHolder;
+ }
+ }
+
+ if (currentMatch != null) {
+ httpResponse.sendRedirect(currentMatch.getUrl());
+ } else {
+ httpResponse.sendRedirect(defaultErrorRedirectPage);
+ }
+ }
+ }
+
+ public void init(final FilterConfig filterConfig) throws ServletException {
+ this.defaultErrorRedirectPage = filterConfig.getInitParameter("defaultErrorRedirectPage");
+
+ final Enumeration> enumeration = filterConfig.getInitParameterNames();
+ while (enumeration.hasMoreElements()) {
+ final String className = (String) enumeration.nextElement();
+ try {
+ if (!className.equals("defaultErrorRedirectPage")) {
+ this.errors.add(new ErrorHolder(className, filterConfig.getInitParameter(className)));
+ }
+ } catch (final ClassNotFoundException e) {
+ logger.warn("Class [{}] cannot be found in ClassLoader. Ignoring.", className);
+ }
+ }
+ }
+
+ protected final class ErrorHolder {
+
+ private Class> className;
+
+ private String url;
+
+ protected ErrorHolder(final String className, final String url) throws ClassNotFoundException {
+ this.className = Class.forName(className);
+ this.url = url;
+ }
+
+ public boolean exactMatch(final Throwable e) {
+ return this.className.equals(e.getClass());
+ }
+
+ public boolean inheritanceMatch(final Throwable e) {
+ return className.isAssignableFrom(e.getClass());
+ }
+
+ public String getUrl() {
+ return this.url;
+ }
+ }
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/HttpServletRequestWrapperFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/HttpServletRequestWrapperFilter.java
index 56920b0df..3512f48f3 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/HttpServletRequestWrapperFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/HttpServletRequestWrapperFilter.java
@@ -1,38 +1,32 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
-import org.jasig.cas.client.authentication.AttributePrincipal;
-import org.jasig.cas.client.validation.Assertion;
-
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.Principal;
import java.util.Collection;
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpSession;
+import org.jasig.cas.client.authentication.AttributePrincipal;
+import org.jasig.cas.client.validation.Assertion;
/**
* Implementation of a filter that wraps the normal HttpServletRequest with a
@@ -56,7 +50,7 @@ public final class HttpServletRequestWrapperFilter extends AbstractConfiguration
/** Name of the attribute used to answer role membership queries */
private String roleAttribute;
-
+
/** Whether or not to ignore case in role membership queries */
private boolean ignoreCase;
@@ -69,16 +63,20 @@ public void destroy() {
* request.getRemoteUser to the underlying Assertion object
* stored in the user session.
*/
- public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+ public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
+ final FilterChain filterChain) throws IOException, ServletException {
final AttributePrincipal principal = retrievePrincipalFromSessionOrRequest(servletRequest);
- filterChain.doFilter(new CasHttpServletRequestWrapper((HttpServletRequest) servletRequest, principal), servletResponse);
+ filterChain.doFilter(new CasHttpServletRequestWrapper((HttpServletRequest) servletRequest, principal),
+ servletResponse);
}
protected AttributePrincipal retrievePrincipalFromSessionOrRequest(final ServletRequest servletRequest) {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpSession session = request.getSession(false);
- final Assertion assertion = (Assertion) (session == null ? request.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION));
+ final Assertion assertion = (Assertion) (session == null ? request
+ .getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION) : session
+ .getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION));
return assertion == null ? null : assertion.getPrincipal();
}
@@ -107,36 +105,36 @@ public String getRemoteUser() {
public boolean isUserInRole(final String role) {
if (CommonUtils.isBlank(role)) {
- log.debug("No valid role provided. Returning false.");
+ logger.debug("No valid role provided. Returning false.");
return false;
}
if (this.principal == null) {
- log.debug("No Principal in Request. Returning false.");
+ logger.debug("No Principal in Request. Returning false.");
return false;
}
if (CommonUtils.isBlank(roleAttribute)) {
- log.debug("No Role Attribute Configured. Returning false.");
+ logger.debug("No Role Attribute Configured. Returning false.");
return false;
}
final Object value = this.principal.getAttributes().get(roleAttribute);
-
+
if (value instanceof Collection>) {
for (final Object o : (Collection>) value) {
if (rolesEqual(role, o)) {
- log.debug("User [" + getRemoteUser() + "] is in role [" + role + "]: " + true);
+ logger.debug("User [{}] is in role [{}]: true", getRemoteUser(), role);
return true;
}
}
}
final boolean isMember = rolesEqual(role, value);
- log.debug("User [" + getRemoteUser() + "] is in role [" + role + "]: " + isMember);
+ logger.debug("User [{}] is in role [{}]: {}", getRemoteUser(), role, isMember);
return isMember;
}
-
+
/**
* Determines whether the given role is equal to the candidate
* role attribute taking into account case sensitivity.
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/ReflectUtils.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/ReflectUtils.java
index 0b1f963ef..1ec21162e 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/ReflectUtils.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/ReflectUtils.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
import java.beans.BeanInfo;
@@ -54,7 +53,6 @@ public static Class loadClass(final String className) throws IllegalArgum
}
}
-
/**
* Creates a new instance of the given class by passing the given arguments
* to the constructor.
@@ -62,10 +60,10 @@ public static Class loadClass(final String className) throws IllegalArgum
* @param args Constructor arguments.
* @return New instance of given class.
*/
- public static T newInstance(final String className, final Object ... args) {
- return newInstance(ReflectUtils.loadClass(className), args);
+ public static T newInstance(final String className, final Object... args) {
+ return newInstance(ReflectUtils. loadClass(className), args);
}
-
+
/**
* Creates a new instance of the given class by passing the given arguments
* to the constructor.
@@ -73,7 +71,7 @@ public static T newInstance(final String className, final Object ... args) {
* @param args Constructor arguments.
* @return New instance of given class.
*/
- public static T newInstance(final Class clazz, final Object ... args) {
+ public static T newInstance(final Class clazz, final Object... args) {
final Class>[] argClasses = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argClasses[i] = args[i].getClass();
@@ -139,7 +137,8 @@ public static void setProperty(final String propertyName, final Object value, fi
* @param target Target JavaBean on which to set property.
* @param info BeanInfo describing the target JavaBean.
*/
- public static void setProperty(final String propertyName, final Object value, final Object target, final BeanInfo info) {
+ public static void setProperty(final String propertyName, final Object value, final Object target,
+ final BeanInfo info) {
try {
final PropertyDescriptor pd = getPropertyDescriptor(info, propertyName);
pd.getWriteMethod().invoke(target, value);
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java
index 62abfdfe0..f882b04c6 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java
@@ -1,42 +1,35 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.util;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.NodeList;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
-import org.xml.sax.helpers.XMLReaderFactory;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
+import javax.xml.parsers.SAXParserFactory;
/**
* Common utilities for easily parsing XML without duplicating logic.
@@ -50,7 +43,7 @@ public final class XmlUtils {
/**
* Static instance of Commons Logging.
*/
- private final static Log LOG = LogFactory.getLog(XmlUtils.class);
+ private final static Logger LOGGER = LoggerFactory.getLogger(XmlUtils.class);
/**
* Get an instance of an XML reader from the XMLReaderFactory.
@@ -59,10 +52,12 @@ public final class XmlUtils {
*/
public static XMLReader getXmlReader() {
try {
- final XMLReader reader = XMLReaderFactory.createXMLReader();
+ final XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
+ reader.setFeature("http://xml.org/sax/features/namespaces", true);
+ reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false);
reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
return reader;
- } catch (final SAXException e) {
+ } catch (final Exception e) {
throw new RuntimeException("Unable to create XMLReader", e);
}
}
@@ -76,8 +71,7 @@ public static XMLReader getXmlReader() {
* @param element the element to look for
* @return the list of text from the elements.
*/
- public static List getTextForElements(final String xmlAsString,
- final String element) {
+ public static List getTextForElements(final String xmlAsString, final String element) {
final List elements = new ArrayList(2);
final XMLReader reader = getXmlReader();
@@ -87,16 +81,14 @@ public static List getTextForElements(final String xmlAsString,
private StringBuilder buffer = new StringBuilder();
- public void startElement(final String uri, final String localName,
- final String qName, final Attributes attributes)
- throws SAXException {
+ public void startElement(final String uri, final String localName, final String qName,
+ final Attributes attributes) throws SAXException {
if (localName.equals(element)) {
this.foundElement = true;
}
}
- public void endElement(final String uri, final String localName,
- final String qName) throws SAXException {
+ public void endElement(final String uri, final String localName, final String qName) throws SAXException {
if (localName.equals(element)) {
this.foundElement = false;
elements.add(this.buffer.toString());
@@ -104,8 +96,7 @@ public void endElement(final String uri, final String localName,
}
}
- public void characters(char[] ch, int start, int length)
- throws SAXException {
+ public void characters(char[] ch, int start, int length) throws SAXException {
if (this.foundElement) {
this.buffer.append(ch, start, length);
}
@@ -118,7 +109,7 @@ public void characters(char[] ch, int start, int length)
try {
reader.parse(new InputSource(new StringReader(xmlAsString)));
} catch (final Exception e) {
- LOG.error(e, e);
+ LOGGER.error(e.getMessage(), e);
return null;
}
@@ -133,8 +124,7 @@ public void characters(char[] ch, int start, int length)
* @param element the element to look for
* @return the text value of the element.
*/
- public static String getTextForElement(final String xmlAsString,
- final String element) {
+ public static String getTextForElement(final String xmlAsString, final String element) {
final XMLReader reader = getXmlReader();
final StringBuilder builder = new StringBuilder();
@@ -142,23 +132,20 @@ public static String getTextForElement(final String xmlAsString,
private boolean foundElement = false;
- public void startElement(final String uri, final String localName,
- final String qName, final Attributes attributes)
- throws SAXException {
+ public void startElement(final String uri, final String localName, final String qName,
+ final Attributes attributes) throws SAXException {
if (localName.equals(element)) {
this.foundElement = true;
}
}
- public void endElement(final String uri, final String localName,
- final String qName) throws SAXException {
+ public void endElement(final String uri, final String localName, final String qName) throws SAXException {
if (localName.equals(element)) {
this.foundElement = false;
}
}
- public void characters(char[] ch, int start, int length)
- throws SAXException {
+ public void characters(char[] ch, int start, int length) throws SAXException {
if (this.foundElement) {
builder.append(ch, start, length);
}
@@ -171,33 +158,10 @@ public void characters(char[] ch, int start, int length)
try {
reader.parse(new InputSource(new StringReader(xmlAsString)));
} catch (final Exception e) {
- LOG.error(e, e);
+ LOGGER.error(e.getMessage(), e);
return null;
}
return builder.toString();
}
-
- /**
- * Retrieve the child nodes from xml string, for a specific element.
- *
- * @param xmlAsString the xml response
- * @param tagName the element to look for
- * @return the {@link org.w3c.dom.NodeList NodeList} containing the child nodes.
- * @throws ParserConfigurationException
- * @throws IOException
- * @throws SAXException
- */
- public static NodeList getNodeListForElements(final String xmlAsString, final String tagName)
- throws ParserConfigurationException,
- IOException,
- SAXException {
-
- final DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
- final InputSource inStream = new InputSource();
- inStream.setCharacterStream(new StringReader(xmlAsString));
- final Document document = documentBuilder.parse(inStream);
-
- return document.getElementsByTagName(tagName).item(0).getChildNodes();
- }
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/package.html b/cas-client-core/src/main/java/org/jasig/cas/client/util/package.html
index 300a79b89..fcf85e2f9 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/util/package.html
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/package.html
@@ -5,20 +5,19 @@
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:
+ 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
+ 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
+ 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.
-->
-
The validation package includes interfaces for validating Tickets, as well as the common implementations.
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractCasProtocolUrlBasedTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractCasProtocolUrlBasedTicketValidator.java
index 84d9e6740..b5d5c2fac 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractCasProtocolUrlBasedTicketValidator.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractCasProtocolUrlBasedTicketValidator.java
@@ -1,27 +1,25 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
-import org.jasig.cas.client.util.CommonUtils;
-
import java.net.URL;
+import org.jasig.cas.client.util.CommonUtils;
/**
* Abstract class that knows the protocol for validating a CAS ticket.
@@ -44,10 +42,6 @@ protected final void setDisableXmlSchemaValidation(final boolean disable) {
* Retrieves the response from the server by opening a connection and merely reading the response.
*/
protected final String retrieveResponseFromServer(final URL validationUrl, final String ticket) {
- if (this.hostnameVerifier != null) {
- return CommonUtils.getResponseFromServer(validationUrl, this.hostnameVerifier, getEncoding());
- } else {
- return CommonUtils.getResponseFromServer(validationUrl, getEncoding());
- }
+ return CommonUtils.getResponseFromServer(validationUrl, getURLConnectionFactory(), getEncoding());
}
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java
index 71b62e7ed..58f57c462 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractTicketValidationFilter.java
@@ -1,47 +1,46 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
-import org.jasig.cas.client.util.AbstractCasFilter;
-import org.jasig.cas.client.util.CommonUtils;
-import org.jasig.cas.client.util.ReflectUtils;
-
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
import javax.net.ssl.HostnameVerifier;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
+import org.jasig.cas.client.util.AbstractCasFilter;
+import org.jasig.cas.client.util.CommonUtils;
+import org.jasig.cas.client.util.ReflectUtils;
/**
* The filter that handles all the work of validating ticket requests.
*
* This filter can be configured with the following values:
*
- *
redirectAfterValidation - redirect the CAS client to the same URL without the ticket.
+ *
redirectAfterValidation - redirect the CAS client to the same URL without the ticket.
+ * (default: true, Will be forced to false when {@link #useSession} is false.)
*
exceptionOnValidationFailure - throw an exception if the validation fails. Otherwise, continue
- * processing.
- *
useSession - store any of the useful information in a session attribute.
+ * processing. (default: true)
+ *
useSession - store any of the useful information in a session attribute. (default: true)
+ *
hostnameVerifier - name of class implementing a {@link HostnameVerifier}.
+ *
hostnameVerifierConfig - name of configuration class (constructor argument of verifier).
*
*
* @author Scott Battaglia
@@ -58,11 +57,15 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
* successful validation to remove the ticket parameter from the query
* string.
*/
- private boolean redirectAfterValidation = false;
+ private boolean redirectAfterValidation = true;
/** Determines whether an exception is thrown when there is a ticket validation failure. */
- private boolean exceptionOnValidationFailure = true;
+ private boolean exceptionOnValidationFailure = false;
+ /**
+ * Specify whether the Assertion should be stored in a session
+ * attribute {@link AbstractCasFilter#CONST_CAS_ASSERTION}.
+ */
private boolean useSession = true;
/**
@@ -74,7 +77,32 @@ public abstract class AbstractTicketValidationFilter extends AbstractCasFilter {
protected TicketValidator getTicketValidator(final FilterConfig filterConfig) {
return this.ticketValidator;
}
-
+
+ /**
+ * Gets the ssl config to use for HTTPS connections
+ * if one is configured for this filter.
+ * @param filterConfig Servlet filter configuration.
+ * @return Properties that can contains key/trust info for Client Side Certificates
+ */
+ protected Properties getSSLConfig(final FilterConfig filterConfig) {
+ final Properties properties = new Properties();
+ final String fileName = getPropertyFromInitParams(filterConfig, "sslConfigFile", null);
+
+ if (fileName != null) {
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(fileName);
+ properties.load(fis);
+ logger.trace("Loaded {} entries from {}", properties.size(), fileName);
+ } catch (final IOException ioe) {
+ logger.error(ioe.getMessage(), ioe);
+ } finally {
+ CommonUtils.closeQuietly(fis);
+ }
+ }
+ return properties;
+ }
+
/**
* Gets the configured {@link HostnameVerifier} to use for HTTPS connections
* if one is configured for this filter.
@@ -83,9 +111,9 @@ protected TicketValidator getTicketValidator(final FilterConfig filterConfig) {
*/
protected HostnameVerifier getHostnameVerifier(final FilterConfig filterConfig) {
final String className = getPropertyFromInitParams(filterConfig, "hostnameVerifier", null);
- log.trace("Using hostnameVerifier parameter: " + className);
+ logger.trace("Using hostnameVerifier parameter: {}", className);
final String config = getPropertyFromInitParams(filterConfig, "hostnameVerifierConfig", null);
- log.trace("Using hostnameVerifierConfig parameter: " + config);
+ logger.trace("Using hostnameVerifierConfig parameter: {}", config);
if (className != null) {
if (config != null) {
return ReflectUtils.newInstance(className, config);
@@ -97,12 +125,20 @@ protected HostnameVerifier getHostnameVerifier(final FilterConfig filterConfig)
}
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
- setExceptionOnValidationFailure(parseBoolean(getPropertyFromInitParams(filterConfig, "exceptionOnValidationFailure", "true")));
- log.trace("Setting exceptionOnValidationFailure parameter: " + this.exceptionOnValidationFailure);
- setRedirectAfterValidation(parseBoolean(getPropertyFromInitParams(filterConfig, "redirectAfterValidation", "true")));
- log.trace("Setting redirectAfterValidation parameter: " + this.redirectAfterValidation);
+ setExceptionOnValidationFailure(parseBoolean(getPropertyFromInitParams(filterConfig,
+ "exceptionOnValidationFailure", "false")));
+ logger.trace("Setting exceptionOnValidationFailure parameter: {}", this.exceptionOnValidationFailure);
+ setRedirectAfterValidation(parseBoolean(getPropertyFromInitParams(filterConfig, "redirectAfterValidation",
+ "true")));
+ logger.trace("Setting redirectAfterValidation parameter: {}", this.redirectAfterValidation);
setUseSession(parseBoolean(getPropertyFromInitParams(filterConfig, "useSession", "true")));
- log.trace("Setting useSession parameter: " + this.useSession);
+ logger.trace("Setting useSession parameter: {}", this.useSession);
+
+ if (!this.useSession && this.redirectAfterValidation) {
+ logger.warn("redirectAfterValidation parameter may not be true when useSession parameter is false. Resetting it to false in order to prevent infinite redirects.");
+ setRedirectAfterValidation(false);
+ }
+
setTicketValidator(getTicketValidator(filterConfig));
super.initInternal(filterConfig);
}
@@ -122,7 +158,8 @@ public void init() {
* @throws IOException if there is an I/O problem
* @throws ServletException if there is a servlet problem.
*/
- protected boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+ protected boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
+ final FilterChain filterChain) throws IOException, ServletException {
return true;
}
@@ -135,8 +172,9 @@ protected boolean preFilter(final ServletRequest servletRequest, final ServletRe
* @param response the HttpServletResponse.
* @param assertion the successful Assertion from the server.
*/
- protected void onSuccessfulValidation(final HttpServletRequest request, final HttpServletResponse response, final Assertion assertion) {
- // nothing to do here.
+ protected void onSuccessfulValidation(final HttpServletRequest request, final HttpServletResponse response,
+ final Assertion assertion) {
+ // nothing to do here.
}
/**
@@ -150,7 +188,8 @@ protected void onFailedValidation(final HttpServletRequest request, final HttpSe
// nothing to do here.
}
- public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+ public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
+ final FilterChain filterChain) throws IOException, ServletException {
if (!preFilter(servletRequest, servletResponse, filterChain)) {
return;
@@ -161,16 +200,13 @@ public final void doFilter(final ServletRequest servletRequest, final ServletRes
final String ticket = retrieveTicketFromRequest(request);
if (CommonUtils.isNotBlank(ticket)) {
- if (log.isDebugEnabled()) {
- log.debug("Attempting to validate ticket: " + ticket);
- }
+ logger.debug("Attempting to validate ticket: {}", ticket);
try {
- final Assertion assertion = this.ticketValidator.validate(ticket, constructServiceUrl(request, response));
+ final Assertion assertion = this.ticketValidator.validate(ticket,
+ constructServiceUrl(request, response));
- if (log.isDebugEnabled()) {
- log.debug("Successfully authenticated user: " + assertion.getPrincipal().getName());
- }
+ logger.debug("Successfully authenticated user: {}", assertion.getPrincipal().getName());
request.setAttribute(CONST_CAS_ASSERTION, assertion);
@@ -180,13 +216,12 @@ public final void doFilter(final ServletRequest servletRequest, final ServletRes
onSuccessfulValidation(request, response, assertion);
if (this.redirectAfterValidation) {
- log. debug("Redirecting after successful ticket validation.");
+ logger.debug("Redirecting after successful ticket validation.");
response.sendRedirect(constructServiceUrl(request, response));
return;
}
} catch (final TicketValidationException e) {
- response.setStatus(HttpServletResponse.SC_FORBIDDEN);
- log.warn(e, e);
+ logger.debug(e.getMessage(), e);
onFailedValidation(request, response);
@@ -194,7 +229,7 @@ public final void doFilter(final ServletRequest servletRequest, final ServletRes
throw new ServletException(e);
}
- response.sendError(HttpServletResponse.SC_FORBIDDEN);
+ response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
return;
}
@@ -205,8 +240,8 @@ public final void doFilter(final ServletRequest servletRequest, final ServletRes
}
public final void setTicketValidator(final TicketValidator ticketValidator) {
- this.ticketValidator = ticketValidator;
-}
+ this.ticketValidator = ticketValidator;
+ }
public final void setRedirectAfterValidation(final boolean redirectAfterValidation) {
this.redirectAfterValidation = redirectAfterValidation;
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractUrlBasedTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractUrlBasedTicketValidator.java
index 0012b5e86..3ea31bdd0 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractUrlBasedTicketValidator.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AbstractUrlBasedTicketValidator.java
@@ -1,55 +1,50 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jasig.cas.client.util.CommonUtils;
-
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
-
-import javax.net.ssl.HostnameVerifier;
+import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
+import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
+import org.jasig.cas.client.util.CommonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* Abstract validator implementation for tickets that must be validated against a server.
*
* @author Scott Battaglia
- * @version $Revision$ $Date$
* @since 3.1
*/
public abstract class AbstractUrlBasedTicketValidator implements TicketValidator {
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
+
/**
- * Commons Logging instance.
- */
- protected final Log log = LogFactory.getLog(getClass());
-
- /**
- * Hostname verifier used when making an SSL request to the CAS server.
+ * URLConnection factory instance to use when making validation requests to the CAS server.
+ * Defaults to {@link HttpsURLConnectionFactory}
*/
- protected HostnameVerifier hostnameVerifier;
+ private HttpURLConnectionFactory urlConnectionFactory = new HttpsURLConnectionFactory();
/**
* Prefix for the CAS server. Should be everything up to the url endpoint, including the /.
@@ -66,7 +61,7 @@ public abstract class AbstractUrlBasedTicketValidator implements TicketValidator
/**
* A map containing custom parameters to pass to the validation url.
*/
- private Map customParameters;
+ private Map customParameters;
private String encoding;
@@ -85,7 +80,7 @@ protected AbstractUrlBasedTicketValidator(final String casServerUrlPrefix) {
*
* @param urlParameters the map containing the parameters.
*/
- protected void populateUrlAttributeMap(final Map urlParameters) {
+ protected void populateUrlAttributeMap(final Map urlParameters) {
// nothing to do
}
@@ -111,9 +106,9 @@ protected void populateUrlAttributeMap(final Map urlParameters) {
* @return the fully constructed URL.
*/
protected final String constructValidationUrl(final String ticket, final String serviceUrl) {
- final Map urlParameters = new HashMap();
+ final Map urlParameters = new HashMap();
- log.debug("Placing URL parameters in map.");
+ logger.debug("Placing URL parameters in map.");
urlParameters.put("ticket", ticket);
urlParameters.put("service", encodeUrl(serviceUrl));
@@ -121,16 +116,17 @@ protected final String constructValidationUrl(final String ticket, final String
urlParameters.put("renew", "true");
}
- log.debug("Calling template URL attribute map.");
+ logger.debug("Calling template URL attribute map.");
populateUrlAttributeMap(urlParameters);
- log.debug("Loading custom parameters from configuration.");
+ logger.debug("Loading custom parameters from configuration.");
if (this.customParameters != null) {
urlParameters.putAll(this.customParameters);
}
final String suffix = getUrlSuffix();
- final StringBuilder buffer = new StringBuilder(urlParameters.size()*10 + this.casServerUrlPrefix.length() + suffix.length() +1);
+ final StringBuilder buffer = new StringBuilder(urlParameters.size() * 10 + this.casServerUrlPrefix.length()
+ + suffix.length() + 1);
int i = 0;
@@ -140,7 +136,7 @@ protected final String constructValidationUrl(final String ticket, final String
}
buffer.append(suffix);
- for (Map.Entry entry : urlParameters.entrySet()) {
+ for (Map.Entry entry : urlParameters.entrySet()) {
final String key = entry.getKey();
final String value = entry.getValue();
@@ -163,10 +159,10 @@ protected final String constructValidationUrl(final String ticket, final String
* @return the encoded url, or the original url if "UTF-8" character encoding could not be found.
*/
protected final String encodeUrl(final String url) {
- if (url == null) {
- return null;
- }
-
+ if (url == null) {
+ return null;
+ }
+
try {
return URLEncoder.encode(url, "UTF-8");
} catch (final UnsupportedEncodingException e) {
@@ -195,24 +191,18 @@ protected final String encodeUrl(final String url) {
protected abstract String retrieveResponseFromServer(URL validationUrl, String ticket);
public final Assertion validate(final String ticket, final String service) throws TicketValidationException {
-
-
final String validationUrl = constructValidationUrl(ticket, service);
- if (log.isDebugEnabled()) {
- log.debug("Constructing validation url: " + validationUrl);
- }
+ logger.debug("Constructing validation url: {}", validationUrl);
try {
- log.debug("Retrieving response from server.");
+ logger.debug("Retrieving response from server.");
final String serverResponse = retrieveResponseFromServer(new URL(validationUrl), ticket);
if (serverResponse == null) {
throw new TicketValidationException("The CAS server returned no response.");
}
-
- if (log.isDebugEnabled()) {
- log.debug("Server response: " + serverResponse);
- }
+
+ logger.debug("Server response: {}", serverResponse);
return parseResponseFromServer(serverResponse);
} catch (final MalformedURLException e) {
@@ -224,13 +214,9 @@ public final void setRenew(final boolean renew) {
this.renew = renew;
}
- public final void setCustomParameters(final Map customParameters) {
+ public final void setCustomParameters(final Map customParameters) {
this.customParameters = customParameters;
}
-
- public final void setHostnameVerifier(final HostnameVerifier verifier) {
- this.hostnameVerifier = verifier;
- }
public final void setEncoding(final String encoding) {
this.encoding = encoding;
@@ -251,4 +237,12 @@ protected final String getCasServerUrlPrefix() {
protected final Map getCustomParameters() {
return this.customParameters;
}
-}
\ No newline at end of file
+
+ protected HttpURLConnectionFactory getURLConnectionFactory() {
+ return this.urlConnectionFactory;
+ }
+
+ public void setURLConnectionFactory(final HttpURLConnectionFactory urlConnectionFactory) {
+ this.urlConnectionFactory = urlConnectionFactory;
+ }
+}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Assertion.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Assertion.java
index 75ac70d40..06d98aa59 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Assertion.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Assertion.java
@@ -1,29 +1,27 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
-import org.jasig.cas.client.authentication.AttributePrincipal;
-
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
+import org.jasig.cas.client.authentication.AttributePrincipal;
/**
* Represents a response to a validation request.
@@ -48,12 +46,20 @@ public interface Assertion extends Serializable {
*/
Date getValidUntilDate();
+ /**
+ * The date the authentication actually occurred on. If its unable to be determined, it should be set to the current
+ * time.
+ *
+ * @return the authentication date, or the current time if it can't be determined.
+ */
+ Date getAuthenticationDate();
+
/**
* The key/value pairs associated with this assertion.
*
* @return the map of attributes.
*/
- Map getAttributes();
+ Map getAttributes();
/**
* The principal for which this assertion is valid.
@@ -61,4 +67,12 @@ public interface Assertion extends Serializable {
* @return the principal.
*/
AttributePrincipal getPrincipal();
+
+ /**
+ * Determines whether an Assertion is considered usable or not. A naive implementation may just check the date validity.
+ *
+ * @return true if its valid, false otherwise.
+ * @since 3.3.0 (though in 3.3.0, no one actually calls this)
+ */
+ boolean isValid();
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AssertionImpl.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AssertionImpl.java
index a845fe871..86e286fd7 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/AssertionImpl.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/AssertionImpl.java
@@ -1,31 +1,29 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
-import org.jasig.cas.client.authentication.AttributePrincipal;
-import org.jasig.cas.client.authentication.AttributePrincipalImpl;
-import org.jasig.cas.client.util.CommonUtils;
-
import java.util.Collections;
import java.util.Date;
import java.util.Map;
+import org.jasig.cas.client.authentication.AttributePrincipal;
+import org.jasig.cas.client.authentication.AttributePrincipalImpl;
+import org.jasig.cas.client.util.CommonUtils;
/**
* Concrete Implementation of the {@link Assertion}.
@@ -38,16 +36,18 @@
public final class AssertionImpl implements Assertion {
/** Unique Id for serialization. */
- private static final long serialVersionUID = -7767943925833639221L;
+ private static final long serialVersionUID = -7767943925833639221L;
- /** The date from which the assertion is valid. */
+ /** The date from which the assertion is valid. */
private final Date validFromDate;
/** The date the assertion is valid until. */
private final Date validUntilDate;
+ private final Date authenticationDate;
+
/** Map of key/value pairs associated with this assertion. I.e. authentication type. */
- private final Map attributes;
+ private final Map attributes;
/** The principal for which this assertion is valid for. */
private final AttributePrincipal principal;
@@ -58,7 +58,7 @@ public final class AssertionImpl implements Assertion {
* @param name the name of the principal for which this assertion is valid.
*/
public AssertionImpl(final String name) {
- this(new AttributePrincipalImpl(name));
+ this(new AttributePrincipalImpl(name));
}
/**
@@ -67,7 +67,7 @@ public AssertionImpl(final String name) {
* @param principal the Principal to associate with the Assertion.
*/
public AssertionImpl(final AttributePrincipal principal) {
- this(principal, Collections.emptyMap());
+ this(principal, Collections. emptyMap());
}
/**
@@ -76,8 +76,8 @@ public AssertionImpl(final AttributePrincipal principal) {
* @param principal the Principal to associate with the Assertion.
* @param attributes the key/value pairs for this attribute.
*/
- public AssertionImpl(final AttributePrincipal principal, final Map attributes) {
- this(principal, new Date(), null, attributes);
+ public AssertionImpl(final AttributePrincipal principal, final Map attributes) {
+ this(principal, new Date(), null, new Date(), attributes);
}
/**
@@ -88,16 +88,23 @@ public AssertionImpl(final AttributePrincipal principal, final Map attributes) {
+ public AssertionImpl(final AttributePrincipal principal, final Date validFromDate, final Date validUntilDate,
+ final Date authenticationDate, final Map attributes) {
this.principal = principal;
this.validFromDate = validFromDate;
this.validUntilDate = validUntilDate;
this.attributes = attributes;
+ this.authenticationDate = authenticationDate;
CommonUtils.assertNotNull(this.principal, "principal cannot be null.");
CommonUtils.assertNotNull(this.validFromDate, "validFromDate cannot be null.");
CommonUtils.assertNotNull(this.attributes, "attributes cannot be null.");
}
+
+ public Date getAuthenticationDate() {
+ return this.authenticationDate;
+ }
+
public Date getValidFromDate() {
return this.validFromDate;
}
@@ -106,11 +113,20 @@ public Date getValidUntilDate() {
return this.validUntilDate;
}
- public Map getAttributes() {
+ public Map getAttributes() {
return this.attributes;
}
public AttributePrincipal getPrincipal() {
return this.principal;
}
+
+ public boolean isValid() {
+ if (this.validFromDate == null) {
+ return true;
+ }
+
+ final Date now = new Date();
+ return this.validFromDate.before(now) && (this.validUntilDate == null || this.validUntilDate.after(now));
+ }
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas10TicketValidationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas10TicketValidationFilter.java
index 51f59e7b2..6e142c921 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas10TicketValidationFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas10TicketValidationFilter.java
@@ -1,25 +1,26 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
import javax.servlet.FilterConfig;
+import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
+import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
/**
* Implementation of AbstractTicketValidatorFilter that instanciates a Cas10TicketValidator.
@@ -36,7 +37,10 @@ protected final TicketValidator getTicketValidator(final FilterConfig filterConf
final String casServerUrlPrefix = getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null);
final Cas10TicketValidator validator = new Cas10TicketValidator(casServerUrlPrefix);
validator.setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
- validator.setHostnameVerifier(getHostnameVerifier(filterConfig));
+
+ final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(filterConfig),
+ getSSLConfig(filterConfig));
+ validator.setURLConnectionFactory(factory);
validator.setEncoding(getPropertyFromInitParams(filterConfig, "encoding", null));
return validator;
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas10TicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas10TicketValidator.java
index 7bdfd0442..dce9a50a0 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas10TicketValidator.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas10TicketValidator.java
@@ -1,22 +1,21 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
import java.io.BufferedReader;
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java
index fb97ac3a2..e256755f5 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyReceivingTicketValidationFilter.java
@@ -1,36 +1,31 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
import java.io.IOException;
import java.util.*;
-
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
import org.jasig.cas.client.proxy.*;
+import org.jasig.cas.client.ssl.HttpURLConnectionFactory;
+import org.jasig.cas.client.ssl.HttpsURLConnectionFactory;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.ReflectUtils;
@@ -49,7 +44,11 @@
*/
public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketValidationFilter {
- private static final String[] RESERVED_INIT_PARAMS = new String[] {"proxyGrantingTicketStorageClass", "proxyReceptorUrl", "acceptAnyProxy", "allowedProxyChains", "casServerUrlPrefix", "proxyCallbackUrl", "renew", "exceptionOnValidationFailure", "redirectAfterValidation", "useSession", "serverName", "service", "artifactParameterName", "serviceParameterName", "encodeServiceUrl", "millisBetweenCleanUps", "hostnameVerifier", "encoding", "config"};
+ private static final String[] RESERVED_INIT_PARAMS = new String[] { "proxyGrantingTicketStorageClass",
+ "proxyReceptorUrl", "acceptAnyProxy", "allowedProxyChains", "casServerUrlPrefix", "proxyCallbackUrl",
+ "renew", "exceptionOnValidationFailure", "redirectAfterValidation", "useSession", "serverName", "service",
+ "artifactParameterName", "serviceParameterName", "encodeServiceUrl", "millisBetweenCleanUps",
+ "hostnameVerifier", "encoding", "config", "ticketValidatorClass" };
private static final int DEFAULT_MILLIS_BETWEEN_CLEANUPS = 60 * 1000;
@@ -63,7 +62,7 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
private TimerTask timerTask;
private int millisBetweenCleanUps;
-
+
/**
* Storage location of ProxyGrantingTickets and Proxy Ticket IOUs.
*/
@@ -72,14 +71,16 @@ public class Cas20ProxyReceivingTicketValidationFilter extends AbstractTicketVal
protected void initInternal(final FilterConfig filterConfig) throws ServletException {
setProxyReceptorUrl(getPropertyFromInitParams(filterConfig, "proxyReceptorUrl", null));
- final String proxyGrantingTicketStorageClass = getPropertyFromInitParams(filterConfig, "proxyGrantingTicketStorageClass", null);
+ final String proxyGrantingTicketStorageClass = getPropertyFromInitParams(filterConfig,
+ "proxyGrantingTicketStorageClass", null);
if (proxyGrantingTicketStorageClass != null) {
this.proxyGrantingTicketStorage = ReflectUtils.newInstance(proxyGrantingTicketStorageClass);
if (this.proxyGrantingTicketStorage instanceof AbstractEncryptedProxyGrantingTicketStorageImpl) {
final AbstractEncryptedProxyGrantingTicketStorageImpl p = (AbstractEncryptedProxyGrantingTicketStorageImpl) this.proxyGrantingTicketStorage;
- final String cipherAlgorithm = getPropertyFromInitParams(filterConfig, "cipherAlgorithm", AbstractEncryptedProxyGrantingTicketStorageImpl.DEFAULT_ENCRYPTION_ALGORITHM);
+ final String cipherAlgorithm = getPropertyFromInitParams(filterConfig, "cipherAlgorithm",
+ AbstractEncryptedProxyGrantingTicketStorageImpl.DEFAULT_ENCRYPTION_ALGORITHM);
final String secretKey = getPropertyFromInitParams(filterConfig, "secretKey", null);
p.setCipherAlgorithm(cipherAlgorithm);
@@ -94,8 +95,9 @@ protected void initInternal(final FilterConfig filterConfig) throws ServletExcep
}
}
- log.trace("Setting proxyReceptorUrl parameter: " + this.proxyReceptorUrl);
- this.millisBetweenCleanUps = Integer.parseInt(getPropertyFromInitParams(filterConfig, "millisBetweenCleanUps", Integer.toString(DEFAULT_MILLIS_BETWEEN_CLEANUPS)));
+ logger.trace("Setting proxyReceptorUrl parameter: {}", this.proxyReceptorUrl);
+ this.millisBetweenCleanUps = Integer.parseInt(getPropertyFromInitParams(filterConfig, "millisBetweenCleanUps",
+ Integer.toString(DEFAULT_MILLIS_BETWEEN_CLEANUPS)));
super.initInternal(filterConfig);
}
@@ -113,6 +115,15 @@ public void init() {
this.timer.schedule(this.timerTask, this.millisBetweenCleanUps, this.millisBetweenCleanUps);
}
+ private T createNewTicketValidator(final String ticketValidatorClass, final String casServerUrlPrefix,
+ final Class clazz) {
+ if (CommonUtils.isBlank(ticketValidatorClass)) {
+ return ReflectUtils.newInstance(clazz, casServerUrlPrefix);
+ }
+
+ return ReflectUtils.newInstance(ticketValidatorClass, casServerUrlPrefix);
+ }
+
/**
* Constructs a Cas20ServiceTicketValidator or a Cas20ProxyTicketValidator based on supplied parameters.
*
@@ -123,23 +134,32 @@ protected final TicketValidator getTicketValidator(final FilterConfig filterConf
final String allowAnyProxy = getPropertyFromInitParams(filterConfig, "acceptAnyProxy", null);
final String allowedProxyChains = getPropertyFromInitParams(filterConfig, "allowedProxyChains", null);
final String casServerUrlPrefix = getPropertyFromInitParams(filterConfig, "casServerUrlPrefix", null);
+ final String ticketValidatorClass = getPropertyFromInitParams(filterConfig, "ticketValidatorClass", null);
final Cas20ServiceTicketValidator validator;
if (CommonUtils.isNotBlank(allowAnyProxy) || CommonUtils.isNotBlank(allowedProxyChains)) {
- final Cas20ProxyTicketValidator v = new Cas20ProxyTicketValidator(casServerUrlPrefix);
+ final Cas20ProxyTicketValidator v = createNewTicketValidator(ticketValidatorClass, casServerUrlPrefix,
+ Cas20ProxyTicketValidator.class);
v.setAcceptAnyProxy(parseBoolean(allowAnyProxy));
v.setAllowedProxyChains(CommonUtils.createProxyList(allowedProxyChains));
validator = v;
} else {
- validator = new Cas20ServiceTicketValidator(casServerUrlPrefix);
+ validator = createNewTicketValidator(ticketValidatorClass, casServerUrlPrefix,
+ Cas20ServiceTicketValidator.class);
}
validator.setProxyCallbackUrl(getPropertyFromInitParams(filterConfig, "proxyCallbackUrl", null));
validator.setProxyGrantingTicketStorage(this.proxyGrantingTicketStorage);
- validator.setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix, getPropertyFromInitParams(filterConfig, "encoding", null)));
+
+ final HttpURLConnectionFactory factory = new HttpsURLConnectionFactory(getHostnameVerifier(filterConfig),
+ getSSLConfig(filterConfig));
+ validator.setURLConnectionFactory(factory);
+
+ validator.setProxyRetriever(new Cas20ProxyRetriever(casServerUrlPrefix, getPropertyFromInitParams(filterConfig,
+ "encoding", null), factory));
validator.setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));
validator.setEncoding(getPropertyFromInitParams(filterConfig, "encoding", null));
- final Map additionalParameters = new HashMap();
+ final Map additionalParameters = new HashMap();
final List params = Arrays.asList(RESERVED_INIT_PARAMS);
for (final Enumeration> e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {
@@ -151,8 +171,6 @@ protected final TicketValidator getTicketValidator(final FilterConfig filterConf
}
validator.setCustomParameters(additionalParameters);
- validator.setHostnameVerifier(getHostnameVerifier(filterConfig));
-
return validator;
}
@@ -164,7 +182,8 @@ public void destroy() {
/**
* This processes the ProxyReceptor request before the ticket validation code executes.
*/
- protected final boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
+ protected final boolean preFilter(final ServletRequest servletRequest, final ServletResponse servletResponse,
+ final FilterChain filterChain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
final String requestUri = request.getRequestURI();
@@ -176,7 +195,7 @@ protected final boolean preFilter(final ServletRequest servletRequest, final Ser
try {
CommonUtils.readAndRespondToProxyReceptorRequest(request, response, this.proxyGrantingTicketStorage);
} catch (final RuntimeException e) {
- log.error(e.getMessage(), e);
+ logger.error(e.getMessage(), e);
throw e;
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidator.java
index cea0a2659..592c33049 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidator.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ProxyTicketValidator.java
@@ -1,33 +1,30 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
-import org.jasig.cas.client.util.XmlUtils;
-
import java.util.List;
+import org.jasig.cas.client.util.XmlUtils;
/**
* Extension to the traditional Service Ticket validation that will validate service tickets and proxy tickets.
*
* @author Scott Battaglia
- * @version $Revision$ $Date$
* @since 3.1
*/
public class Cas20ProxyTicketValidator extends Cas20ServiceTicketValidator {
@@ -37,6 +34,9 @@ public class Cas20ProxyTicketValidator extends Cas20ServiceTicketValidator {
/** This should be a list of an array of Strings */
private ProxyList allowedProxyChains = new ProxyList();
+ /** Allows for an empty chain of proxy callback urls. **/
+ private boolean allowEmptyProxyChain = true;
+
public Cas20ProxyTicketValidator(final String casServerUrlPrefix) {
super(casServerUrlPrefix);
}
@@ -49,15 +49,16 @@ protected String getUrlSuffix() {
return "proxyValidate";
}
- protected void customParseResponse(final String response, final Assertion assertion) throws TicketValidationException {
+ protected void customParseResponse(final String response, final Assertion assertion)
+ throws TicketValidationException {
final List proxies = XmlUtils.getTextForElements(response, "proxy");
- final String[] proxiedList = proxies.toArray(new String[proxies.size()]);
// this means there was nothing in the proxy chain, which is okay
- if (proxies.isEmpty() || this.acceptAnyProxy) {
+ if ((this.allowEmptyProxyChain && proxies.isEmpty()) || this.acceptAnyProxy) {
return;
}
+ final String[] proxiedList = proxies.toArray(new String[proxies.size()]);
if (this.allowedProxyChains.contains(proxiedList)) {
return;
}
@@ -73,7 +74,20 @@ public final void setAllowedProxyChains(final ProxyList allowedProxyChains) {
this.allowedProxyChains = allowedProxyChains;
}
- protected boolean isAcceptAnyProxy() {
+ protected final boolean isAcceptAnyProxy() {
return this.acceptAnyProxy;
}
+
+ protected final boolean isAllowEmptyProxyChain() {
+ return this.allowEmptyProxyChain;
+ }
+
+ /**
+ * Set to determine whether empty proxy chains are allowed.
+ * @see #customParseResponse(String, Assertion)
+ * @param allowEmptyProxyChain whether to allow empty proxy chains or not. True if so, false otherwise.
+ */
+ public final void setAllowEmptyProxyChain(final boolean allowEmptyProxyChain) {
+ this.allowEmptyProxyChain = allowEmptyProxyChain;
+ }
}
diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java
index 9b132f82c..4380348b2 100644
--- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java
+++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java
@@ -1,24 +1,27 @@
-/**
+/*
* 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:
+ * 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
+ * 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
+ * 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.validation;
+import java.io.StringReader;
+import java.util.*;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
import org.jasig.cas.client.authentication.AttributePrincipal;
import org.jasig.cas.client.authentication.AttributePrincipalImpl;
import org.jasig.cas.client.proxy.Cas20ProxyRetriever;
@@ -26,17 +29,16 @@
import org.jasig.cas.client.proxy.ProxyRetriever;
import org.jasig.cas.client.util.CommonUtils;
import org.jasig.cas.client.util.XmlUtils;
-import org.w3c.dom.NodeList;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
/**
* Implementation of the TicketValidator that will validate Service Tickets in compliance with the CAS 2.
*
* @author Scott Battaglia
- * @version $Revision$ $Date$
* @since 3.1
*/
public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTicketValidator {
@@ -55,10 +57,11 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick
* CAS server url prefix.
*
* @param casServerUrlPrefix the CAS Server URL prefix.
+ * @param urlFactory URL connection factory to use when communicating with the server
*/
public Cas20ServiceTicketValidator(final String casServerUrlPrefix) {
super(casServerUrlPrefix);
- this.proxyRetriever = new Cas20ProxyRetriever(casServerUrlPrefix, getEncoding());
+ this.proxyRetriever = new Cas20ProxyRetriever(casServerUrlPrefix, getEncoding(), getURLConnectionFactory());
}
/**
@@ -66,7 +69,7 @@ public Cas20ServiceTicketValidator(final String casServerUrlPrefix) {
*
* @param urlParameters the Map containing the existing parameters to send to the server.
*/
- protected final void populateUrlAttributeMap(final Map urlParameters) {
+ protected final void populateUrlAttributeMap(final Map urlParameters) {
urlParameters.put("pgtUrl", encodeUrl(this.proxyCallbackUrl));
}
@@ -83,12 +86,12 @@ protected final Assertion parseResponseFromServer(final String response) throws
final String principal = XmlUtils.getTextForElement(response, "user");
final String proxyGrantingTicketIou = XmlUtils.getTextForElement(response, "proxyGrantingTicket");
-
+
final String proxyGrantingTicket;
if (CommonUtils.isBlank(proxyGrantingTicketIou) || this.proxyGrantingTicketStorage == null) {
- proxyGrantingTicket = null;
+ proxyGrantingTicket = null;
} else {
- proxyGrantingTicket = this.proxyGrantingTicketStorage.retrieve(proxyGrantingTicketIou);
+ proxyGrantingTicket = this.proxyGrantingTicketStorage.retrieve(proxyGrantingTicketIou);
}
if (CommonUtils.isEmpty(principal)) {
@@ -96,9 +99,10 @@ protected final Assertion parseResponseFromServer(final String response) throws
}
final Assertion assertion;
- final Map attributes = extractCustomAttributes(response);
+ final Map attributes = extractCustomAttributes(response);
if (CommonUtils.isNotBlank(proxyGrantingTicket)) {
- final AttributePrincipal attributePrincipal = new AttributePrincipalImpl(principal, attributes, proxyGrantingTicket, this.proxyRetriever);
+ final AttributePrincipal attributePrincipal = new AttributePrincipalImpl(principal, attributes,
+ proxyGrantingTicket, this.proxyRetriever);
assertion = new AssertionImpl(attributePrincipal);
} else {
assertion = new AssertionImpl(new AttributePrincipalImpl(principal, attributes));
@@ -127,28 +131,19 @@ protected final Assertion parseResponseFromServer(final String response) throws
* @param xml the XML to parse.
* @return the map of attributes.
*/
- protected Map extractCustomAttributes(final String xml) {
-
- if (!xml.contains("")) {
- return Collections.emptyMap();
- }
-
- final Map attributes = new HashMap();
-
+ protected Map extractCustomAttributes(final String xml) {
+ final SAXParserFactory spf = SAXParserFactory.newInstance();
+ spf.setNamespaceAware(true);
+ spf.setValidating(false);
try {
- NodeList nodeList = XmlUtils.getNodeListForElements(xml,"cas:attributes");
- for (int i = 0; i < nodeList.getLength(); i++) {
- final String nodeName = nodeList.item(i).getNodeName();
- final int beginIndex = nodeName.indexOf(":") + 1;
- final int endIndex = nodeList.item(i).getNodeName().length();
-
- final String attributeName = nodeName.substring(beginIndex, endIndex); // remove the "cas:" prefix from node name
- final Object attributeValue = nodeList.item(i).getTextContent();
- attributes.put(attributeName, attributeValue);
- }
- return attributes;
-
- } catch (Exception e) {
+ final SAXParser saxParser = spf.newSAXParser();
+ final XMLReader xmlReader = saxParser.getXMLReader();
+ final CustomAttributeHandler handler = new CustomAttributeHandler();
+ xmlReader.setContentHandler(handler);
+ xmlReader.parse(new InputSource(new StringReader(xml)));
+ return handler.getAttributes();
+ } catch (final Exception e) {
+ logger.error(e.getMessage(), e);
return Collections.emptyMap();
}
}
@@ -160,7 +155,8 @@ protected Map extractCustomAttributes(final String xml) {
* @param assertion the partially constructed assertion.
* @throws TicketValidationException if there is a problem constructing the Assertion.
*/
- protected void customParseResponse(final String response, final Assertion assertion) throws TicketValidationException {
+ protected void customParseResponse(final String response, final Assertion assertion)
+ throws TicketValidationException {
// nothing to do
}
@@ -187,4 +183,67 @@ protected final ProxyGrantingTicketStorage getProxyGrantingTicketStorage() {
protected final ProxyRetriever getProxyRetriever() {
return this.proxyRetriever;
}
+
+ private class CustomAttributeHandler extends DefaultHandler {
+
+ private Map attributes;
+
+ private boolean foundAttributes;
+
+ private String currentAttribute;
+
+ private StringBuilder value;
+
+ @Override
+ public void startDocument() throws SAXException {
+ this.attributes = new HashMap();
+ }
+
+ @Override
+ public void startElement(final String namespaceURI, final String localName, final String qName,
+ final Attributes attributes) throws SAXException {
+ if ("attributes".equals(localName)) {
+ this.foundAttributes = true;
+ } else if (this.foundAttributes) {
+ this.value = new StringBuilder();
+ this.currentAttribute = localName;
+ }
+ }
+
+ @Override
+ public void characters(final char[] chars, final int start, final int length) throws SAXException {
+ if (this.currentAttribute != null) {
+ value.append(chars, start, length);
+ }
+ }
+
+ @Override
+ public void endElement(final String namespaceURI, final String localName, final String qName)
+ throws SAXException {
+ if ("attributes".equals(localName)) {
+ this.foundAttributes = false;
+ this.currentAttribute = null;
+ } else if (this.foundAttributes) {
+ final Object o = this.attributes.get(this.currentAttribute);
+
+ if (o == null) {
+ this.attributes.put(this.currentAttribute, this.value.toString());
+ } else {
+ final List