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 @@
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;
/**
- * The
+ * The
* corresponding authentication provider is {@link PortletAuthenticationProvider}. Populates the portlet authorities via role information from the portlet container.
* Primarily it uses the This bean has the following configurable properties: This populator depends on finding the Authentication implementation for JSR-168 Portlet authentication. Authentication implementation for JSR 168 Portlet authentication. 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.
*
*
+ * rolesToCheck : A list of strings containing names of roles to check.
@@ -43,10 +44,16 @@ import org.acegisecurity.userdetails.UserDetails;
* of the portlet descriptor in the portlet.xml file.rolePrefix : The prefix to be added onto each role name that as it is
* added to the list of authorities. The default value is 'ROLE_'.userRole : The role that all authenticated users will automatically be
- * granted. The default value is 'ROLE_USER'.userRole : The authority that all authenticated users will automatically
+ * be granted. The default value is 'ROLE_USER'. Set this to null to avoid having any
+ * value automatically populated.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
* This method can be overridden by subclasses to provide special handling
- * for portals with weak support for the JSR-168 spec.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. 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; + } + + } + +}