From b16412731db76c63f750f920a49810c38ff62947 Mon Sep 17 00:00:00 2001 From: Scott Battaglia Date: Tue, 22 Sep 2009 15:26:49 +0000 Subject: [PATCH] CASC-93 added check for role --- cas-client-core/pom.xml | 2 +- .../util/HttpServletRequestWrapperFilter.java | 85 +++++++++++++--- .../HttpServletRequestWrapperFilterTests.java | 97 ++++++++++++++++--- 3 files changed, 153 insertions(+), 31 deletions(-) diff --git a/cas-client-core/pom.xml b/cas-client-core/pom.xml index 20b9f72..4830765 100644 --- a/cas-client-core/pom.xml +++ b/cas-client-core/pom.xml @@ -67,7 +67,7 @@ org.opensaml opensaml - 1.1b + 1.1 jar provided true 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 106f977..e4158e2 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 @@ -5,9 +5,9 @@ */ package org.jasig.cas.client.util; +import org.jasig.cas.client.authentication.AttributePrincipal; import org.jasig.cas.client.validation.Assertion; -import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; @@ -18,20 +18,34 @@ import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpSession; import java.io.IOException; import java.security.Principal; +import java.util.Collection; +import java.util.Iterator; /** * Implementation of a filter that wraps the normal HttpServletRequest with a - * wrapper that overrides the getRemoteUser method to retrieve the user from the - * CAS Assertion. + * wrapper that overrides the following methods to provide data from the + * CAS Assertion: + * *

* This filter needs to be configured in the chain so that it executes after * both the authentication and the validation filters. * * @author Scott Battaglia + * @author Marvin S. Addison * @version $Revision: 11729 $ $Date: 2007-09-26 14:22:30 -0400 (Tue, 26 Sep 2007) $ * @since 3.0 */ -public final class HttpServletRequestWrapperFilter implements Filter { +public final class HttpServletRequestWrapperFilter extends AbstractConfigurationFilter { + + /** 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; public void destroy() { // nothing to do @@ -42,16 +56,13 @@ public final class HttpServletRequestWrapperFilter implements Filter { * 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 { - final Principal principal = retrievePrincipalFromSessionOrRequest(servletRequest); + 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 Principal retrievePrincipalFromSessionOrRequest(final ServletRequest servletRequest) { + 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)); @@ -60,14 +71,15 @@ public final class HttpServletRequestWrapperFilter implements Filter { } public void init(final FilterConfig filterConfig) throws ServletException { - // nothing to do + this.roleAttribute = getPropertyFromInitParams(filterConfig, "roleAttribute", null); + this.ignoreCase = Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "ignoreCase", "false")); } final class CasHttpServletRequestWrapper extends HttpServletRequestWrapper { - private final Principal principal; + private final AttributePrincipal principal; - CasHttpServletRequestWrapper(final HttpServletRequest request, final Principal principal) { + CasHttpServletRequestWrapper(final HttpServletRequest request, final AttributePrincipal principal) { super(request); this.principal = principal; } @@ -79,5 +91,50 @@ public final class HttpServletRequestWrapperFilter implements Filter { public String getRemoteUser() { return principal != null ? this.principal.getName() : null; } + + public boolean isUserInRole(final String role) { + if (CommonUtils.isBlank(role)) { + log.debug("No valid role provided. Returning false."); + return false; + } + + if (this.principal == null) { + log.debug("No Principal in Request. Returning false."); + return false; + } + + if (CommonUtils.isBlank(roleAttribute)) { + log.debug("No Role Attribute Configured. Returning false."); + return false; + } + + final Object value = this.principal.getAttributes().get(roleAttribute); + + if (value instanceof Collection) { + for (final Iterator iter = ((Collection) value).iterator(); iter.hasNext();) { + if (rolesEqual(role, iter.next())) { + log.debug("User [" + getRemoteUser() + "] is in role [" + role + "]: " + true); + return true; + } + } + } + + final boolean isMember = rolesEqual(role, value); + log.debug("User [" + getRemoteUser() + "] is in role [" + role + "]: " + isMember); + return isMember; + } + + /** + * Determines whether the given role is equal to the candidate + * role attribute taking into account case sensitivity. + * + * @param given Role under consideration. + * @param candidate Role that the current user possesses. + * + * @return True if roles are equal, false otherwise. + */ + private boolean rolesEqual(final String given, final Object candidate) { + return ignoreCase ? given.equalsIgnoreCase(candidate.toString()) : given.equals(candidate); + } } } diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/util/HttpServletRequestWrapperFilterTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/util/HttpServletRequestWrapperFilterTests.java index 863b077..4ace6dd 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/util/HttpServletRequestWrapperFilterTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/util/HttpServletRequestWrapperFilterTests.java @@ -6,7 +6,11 @@ package org.jasig.cas.client.util; import junit.framework.TestCase; + +import org.jasig.cas.client.authentication.AttributePrincipal; +import org.jasig.cas.client.authentication.AttributePrincipalImpl; import org.jasig.cas.client.validation.AssertionImpl; +import org.springframework.mock.web.MockFilterConfig; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockHttpSession; @@ -17,6 +21,9 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; /** * Tests for the HttpServletRequestWrapperFilter. @@ -28,33 +35,91 @@ import java.io.IOException; public final class HttpServletRequestWrapperFilterTests extends TestCase { - private HttpServletRequestWrapperFilter filter = new HttpServletRequestWrapperFilter(); - protected HttpServletRequest mockRequest; - protected void setUp() throws Exception { - this.filter.init(null); - this.filter.destroy(); - } - public void testWrappedRequest() throws Exception { + final HttpServletRequestWrapperFilter filter = new HttpServletRequestWrapperFilter(); + filter.init(new MockFilterConfig()); final MockHttpServletRequest request = new MockHttpServletRequest(); final MockHttpSession session = new MockHttpSession(); - final FilterChain filterChain = new FilterChain() { + session.setAttribute( + AbstractCasFilter.CONST_CAS_ASSERTION, + new AssertionImpl("test")); + request.setSession(session); + + filter.doFilter(request, new MockHttpServletResponse(), createFilterChain()); + assertEquals("test", this.mockRequest.getRemoteUser()); + + filter.destroy(); + } + + public void testIsUserInRole() throws Exception { + final MockHttpServletRequest request = new MockHttpServletRequest(); + final MockHttpSession session = new MockHttpSession(); + final MockFilterConfig config = new MockFilterConfig(); + + config.addInitParameter("roleAttribute", "memberOf"); + final HttpServletRequestWrapperFilter filter = new HttpServletRequestWrapperFilter(); + filter.init(config); + + final Map attributes = new HashMap(); + attributes.put("memberOf", "administrators"); + final AttributePrincipal principal = new AttributePrincipalImpl("alice", attributes); + session.setAttribute( + AbstractCasFilter.CONST_CAS_ASSERTION, + new AssertionImpl(principal)); + + request.setSession(session); + + filter.doFilter(request, new MockHttpServletResponse(), createFilterChain()); + assertEquals("alice", this.mockRequest.getRemoteUser()); + assertTrue(this.mockRequest.isUserInRole("administrators")); + assertFalse(this.mockRequest.isUserInRole("ADMINISTRATORS")); + assertFalse(this.mockRequest.isUserInRole("users")); + assertFalse(this.mockRequest.isUserInRole(null)); + + filter.destroy(); + } + + public void testIsUserInRoleCaseInsensitive() throws Exception { + final MockHttpServletRequest request = new MockHttpServletRequest(); + final MockHttpSession session = new MockHttpSession(); + final MockFilterConfig config = new MockFilterConfig(); + + config.addInitParameter("roleAttribute", "groupMembership"); + config.addInitParameter("ignoreCase", "true"); + final HttpServletRequestWrapperFilter filter = new HttpServletRequestWrapperFilter(); + filter.init(config); + + final Map attributes = new HashMap(); + attributes.put("groupMembership", Arrays.asList(new Object[] {"animals", "ducks"})); + final AttributePrincipal principal = new AttributePrincipalImpl("daffy", attributes); + session.setAttribute( + AbstractCasFilter.CONST_CAS_ASSERTION, + new AssertionImpl(principal)); + + request.setSession(session); + + filter.doFilter(request, new MockHttpServletResponse(), createFilterChain()); + assertEquals("daffy", this.mockRequest.getRemoteUser()); + assertTrue(this.mockRequest.isUserInRole("animals")); + assertTrue(this.mockRequest.isUserInRole("ANIMALS")); + assertTrue(this.mockRequest.isUserInRole("ducks")); + assertTrue(this.mockRequest.isUserInRole("DUCKS")); + assertFalse(this.mockRequest.isUserInRole("varmints")); + assertFalse(this.mockRequest.isUserInRole("")); + + filter.destroy(); + } + + private FilterChain createFilterChain() { + return new FilterChain() { public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { HttpServletRequestWrapperFilterTests.this.mockRequest = (HttpServletRequest) request; } }; - session.setAttribute(AbstractCasFilter.CONST_CAS_ASSERTION, - new AssertionImpl("test")); - - request.setSession(session); - - this.filter.doFilter(request, new MockHttpServletResponse(), - filterChain); - assertEquals("test", this.mockRequest.getRemoteUser()); } }