diff --git a/sandbox/portlet/pom.xml b/sandbox/portlet/pom.xml index 3c3bad1897..7cb8a266f0 100644 --- a/sandbox/portlet/pom.xml +++ b/sandbox/portlet/pom.xml @@ -8,7 +8,7 @@ acegi-security-portlet Acegi Security System for Spring - Portlet support - Acegi Security System for Spring - Support for JSR-168 Portlets + Acegi Security System for Spring - Support for JSR 168 Portlets 0.1-SNAPSHOT diff --git a/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationProvider.java b/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationProvider.java index cc4879f27f..6261feb2a7 100644 --- a/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationProvider.java +++ b/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationProvider.java @@ -34,7 +34,7 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** - *

Processes a JSR-168 Portlet authentication request. The request will typically + *

Processes a JSR 168 Portlet authentication request. The request will typically * originate from {@link org.acegisecurity.ui.portlet.PortletProcessingInterceptor}.

* *

Be aware that this provider is trusting the portal and portlet container to handle diff --git a/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationToken.java b/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationToken.java index 172ac121d3..b468468ecc 100644 --- a/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationToken.java +++ b/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/PortletAuthenticationToken.java @@ -20,7 +20,7 @@ import org.acegisecurity.GrantedAuthority; import org.acegisecurity.providers.AbstractAuthenticationToken; /** - * Authentication implementation for JSR-168 Portlet authentication.

The + * Authentication implementation for JSR 168 Portlet authentication.

The * corresponding authentication provider is {@link PortletAuthenticationProvider}.

* * @author John A. Lewis diff --git a/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulator.java b/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulator.java index a1200520a2..044860971c 100644 --- a/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulator.java +++ b/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulator.java @@ -33,9 +33,10 @@ import org.acegisecurity.userdetails.User; import org.acegisecurity.userdetails.UserDetails; /** - * Populates the portlet authorities via role information from the portlet container. + *

Populates the portlet authorities via role information from the portlet container. * Primarily it uses the PortletRequest.isUserInRole(role) method to - * check if the user is in a list of configured roles. + * check if the user is in a list of configured roles.

+ * *

This bean has the following configurable properties:

* * + *

This populator depends on finding the PortletRequest when calling the + * {@link Authentication#getDetails()} method on the object passed to + * {@link #getUserDetails(Authentication)}. If not, it will throw an + * {@link AuthenticationServiceException}. + * * @author John A. Lewis * @since 2.0 * @version $Id$ @@ -56,14 +63,14 @@ public class ContainerPortletAuthoritiesPopulator //~ Static fields/initializers ===================================================================================== - private static final String defaultRolePrefix = "ROLE_"; - private static final String defaultUserRole = "ROLE_USER"; + public static final String DEFAULT_ROLE_PREFIX = "ROLE_"; + public static final String DEFAULT_USER_ROLE = "ROLE_USER"; //~ Instance fields ================================================================================================ - private List rolesToCheck; - private String rolePrefix = defaultRolePrefix; - private String userRole = defaultUserRole; + private List rolesToCheck; + private String rolePrefix = DEFAULT_ROLE_PREFIX; + private String userRole = DEFAULT_USER_ROLE; //~ Methods ======================================================================================================== @@ -77,7 +84,7 @@ public class ContainerPortletAuthoritiesPopulator // see if we can load authorities from the portlet request Object details = authentication.getDetails(); if (!(details instanceof PortletRequest)) { - throw new AuthenticationServiceException("expected getDetails() to return the PortletRequest object"); + throw new AuthenticationServiceException("expected Authentication.getDetails() to return a PortletRequest"); } GrantedAuthority[] authorities = loadGrantedAuthorities((PortletRequest)details); @@ -89,7 +96,8 @@ public class ContainerPortletAuthoritiesPopulator // start the list and add the standard user role ArrayList authorities = new ArrayList(); - authorities.add(new GrantedAuthorityImpl(getUserRole())); + if (this.userRole != null && this.userRole.length() > 0) + authorities.add(new GrantedAuthorityImpl(getUserRole())); // iterate through the configured list of roles to check (if there is one) if (this.rolesToCheck != null) { @@ -104,7 +112,7 @@ public class ContainerPortletAuthoritiesPopulator } } - // return the array of GrantedAuthority objects + // return the array of GrantedAuthority objects return (GrantedAuthority[])authorities.toArray(new GrantedAuthority[authorities.size()]); } diff --git a/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulator.java b/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulator.java index f84416658c..56ea370ecd 100644 --- a/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulator.java +++ b/sandbox/portlet/src/main/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulator.java @@ -38,7 +38,7 @@ public class DaoPortletAuthoritiesPopulator //~ Instance fields ================================================================================================ - private UserDetailsService userDetailsService; + private UserDetailsService userDetailsService; //~ Methods ======================================================================================================== diff --git a/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptor.java b/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptor.java index e90f30f99a..37c6c75264 100644 --- a/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptor.java +++ b/sandbox/portlet/src/main/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptor.java @@ -17,6 +17,7 @@ package org.acegisecurity.ui.portlet; import java.io.IOException; +import java.security.Principal; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -25,6 +26,7 @@ import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import javax.portlet.PortletRequest; import javax.portlet.PortletResponse; +import javax.portlet.PortletSession; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; @@ -52,8 +54,8 @@ import org.springframework.web.portlet.ModelAndView; * {@link Authentication} object will be placed into the SecurityContext, which * is guaranteed to have already been created by an earlier interceptor. If authentication * fails, the AuthenticationException will be placed into the - * PortletSession with the attribute defined by - * {@link AbstractProcessingFilter#ACEGI_SECURITY_LAST_EXCEPTION_KEY}.

+ * APPLICATION_SCOPE of the PortletSession with the attribute defined + * by {@link AbstractProcessingFilter#ACEGI_SECURITY_LAST_EXCEPTION_KEY}.

* *

Some portals do not properly provide the identity of the current user via the * getRemoteUser() or getUserPrincipal() methods of the @@ -167,7 +169,9 @@ public class PortletProcessingInterceptor implements if (logger.isDebugEnabled()) logger.debug("Authentication failed - updating ContextHolder to contain null Authentication"); ctx.setAuthentication(null); - request.getPortletSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY, failed); + request.getPortletSession().setAttribute( + AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY, + failed, PortletSession.APPLICATION_SCOPE); onUnsuccessfulAuthentication(request, response, failed); } } @@ -177,7 +181,7 @@ public class PortletProcessingInterceptor implements /** * This method attempts to extract a principal from the portlet request. - * According to the JSR-168 spec, the PortletRequest should return the name + * According to the JSR 168 spec, the PortletRequest should return the name * of the user in the getRemoteUser() method. It should also provide a * java.security.Principal object from the getUserPrincipal() * method. We will first try these to come up with a valid username. @@ -186,22 +190,25 @@ public class PortletProcessingInterceptor implements * property has been populated, then we will search through the USER_INFO * map from the request to see if we can find a valid username. *

This method can be overridden by subclasses to provide special handling - * for portals with weak support for the JSR-168 spec.

+ * for portals with weak support for the JSR 168 spec.

* @param request the portlet request object * @return the determined principal object, or null if none found */ protected Object getPrincipalFromRequest(PortletRequest request) { // first try getRemoteUser() - Object principal = request.getRemoteUser(); - if (principal != null) { - return principal; + String remoteUser = request.getRemoteUser(); + if (remoteUser != null) { + return remoteUser; } // next try getUserPrincipal() - principal = request.getUserPrincipal(); - if (principal != null) { - return principal; + Principal userPrincipal = request.getUserPrincipal(); + if (userPrincipal != null) { + String userPrincipalName = userPrincipal.getName(); + if (userPrincipalName != null) { + return userPrincipalName; + } } // last try entries in USER_INFO if any attributes were defined @@ -213,9 +220,9 @@ public class PortletProcessingInterceptor implements logger.warn("unable to retrieve USER_INFO map from portlet request", e); } if (userInfo != null) { - Iterator i = this.userNameAttributes.iterator(); - while(i.hasNext()) { - principal = (String)userInfo.get(i.next()); + Iterator i = this.userNameAttributes.iterator(); + while(i.hasNext()) { + Object principal = (String)userInfo.get(i.next()); if (principal != null) { return principal; } @@ -231,13 +238,13 @@ public class PortletProcessingInterceptor implements * This method attempts to extract a credentials from the portlet request. * We are trusting the portal framework to authenticate the user, so all * we are really doing is trying to put something intelligent in here to - * indicate the user is authenticated. According to the JSR-168 spec, + * indicate the user is authenticated. According to the JSR 168 spec, * PortletRequest.getAuthType() should return a non-null value if the * user is authenticated and should be null if not authenticated. So we * will use this as the credentials and the token will be trusted as * authenticated if the credentials are not null. *

This method can be overridden by subclasses to provide special handling - * for portals with weak support for the JSR-168 spec. If that is done, + * for portals with weak support for the JSR 168 spec. If that is done, * be sure the value is non-null for authenticated users and null for * non-authenticated users.

* @param request the portlet request object @@ -255,28 +262,28 @@ public class PortletProcessingInterceptor implements * @throws AuthenticationException to indicate that authentication attempt is not valid and should be terminated * @throws IOException */ - protected void onPreAuthentication(PortletRequest request, PortletResponse response) - throws AuthenticationException, IOException {} - - /** - * Callback for custom processing after a successful authentication attempt. - * @param request the portlet request that was authenticated - * @param response the portlet response that was authenticated - * @param authResult the resulting Authentication object - * @throws IOException - */ - protected void onSuccessfulAuthentication(PortletRequest request, PortletResponse response, Authentication authResult) - throws IOException {} - - /** - * Callback for custom processing after an unsuccessful authentication attempt. - * @param request the portlet request that failed authentication - * @param response the portlet response that failed authentication - * @param failed the AuthenticationException that occurred - * @throws IOException - */ - protected void onUnsuccessfulAuthentication(PortletRequest request, PortletResponse response, AuthenticationException failed) - throws IOException {} + protected void onPreAuthentication(PortletRequest request, PortletResponse response) + throws AuthenticationException, IOException {} + + /** + * Callback for custom processing after a successful authentication attempt. + * @param request the portlet request that was authenticated + * @param response the portlet response that was authenticated + * @param authResult the resulting Authentication object + * @throws IOException + */ + protected void onSuccessfulAuthentication(PortletRequest request, PortletResponse response, Authentication authResult) + throws IOException {} + + /** + * Callback for custom processing after an unsuccessful authentication attempt. + * @param request the portlet request that failed authentication + * @param response the portlet response that failed authentication + * @param failed the AuthenticationException that occurred + * @throws IOException + */ + protected void onUnsuccessfulAuthentication(PortletRequest request, PortletResponse response, AuthenticationException failed) + throws IOException {} public AuthenticationManager getAuthenticationManager() { diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/context/PortletSessionContextIntegrationInterceptorTests.java b/sandbox/portlet/src/test/java/org/acegisecurity/context/PortletSessionContextIntegrationInterceptorTests.java new file mode 100644 index 0000000000..8d03c8c464 --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/context/PortletSessionContextIntegrationInterceptorTests.java @@ -0,0 +1,372 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.context; + +import javax.portlet.PortletSession; + +import junit.framework.TestCase; + +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.providers.portlet.PortletAuthenticationToken; +import org.acegisecurity.providers.portlet.PortletTestUtils; +import org.acegisecurity.userdetails.User; +import org.springframework.mock.web.portlet.MockActionRequest; +import org.springframework.mock.web.portlet.MockActionResponse; +import org.springframework.mock.web.portlet.MockRenderRequest; +import org.springframework.mock.web.portlet.MockRenderResponse; + +/** + * Tests {@link PortletSessionContextIntegrationInterceptor}. + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class PortletSessionContextIntegrationInterceptorTests extends TestCase { + + //~ Constructors =================================================================================================== + + public PortletSessionContextIntegrationInterceptorTests() { + super(); + } + + public PortletSessionContextIntegrationInterceptorTests(String arg0) { + super(arg0); + } + + //~ Methods ======================================================================================================== + + public void setUp() throws Exception { + super.setUp(); + SecurityContextHolder.clearContext(); + } + + public void tearDown() throws Exception { + super.tearDown(); + SecurityContextHolder.clearContext(); + } + + public void testDetectsIncompatibleSessionProperties() throws Exception { + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + try { + interceptor.setAllowSessionCreation(false); + interceptor.setForceEagerSessionCreation(true); + interceptor.afterPropertiesSet(); + fail("Shown have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + // ignore + } + interceptor.setAllowSessionCreation(true); + interceptor.afterPropertiesSet(); + } + + public void testDetectsMissingOrInvalidContext() throws Exception { + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + try { + interceptor.setContext(null); + interceptor.afterPropertiesSet(); + fail("Shown have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + // ignore + } + try { + interceptor.setContext(Integer.class); + assertEquals(Integer.class, interceptor.getContext()); + interceptor.afterPropertiesSet(); + fail("Shown have thrown IllegalArgumentException"); + } catch (IllegalArgumentException expected) { + // ignore + } + } + + public void testNormalRenderRequestProcessing() throws Exception { + + // Build an Authentication object we simulate came from PortletSession + PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken(); + PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken(); + + // Build a Context to store in PortletSession (simulating prior request) + SecurityContext sc = new SecurityContextImpl(); + sc.setAuthentication(sessionPrincipal); + + // Build mock request and response + MockRenderRequest request = PortletTestUtils.createRenderRequest(); + MockRenderResponse response = PortletTestUtils.createRenderResponse(); + request.getPortletSession().setAttribute( + PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, + sc, PortletSession.APPLICATION_SCOPE); + + // Prepare interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.afterPropertiesSet(); + + // Verify the SecurityContextHolder starts empty + assertNull(SecurityContextHolder.getContext().getAuthentication()); + + // Run preHandleRender phase and verify SecurityContextHolder contains our Authentication + interceptor.preHandleRender(request, response, null); + assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); + + // Run postHandleRender phase and verify the SecurityContextHolder still contains our Authentication + interceptor.postHandleRender(request, response, null, null); + assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); + + // Run afterRenderCompletion phase and verify the SecurityContextHolder is empty + interceptor.afterRenderCompletion(request, response, null, null); + assertNull(SecurityContextHolder.getContext().getAuthentication()); + } + + public void testNormalActionRequestProcessing() throws Exception { + + // Build an Authentication object we simulate came from PortletSession + PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken(); + PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken(); + + // Build a Context to store in PortletSession (simulating prior request) + SecurityContext sc = new SecurityContextImpl(); + sc.setAuthentication(sessionPrincipal); + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + request.getPortletSession().setAttribute( + PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, + sc, PortletSession.APPLICATION_SCOPE); + + // Prepare interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.afterPropertiesSet(); + + // Verify the SecurityContextHolder starts empty + assertNull(SecurityContextHolder.getContext().getAuthentication()); + + // Run preHandleAction phase and verify SecurityContextHolder contains our Authentication + interceptor.preHandleAction(request, response, null); + assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); + + // Run afterActionCompletion phase and verify the SecurityContextHolder is empty + interceptor.afterActionCompletion(request, response, null, null); + assertNull(SecurityContextHolder.getContext().getAuthentication()); + } + + public void testUpdatesCopiedBackIntoSession() throws Exception { + + // Build an Authentication object we simulate came from PortletSession + PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken(); + PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken(); + + // Build a Context to store in PortletSession (simulating prior request) + SecurityContext sc = new SecurityContextImpl(); + sc.setAuthentication(sessionPrincipal); + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + request.getPortletSession().setAttribute( + PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, + sc, PortletSession.APPLICATION_SCOPE); + + // Prepare interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.afterPropertiesSet(); + + // Verify the SecurityContextHolder starts empty + assertNull(SecurityContextHolder.getContext().getAuthentication()); + + // Run preHandleAction phase and verify SecurityContextHolder contains our Authentication + interceptor.preHandleAction(request, response, null); + assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); + + // Perform updates to principal + sessionPrincipal = PortletTestUtils.createAuthenticatedToken( + new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")})); + baselinePrincipal = PortletTestUtils.createAuthenticatedToken( + new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")})); + + // Store updated principal into SecurityContextHolder + SecurityContextHolder.getContext().setAuthentication(sessionPrincipal); + + // Run afterActionCompletion phase and verify the SecurityContextHolder is empty + interceptor.afterActionCompletion(request, response, null, null); + assertNull(SecurityContextHolder.getContext().getAuthentication()); + + // Verify the new principal is stored in the session + sc = (SecurityContext)request.getPortletSession().getAttribute( + PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, + PortletSession.APPLICATION_SCOPE); + assertEquals(baselinePrincipal, sc.getAuthentication()); + } + + public void testPortletSessionCreatedWhenContextHolderChanges() throws Exception { + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + + // Prepare the interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.afterPropertiesSet(); + + // Execute the interceptor + interceptor.preHandleAction(request, response, null); + PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken(); + SecurityContextHolder.getContext().setAuthentication(principal); + interceptor.afterActionCompletion(request, response, null, null); + + // Verify Authentication is in the PortletSession + SecurityContext sc = (SecurityContext)request.getPortletSession(false). + getAttribute(PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, PortletSession.APPLICATION_SCOPE); + assertEquals(principal, ((SecurityContext)sc).getAuthentication()); + } + + public void testPortletSessionEagerlyCreatedWhenDirected() throws Exception { + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + + // Prepare the interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.setForceEagerSessionCreation(true); // non-default + interceptor.afterPropertiesSet(); + + // Execute the interceptor + interceptor.preHandleAction(request, response, null); + interceptor.afterActionCompletion(request, response, null, null); + + // Check the session is not null + assertNotNull(request.getPortletSession(false)); + } + + public void testPortletSessionNotCreatedUnlessContextHolderChanges() throws Exception { + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + + // Prepare the interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.afterPropertiesSet(); + + // Execute the interceptor + interceptor.preHandleAction(request, response, null); + interceptor.afterActionCompletion(request, response, null, null); + + // Check the session is null + assertNull(request.getPortletSession(false)); + } + + public void testPortletSessionWithNonContextInWellKnownLocationIsOverwritten() + throws Exception { + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + request.getPortletSession().setAttribute( + PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, + "NOT_A_CONTEXT_OBJECT", PortletSession.APPLICATION_SCOPE); + + // Prepare the interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.afterPropertiesSet(); + + // Execute the interceptor + interceptor.preHandleAction(request, response, null); + PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken(); + SecurityContextHolder.getContext().setAuthentication(principal); + interceptor.afterActionCompletion(request, response, null, null); + + // Verify Authentication is in the PortletSession + SecurityContext sc = (SecurityContext)request.getPortletSession(false). + getAttribute(PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, PortletSession.APPLICATION_SCOPE); + assertEquals(principal, ((SecurityContext)sc).getAuthentication()); + } + + public void testPortletSessionCreationNotAllowed() throws Exception { + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + + // Prepare the interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.setAllowSessionCreation(false); // non-default + interceptor.afterPropertiesSet(); + + // Execute the interceptor + interceptor.preHandleAction(request, response, null); + PortletAuthenticationToken principal = PortletTestUtils.createAuthenticatedToken(); + SecurityContextHolder.getContext().setAuthentication(principal); + interceptor.afterActionCompletion(request, response, null, null); + + // Check the session is null + assertNull(request.getPortletSession(false)); + } + + public void testUsePortletScopeSession() throws Exception { + + // Build an Authentication object we simulate came from PortletSession + PortletAuthenticationToken sessionPrincipal = PortletTestUtils.createAuthenticatedToken(); + PortletAuthenticationToken baselinePrincipal = PortletTestUtils.createAuthenticatedToken(); + + // Build a Context to store in PortletSession (simulating prior request) + SecurityContext sc = new SecurityContextImpl(); + sc.setAuthentication(sessionPrincipal); + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + request.getPortletSession().setAttribute( + PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, + sc, PortletSession.PORTLET_SCOPE); + + // Prepare interceptor + PortletSessionContextIntegrationInterceptor interceptor = new PortletSessionContextIntegrationInterceptor(); + interceptor.setUseApplicationScopePortletSession(false); // non-default + interceptor.afterPropertiesSet(); + + // Run preHandleAction phase and verify SecurityContextHolder contains our Authentication + interceptor.preHandleAction(request, response, null); + assertEquals(baselinePrincipal, SecurityContextHolder.getContext().getAuthentication()); + + // Perform updates to principal + sessionPrincipal = PortletTestUtils.createAuthenticatedToken( + new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")})); + baselinePrincipal = PortletTestUtils.createAuthenticatedToken( + new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl("UPDATEDROLE1")})); + + // Store updated principal into SecurityContextHolder + SecurityContextHolder.getContext().setAuthentication(sessionPrincipal); + + // Run afterActionCompletion phase and verify the SecurityContextHolder is empty + interceptor.afterActionCompletion(request, response, null, null); + assertNull(SecurityContextHolder.getContext().getAuthentication()); + + // Verify the new principal is stored in the session + sc = (SecurityContext)request.getPortletSession().getAttribute( + PortletSessionContextIntegrationInterceptor.ACEGI_SECURITY_CONTEXT_KEY, + PortletSession.PORTLET_SCOPE); + assertEquals(baselinePrincipal, sc.getAuthentication()); + } + + +} diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthenticationProviderTests.java b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthenticationProviderTests.java new file mode 100644 index 0000000000..be494016a2 --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthenticationProviderTests.java @@ -0,0 +1,117 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.providers.portlet; + +import junit.framework.TestCase; + +import org.acegisecurity.Authentication; +import org.acegisecurity.AuthenticationException; +import org.acegisecurity.BadCredentialsException; +import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import org.acegisecurity.userdetails.UserDetails; + +/** + * Tests {@link PortletAuthenticationProvider} + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class PortletAuthenticationProviderTests extends TestCase { + + //~ Constructors =================================================================================================== + + public PortletAuthenticationProviderTests() { + super(); + } + + public PortletAuthenticationProviderTests(String arg0) { + super(arg0); + } + + //~ Methods ======================================================================================================== + + public void testRequiresPopulator() throws Exception { + PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); + try { + provider.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException failed) { + //ignored + } + } + + public void testNormalOperation() throws Exception { + PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); + provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(false)); + provider.afterPropertiesSet(); + Authentication result = provider.authenticate(PortletTestUtils.createToken()); + assertNotNull(result); + assertNotNull(result.getAuthorities()); + } + + public void testAuthenticationIsNullWithUnsupportedToken() { + PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); + Authentication request = new UsernamePasswordAuthenticationToken(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED); + Authentication result = provider.authenticate(request); + assertNull(result); + } + + public void testFailsWithNoCredentials() { + PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); + provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(false)); + try { + provider.authenticate(new PortletAuthenticationToken(PortletTestUtils.TESTUSER, null, null)); + fail("Should have thrown BadCredentialsException"); + } catch (BadCredentialsException e) { + //ignore + } + } + + public void testPopulatorRejectionCausesFailure() throws Exception { + PortletAuthenticationProvider provider = new PortletAuthenticationProvider(); + provider.setPortletAuthoritiesPopulator(new MockAuthoritiesPopulator(true)); + try { + provider.authenticate(PortletTestUtils.createToken()); + fail("Should have thrown BadCredentialsException"); + } catch (BadCredentialsException e) { + //ignore + } + } + + //~ Inner Classes ================================================================================================== + + public static class MockAuthoritiesPopulator implements PortletAuthoritiesPopulator { + + private boolean reject = false; + + public MockAuthoritiesPopulator (boolean reject) { + this.reject = reject; + } + + public UserDetails getUserDetails(Authentication authentication) + throws AuthenticationException { + if (authentication.getCredentials() == null) + throw new BadCredentialsException("Invalid Credentials"); + if (reject) + throw new BadCredentialsException("Authentication Rejected"); + return PortletTestUtils.createUser(); + } + + } + +} diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthenticationTokenTests.java b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthenticationTokenTests.java new file mode 100644 index 0000000000..6a3e9eb653 --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletAuthenticationTokenTests.java @@ -0,0 +1,63 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.providers.portlet; + +import junit.framework.TestCase; + +/** + * Tests for {@link PortletAuthenticationToken}. + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class PortletAuthenticationTokenTests extends TestCase { + + //~ Constructors =================================================================================================== + + public PortletAuthenticationTokenTests() {} + + public PortletAuthenticationTokenTests(String s) { + super(s); + } + + //~ Methods ======================================================================================================== + + public void setUp() throws Exception { + super.setUp(); + } + + public void testPrincipal() throws Exception { + PortletAuthenticationToken token = PortletTestUtils.createToken(); + assertEquals(PortletTestUtils.TESTUSER, token.getPrincipal()); + } + + public void testCredentials() throws Exception { + PortletAuthenticationToken token = PortletTestUtils.createToken(); + assertEquals(PortletTestUtils.TESTCRED, token.getCredentials()); + } + + public void testAuthenticated() throws Exception { + PortletAuthenticationToken token = PortletTestUtils.createToken(); + assertTrue(!token.isAuthenticated()); + token.setAuthenticated(true); + assertTrue(token.isAuthenticated()); + token.setAuthenticated(false); + assertTrue(!token.isAuthenticated()); + } + +} diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletTestUtils.java b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletTestUtils.java new file mode 100644 index 0000000000..c2e4156e32 --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/PortletTestUtils.java @@ -0,0 +1,128 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.providers.portlet; + +import javax.portlet.PortletRequest; + +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.context.SecurityContext; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.context.SecurityContextImpl; +import org.acegisecurity.providers.TestingAuthenticationToken; +import org.acegisecurity.userdetails.User; +import org.acegisecurity.userdetails.UserDetails; +import org.springframework.mock.web.portlet.MockActionRequest; +import org.springframework.mock.web.portlet.MockActionResponse; +import org.springframework.mock.web.portlet.MockPortletRequest; +import org.springframework.mock.web.portlet.MockRenderRequest; +import org.springframework.mock.web.portlet.MockRenderResponse; + +/** + * Utilities for testing Portlet (JSR 168) based security. + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class PortletTestUtils { + + //~ Static fields/initializers ===================================================================================== + + public static final String PORTALROLE1 = "ONE"; + public static final String PORTALROLE2 = "TWO"; + + public static final String TESTUSER = "testuser"; + public static final String TESTCRED = PortletRequest.FORM_AUTH; + public static final String TESTROLE1 = "ROLE_" + PORTALROLE1; + public static final String TESTROLE2 = "ROLE_" + PORTALROLE2; + + //~ Methods ======================================================================================================== + + public static UserDetails createUser() { + return new User(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, true, true, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl(TESTROLE1), new GrantedAuthorityImpl(TESTROLE2)}); + } + + public static void applyPortletRequestSecurity(MockPortletRequest request) { + request.setRemoteUser(TESTUSER); + request.setUserPrincipal(new TestingAuthenticationToken(TESTUSER, TESTCRED, null)); + request.addUserRole(PORTALROLE1); + request.addUserRole(PORTALROLE2); + request.setAuthType(PortletRequest.FORM_AUTH); + } + + public static MockRenderRequest createRenderRequest() { + MockRenderRequest request = new MockRenderRequest(); + applyPortletRequestSecurity(request); + return request; + } + + public static MockRenderResponse createRenderResponse() { + MockRenderResponse response = new MockRenderResponse(); + return response; + } + + public static MockActionRequest createActionRequest() { + MockActionRequest request = new MockActionRequest(); + applyPortletRequestSecurity(request); + return request; + } + + public static MockActionResponse createActionResponse() { + MockActionResponse response = new MockActionResponse(); + return response; + } + + public static PortletAuthenticationToken createToken(PortletRequest request) { + PortletAuthenticationToken token = new PortletAuthenticationToken(TESTUSER, TESTCRED, null); + token.setDetails(request); + return token; + } + + public static PortletAuthenticationToken createToken() { + MockRenderRequest request = createRenderRequest(); + return createToken(request); + } + + public static PortletAuthenticationToken createAuthenticatedToken(UserDetails user) { + PortletAuthenticationToken result = new PortletAuthenticationToken( + user, user.getPassword(), user.getAuthorities()); + result.setAuthenticated(true); + return result; + } + public static PortletAuthenticationToken createAuthenticatedToken() { + return createAuthenticatedToken(createUser()); + } + + public static void setupSecurityContext(PortletRequest request) { + PortletAuthenticationToken token = createToken(request); + SecurityContext context = new SecurityContextImpl(); + context.setAuthentication(token); + SecurityContextHolder.setContext(context); + } + + public static void setupSecurityContext() { + MockRenderRequest request = createRenderRequest(); + setupSecurityContext(request); + } + + public static void cleanupSecurityContext() { + SecurityContextHolder.clearContext(); + } + +} diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/cache/EhCacheBasedUserCacheTests.java b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/cache/EhCacheBasedUserCacheTests.java new file mode 100644 index 0000000000..dc37b68c2b --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/cache/EhCacheBasedUserCacheTests.java @@ -0,0 +1,90 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.providers.portlet.cache; + +import java.io.IOException; + +import junit.framework.TestCase; +import net.sf.ehcache.Cache; + +import org.acegisecurity.providers.portlet.PortletTestUtils; +import org.springframework.cache.ehcache.EhCacheFactoryBean; + +/** + * Tests for {@link EhCacheBasedPortletUserCache}. + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class EhCacheBasedUserCacheTests extends TestCase { + + //~ Static fields/initializers ===================================================================================== + + private static EhCacheFactoryBean cacheFactory; + + static { + cacheFactory = new EhCacheFactoryBean(); + cacheFactory.setCacheName("portletUserCache"); + try { + cacheFactory.afterPropertiesSet(); + } catch (IOException e) { + throw new RuntimeException("unable to initialize cache factory", e); + } + } + + //~ Constructors =================================================================================================== + + public EhCacheBasedUserCacheTests() { + super(); + } + + public EhCacheBasedUserCacheTests(String arg0) { + super(arg0); + } + + //~ Methods ======================================================================================================== + + public final void setUp() throws Exception { + super.setUp(); + } + + private Cache getCache() { + return (Cache)cacheFactory.getObject(); + } + + public void testCacheOperation() throws Exception { + + // Create the cache + EhCacheBasedUserCache cache = new EhCacheBasedUserCache(); + cache.setCache(getCache()); + cache.afterPropertiesSet(); + + // Check it gets stored in the cache + cache.putUserInCache(PortletTestUtils.createUser()); + assertEquals(PortletTestUtils.TESTCRED, + cache.getUserFromCache(PortletTestUtils.TESTUSER).getPassword()); + + // Check it gets removed from the cache + cache.removeUserFromCache(PortletTestUtils.TESTUSER); + assertNull(cache.getUserFromCache(PortletTestUtils.TESTUSER)); + + // Check it doesn't return values for null user + assertNull(cache.getUserFromCache(null)); + } + +} diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulatorTests.java b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulatorTests.java new file mode 100644 index 0000000000..02871cb4ec --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/ContainerPortletAuthoritiesPopulatorTests.java @@ -0,0 +1,127 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.providers.portlet.populator; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.acegisecurity.AuthenticationServiceException; +import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.providers.portlet.PortletAuthenticationToken; +import org.acegisecurity.providers.portlet.PortletTestUtils; +import org.acegisecurity.userdetails.UserDetails; + + +/** + * Tests for {@link ContainerPortletAuthoritiesPopulator} + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class ContainerPortletAuthoritiesPopulatorTests extends TestCase { + + //~ Constructors =================================================================================================== + + public ContainerPortletAuthoritiesPopulatorTests() { + super(); + } + + public ContainerPortletAuthoritiesPopulatorTests(String arg0) { + super(arg0); + } + + //~ Methods ======================================================================================================== + + public final void setUp() throws Exception { + super.setUp(); + } + + private List createRolesToCheck() { + ArrayList rolesToCheck = new ArrayList(); + rolesToCheck.add(PortletTestUtils.PORTALROLE1); + rolesToCheck.add("BOGUS1"); + rolesToCheck.add(PortletTestUtils.PORTALROLE2); + rolesToCheck.add("BOGUS2"); + return rolesToCheck; + } + + public void testGetGrantedAuthorities() throws Exception { + ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); + UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); + assertEquals(1, results.getAuthorities().length); + assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]); + } + + public void testGetGrantedAuthoritiesCheckRoles() throws Exception { + ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); + populator.setRolesToCheck(createRolesToCheck()); + UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); + assertEquals(3, results.getAuthorities().length); + assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]); + assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), results.getAuthorities()[1]); + assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2), results.getAuthorities()[2]); + } + + public void testGetGrantedAuthoritiesCustomPrefix() throws Exception { + String prefix = "IHAVE_"; + ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); + populator.setRolesToCheck(createRolesToCheck()); + populator.setRolePrefix(prefix); + UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); + assertEquals(3, results.getAuthorities().length); + assertEquals(new GrantedAuthorityImpl(ContainerPortletAuthoritiesPopulator.DEFAULT_USER_ROLE), results.getAuthorities()[0]); + assertEquals(new GrantedAuthorityImpl(prefix + PortletTestUtils.PORTALROLE1), results.getAuthorities()[1]); + assertEquals(new GrantedAuthorityImpl(prefix + PortletTestUtils.PORTALROLE2), results.getAuthorities()[2]); + } + + public void testGetGrantedAuthoritiesNullDefault() throws Exception { + ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); + populator.setUserRole(null); + UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); + assertEquals(0, results.getAuthorities().length); + } + + public void testGetGrantedAuthoritiesEmptyDefault() throws Exception { + ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); + populator.setUserRole(""); + UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); + assertEquals(0, results.getAuthorities().length); + } + + public void testGetGrantedAuthoritiesForInvalidToken() throws Exception { + ContainerPortletAuthoritiesPopulator populator = new ContainerPortletAuthoritiesPopulator(); + PortletAuthenticationToken token = PortletTestUtils.createToken(); + token.setDetails(null); + try { + populator.getUserDetails(token); + fail("Should have thrown AuthenticationServiceException"); + } catch (AuthenticationServiceException e) { + // ignore + } + token.setDetails("bogus"); + try { + populator.getUserDetails(token); + fail("Should have thrown AuthenticationServiceException"); + } catch (AuthenticationServiceException e) { + // ignore + } + } + +} diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulatorTests.java b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulatorTests.java new file mode 100644 index 0000000000..a40607a55b --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/providers/portlet/populator/DaoPortletAuthoritiesPopulatorTests.java @@ -0,0 +1,100 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.providers.portlet.populator; + +import junit.framework.TestCase; + +import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.providers.portlet.PortletAuthenticationToken; +import org.acegisecurity.providers.portlet.PortletTestUtils; +import org.acegisecurity.userdetails.UserDetails; +import org.acegisecurity.userdetails.UserDetailsService; +import org.acegisecurity.userdetails.UsernameNotFoundException; +import org.springframework.dao.DataAccessException; + + +/** + * Tests for {@link DaoPortletAuthoritiesPopulator} + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class DaoPortletAuthoritiesPopulatorTests extends TestCase { + + //~ Constructors =================================================================================================== + + public DaoPortletAuthoritiesPopulatorTests() { + super(); + } + + public DaoPortletAuthoritiesPopulatorTests(String arg0) { + super(arg0); + } + + //~ Methods ======================================================================================================== + + public final void setUp() throws Exception { + super.setUp(); + } + + public void testRequiresDao() throws Exception { + DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator(); + try { + populator.afterPropertiesSet(); + fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException failed) { + // ignored + } + } + + public void testGetGrantedAuthoritiesForValidUser() throws Exception { + DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator(); + populator.setUserDetailsService(new MockAuthenticationDao()); + populator.afterPropertiesSet(); + UserDetails results = populator.getUserDetails(PortletTestUtils.createToken()); + assertEquals(2, results.getAuthorities().length); + assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), results.getAuthorities()[0]); + assertEquals(new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2), results.getAuthorities()[1]); + } + + public void testGetGrantedAuthoritiesForInvalidUser() throws Exception { + DaoPortletAuthoritiesPopulator populator = new DaoPortletAuthoritiesPopulator(); + populator.setUserDetailsService(new MockAuthenticationDao()); + populator.afterPropertiesSet(); + try { + populator.getUserDetails(new PortletAuthenticationToken("dummy", "dummy", null)); + fail("Should have thrown UsernameNotFoundException"); + } catch (UsernameNotFoundException e) { + // ignore + } + } + + //~ Inner Classes ================================================================================================== + + private class MockAuthenticationDao implements UserDetailsService { + + public UserDetails loadUserByUsername(String username) + throws UsernameNotFoundException, DataAccessException { + if (PortletTestUtils.TESTUSER.equals(username)) + return PortletTestUtils.createUser(); + throw new UsernameNotFoundException("Could not find: " + username); + } + + } + +} diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingFilterEntryPointTests.java b/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingFilterEntryPointTests.java new file mode 100644 index 0000000000..58176b395e --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingFilterEntryPointTests.java @@ -0,0 +1,60 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.ui.portlet; + +import javax.servlet.http.HttpServletResponse; + +import junit.framework.TestCase; + +import org.acegisecurity.BadCredentialsException; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +/** + * Tests {@link PortletProcessingFilterEntryPoint}. + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class PortletProcessingFilterEntryPointTests extends TestCase { + + //~ Constructors =================================================================================================== + + public PortletProcessingFilterEntryPointTests() { + super(); + } + + public PortletProcessingFilterEntryPointTests(String arg0) { + super(arg0); + } + + //~ Methods ======================================================================================================== + + public final void setUp() throws Exception { + super.setUp(); + } + + public void testNormalOperation() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + PortletProcessingFilterEntryPoint entryPoint = new PortletProcessingFilterEntryPoint(); + entryPoint.commence(request, response, new BadCredentialsException(null)); + assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatus()); + } + +} diff --git a/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptorTests.java b/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptorTests.java new file mode 100644 index 0000000000..a619258c8d --- /dev/null +++ b/sandbox/portlet/src/test/java/org/acegisecurity/ui/portlet/PortletProcessingInterceptorTests.java @@ -0,0 +1,284 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed 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 + * + * 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.acegisecurity.ui.portlet; + +import java.util.ArrayList; +import java.util.HashMap; + +import javax.portlet.PortletRequest; +import javax.portlet.PortletSession; + +import junit.framework.TestCase; + +import org.acegisecurity.Authentication; +import org.acegisecurity.AuthenticationManager; +import org.acegisecurity.BadCredentialsException; +import org.acegisecurity.GrantedAuthority; +import org.acegisecurity.GrantedAuthorityImpl; +import org.acegisecurity.context.SecurityContextHolder; +import org.acegisecurity.providers.TestingAuthenticationToken; +import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import org.acegisecurity.providers.portlet.PortletAuthenticationToken; +import org.acegisecurity.providers.portlet.PortletTestUtils; +import org.acegisecurity.ui.AbstractProcessingFilter; +import org.acegisecurity.userdetails.User; +import org.springframework.mock.web.portlet.MockActionRequest; +import org.springframework.mock.web.portlet.MockActionResponse; +import org.springframework.mock.web.portlet.MockRenderRequest; +import org.springframework.mock.web.portlet.MockRenderResponse; + +/** + * Tests {@link PortletProcessingInterceptor}. + * + * @author John A. Lewis + * @since 2.0 + * @version $Id$ + */ +public class PortletProcessingInterceptorTests extends TestCase { + + //~ Constructors =================================================================================================== + + public PortletProcessingInterceptorTests() { + super(); + } + + public PortletProcessingInterceptorTests(String arg0) { + super(arg0); + } + + //~ Methods ======================================================================================================== + + public void setUp() throws Exception { + super.setUp(); + SecurityContextHolder.clearContext(); + } + + public void tearDown() throws Exception { + super.tearDown(); + SecurityContextHolder.clearContext(); + } + + public void testRequiresAuthenticationManager() throws Exception { + PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); + try { + interceptor.afterPropertiesSet(); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // ignored + } + } + + public void testNormalRenderRequestProcessing() throws Exception { + + // Build mock request and response + MockRenderRequest request = PortletTestUtils.createRenderRequest(); + MockRenderResponse response = PortletTestUtils.createRenderResponse(); + + // Prepare interceptor + PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); + interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); + interceptor.afterPropertiesSet(); + + // Execute preHandlerRender phase and verify results + interceptor.preHandleRender(request, response, null); + assertEquals(PortletTestUtils.createAuthenticatedToken(), + SecurityContextHolder.getContext().getAuthentication()); + + // Execute postHandlerRender phase and verify nothing changed + interceptor.postHandleRender(request, response, null, null); + assertEquals(PortletTestUtils.createAuthenticatedToken(), + SecurityContextHolder.getContext().getAuthentication()); + + // Execute afterRenderCompletion phase and verify nothing changed + interceptor.afterRenderCompletion(request, response, null, null); + assertEquals(PortletTestUtils.createAuthenticatedToken(), + SecurityContextHolder.getContext().getAuthentication()); + } + + public void testNormalActionRequestProcessing() throws Exception { + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + + // Prepare interceptor + PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); + interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); + interceptor.afterPropertiesSet(); + + // Execute preHandlerAction phase and verify results + interceptor.preHandleAction(request, response, null); + assertEquals(PortletTestUtils.createAuthenticatedToken(), + SecurityContextHolder.getContext().getAuthentication()); + + // Execute afterActionCompletion phase and verify nothing changed + interceptor.afterActionCompletion(request, response, null, null); + assertEquals(PortletTestUtils.createAuthenticatedToken(), + SecurityContextHolder.getContext().getAuthentication()); + } + + public void testAuthenticationFailsWithNoCredentials() + throws Exception { + + // Build mock request and response + MockActionRequest request = new MockActionRequest(); + MockActionResponse response = new MockActionResponse(); + + // Prepare and execute interceptor + PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); + interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); + interceptor.afterPropertiesSet(); + interceptor.preHandleAction(request, response, null); + + // Verify that authentication is empty + assertNull(SecurityContextHolder.getContext().getAuthentication()); + + // Verify that proper exception was thrown + assertTrue(request.getPortletSession().getAttribute( + AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY, + PortletSession.APPLICATION_SCOPE) + instanceof BadCredentialsException); + } + + public void testExistingAuthenticationIsLeftAlone() throws Exception { + + // Build mock request and response + MockActionRequest request = PortletTestUtils.createActionRequest(); + MockActionResponse response = PortletTestUtils.createActionResponse(); + + // Prepare interceptor + PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); + interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); + interceptor.afterPropertiesSet(); + + UsernamePasswordAuthenticationToken testingToken = new UsernamePasswordAuthenticationToken("dummy", "dummy", null); + UsernamePasswordAuthenticationToken baselineToken = new UsernamePasswordAuthenticationToken("dummy", "dummy", null); + SecurityContextHolder.getContext().setAuthentication(testingToken); + + // Execute preHandlerAction phase and verify results + interceptor.preHandleAction(request, response, null); + assertTrue(SecurityContextHolder.getContext().getAuthentication() == testingToken); + assertEquals(baselineToken, SecurityContextHolder.getContext().getAuthentication()); + + // Execute afterActionCompletion phase and verify nothing changed + interceptor.afterActionCompletion(request, response, null, null); + assertTrue(SecurityContextHolder.getContext().getAuthentication() == testingToken); + assertEquals(baselineToken, SecurityContextHolder.getContext().getAuthentication()); + } + + public void testUsernameFromRemoteUser() throws Exception { + + // Build mock request and response + MockActionRequest request = new MockActionRequest(); + MockActionResponse response = new MockActionResponse(); + request.setRemoteUser(PortletTestUtils.TESTUSER); + request.setAuthType(PortletRequest.FORM_AUTH); + + // Prepare and execute interceptor + PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); + interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); + interceptor.afterPropertiesSet(); + interceptor.preHandleAction(request, response, null); + + // Verify username + assertEquals(PortletTestUtils.TESTUSER, + SecurityContextHolder.getContext().getAuthentication().getName()); + } + + public void testUsernameFromPrincipal() throws Exception { + + // Build mock request and response + MockActionRequest request = new MockActionRequest(); + MockActionResponse response = new MockActionResponse(); + request.setUserPrincipal(new TestingAuthenticationToken(PortletTestUtils.TESTUSER, PortletTestUtils.TESTCRED, null)); + request.setAuthType(PortletRequest.FORM_AUTH); + + // Prepare and execute interceptor + PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); + interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); + interceptor.afterPropertiesSet(); + interceptor.preHandleAction(request, response, null); + + // Verify username + assertEquals(PortletTestUtils.TESTUSER, + SecurityContextHolder.getContext().getAuthentication().getName()); + } + + public void testUsernameFromUserInfo() throws Exception { + + // Build mock request and response + MockActionRequest request = new MockActionRequest(); + MockActionResponse response = new MockActionResponse(); + HashMap userInfo = new HashMap(); + userInfo.put("user.name.given", "Test"); + userInfo.put("user.name.family", "User"); + userInfo.put("user.id", "mytestuser"); + request.setAttribute(PortletRequest.USER_INFO, userInfo); + request.setAuthType(PortletRequest.FORM_AUTH); + + // Prepare and execute interceptor + PortletProcessingInterceptor interceptor = new PortletProcessingInterceptor(); + interceptor.setAuthenticationManager(new MockPortletAuthenticationManager()); + ArrayList userNameAttributes = new ArrayList(); + userNameAttributes.add("user.name"); + userNameAttributes.add("user.id"); + interceptor.setUserNameAttributes(userNameAttributes); + interceptor.afterPropertiesSet(); + interceptor.preHandleAction(request, response, null); + + // Verify username + assertEquals("mytestuser", SecurityContextHolder.getContext().getAuthentication().getName()); + } + + //~ Inner Classes ================================================================================================== + + private static class MockPortletAuthenticationManager implements AuthenticationManager { + + public Authentication authenticate(Authentication token) { + + // Make sure we got a valid token + if (!(token instanceof PortletAuthenticationToken)) { + TestCase.fail("Expected PortletAuthentication object-- got: " + token); + } + + // Make sure the token details are the PortletRequest + if (!(token.getDetails() instanceof PortletRequest)) { + TestCase.fail("Expected Authentication.getDetails to be a PortletRequest object -- got: " + token.getDetails()); + } + + // Make sure it's got a principal + if (token.getPrincipal() == null) { + throw new BadCredentialsException("Mock authentication manager rejecting null principal"); + } + + // Make sure it's got credentials + if (token.getCredentials() == null) { + throw new BadCredentialsException("Mock authentication manager rejecting null credentials"); + } + + // create resulting Authentication object + User user = new User(token.getName(), token.getCredentials().toString(), true, true, true, true, + new GrantedAuthority[] {new GrantedAuthorityImpl(PortletTestUtils.TESTROLE1), new GrantedAuthorityImpl(PortletTestUtils.TESTROLE2)}); + PortletAuthenticationToken result = new PortletAuthenticationToken( + user, user.getPassword(), user.getAuthorities()); + result.setAuthenticated(true); + return result; + } + + } + +}