mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-30 22:28:46 +00:00 
			
		
		
		
	Anonymous principal support. As requested by the community at various times, including in http://forum.springframework.org/viewtopic.php?t=1925.
This commit is contained in:
		
							parent
							
								
									3c4faf58c7
								
							
						
					
					
						commit
						693ac5a24a
					
				| @ -1,4 +1,4 @@ | |||||||
| /* Copyright 2004 Acegi Technology Pty Limited | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -32,10 +32,14 @@ public interface AccessDecisionManager { | |||||||
|      * @param config the configuration attributes associated with the secured |      * @param config the configuration attributes associated with the secured | ||||||
|      *        object being invoked |      *        object being invoked | ||||||
|      * |      * | ||||||
|      * @throws AccessDeniedException if access is denied |      * @throws AccessDeniedException if access is denied as the authentication | ||||||
|  |      *         does not hold a required authority or ACL privilege | ||||||
|  |      * @throws InsufficientAuthenticationException if access is denied as the | ||||||
|  |      *         authentication does not provide a sufficient level of trust | ||||||
|      */ |      */ | ||||||
|     public void decide(Authentication authentication, Object object, |     public void decide(Authentication authentication, Object object, | ||||||
|         ConfigAttributeDefinition config) throws AccessDeniedException; |         ConfigAttributeDefinition config) | ||||||
|  |         throws AccessDeniedException, InsufficientAuthenticationException; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Indicates whether this <code>AccessDecisionManager</code> is able to |      * Indicates whether this <code>AccessDecisionManager</code> is able to | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright 2004 Acegi Technology Pty Limited | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -16,9 +16,8 @@ | |||||||
| package net.sf.acegisecurity; | package net.sf.acegisecurity; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Abstract superclass for all exceptions related to the {@link |  * Abstract superclass for all exceptions related an {@link Authentication} | ||||||
|  * AuthenticationManager} being unable to authenticate an {@link |  * object being invalid for whatever reason. | ||||||
|  * Authentication} object. |  | ||||||
|  * |  * | ||||||
|  * @author Ben Alex |  * @author Ben Alex | ||||||
|  * @version $Id$ |  * @version $Id$ | ||||||
| @ -57,11 +56,11 @@ public abstract class AuthenticationException extends AcegiSecurityException { | |||||||
| 
 | 
 | ||||||
|     //~ Methods ================================================================ |     //~ Methods ================================================================ | ||||||
| 
 | 
 | ||||||
|     void setAuthentication(Authentication authentication) { |  | ||||||
|         this.authentication = authentication; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     public Authentication getAuthentication() { |     public Authentication getAuthentication() { | ||||||
|         return authentication; |         return authentication; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     void setAuthentication(Authentication authentication) { | ||||||
|  |         this.authentication = authentication; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,66 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Evaluates <code>Authentication</code> tokens | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public interface AuthenticationTrustResolver { | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates whether the passed <code>Authentication</code> token | ||||||
|  |      * represents an anonymous user. Typically the framework will call this | ||||||
|  |      * method if it is trying to decide whether an | ||||||
|  |      * <code>AccessDeniedException</code> should result in a final rejection | ||||||
|  |      * (ie as would be the case if the principal was non-anonymous/fully | ||||||
|  |      * authenticated) or direct the principal to attempt actual authentication | ||||||
|  |      * (ie as would be the case if the <code>Authentication</code> was merely | ||||||
|  |      * anonymous). | ||||||
|  |      * | ||||||
|  |      * @param authentication to test (may be <code>null</code> in which case | ||||||
|  |      *        the method will always return <code>false</code>) | ||||||
|  |      * | ||||||
|  |      * @return <code>true</code> the passed authentication token represented an | ||||||
|  |      *         anonymous principal, <code>false</code> otherwise | ||||||
|  |      */ | ||||||
|  |     public boolean isAnonymous(Authentication authentication); | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Indicates whether the passed <code>Authentication</code> token | ||||||
|  |      * represents user that has been remembered (ie not a user that has been | ||||||
|  |      * fully authenticated). | ||||||
|  |      *  | ||||||
|  |      * <p> | ||||||
|  |      * <b>No part of the framework uses this method</b>, as it is a weak | ||||||
|  |      * definition of trust levels. The method is provided simply to assist | ||||||
|  |      * with custom <code>AccessDecisionVoter</code>s and the like that you | ||||||
|  |      * might develop. Of course, you don't need to use this method either and | ||||||
|  |      * can develop your own "trust level" hierarchy instead. | ||||||
|  |      * </p> | ||||||
|  |      * | ||||||
|  |      * @param authentication to test (may be <code>null</code> in which case | ||||||
|  |      *        the method will always return <code>false</code>) | ||||||
|  |      * | ||||||
|  |      * @return <code>true</code> the passed authentication token represented a | ||||||
|  |      *         principal authenticated using a remember-me token, | ||||||
|  |      *         <code>false</code> otherwise | ||||||
|  |      */ | ||||||
|  |     public boolean isRememberMe(Authentication authentication); | ||||||
|  | } | ||||||
| @ -0,0 +1,77 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity; | ||||||
|  | 
 | ||||||
|  | import net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Basic implementation of {@link AuthenticationTrustResolverImpl}. | ||||||
|  |  *  | ||||||
|  |  * <P> | ||||||
|  |  * Makes trust decisions based on whether the passed | ||||||
|  |  * <code>Authentication</code> is an instance of a defined class. | ||||||
|  |  * </p> | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * If {@link #anonymousClass} or {@link #rememberMeClass} is <code>null</code>, | ||||||
|  |  * the corresponding method will always return <code>false</code>. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class AuthenticationTrustResolverImpl | ||||||
|  |     implements AuthenticationTrustResolver { | ||||||
|  |     //~ Instance fields ======================================================== | ||||||
|  | 
 | ||||||
|  |     private Class anonymousClass = AnonymousAuthenticationToken.class; | ||||||
|  |     private Class rememberMeClass; | ||||||
|  | 
 | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     public boolean isAnonymous(Authentication authentication) { | ||||||
|  |         if ((anonymousClass == null) || (authentication == null)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return anonymousClass.isAssignableFrom(authentication.getClass()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setAnonymousClass(Class anonymousClass) { | ||||||
|  |         this.anonymousClass = anonymousClass; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Class getAnonymousClass() { | ||||||
|  |         return anonymousClass; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean isRememberMe(Authentication authentication) { | ||||||
|  |         if ((rememberMeClass == null) || (authentication == null)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return rememberMeClass.isAssignableFrom(authentication.getClass()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setRememberMeClass(Class rememberMeClass) { | ||||||
|  |         this.rememberMeClass = rememberMeClass; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Class getRememberMeClass() { | ||||||
|  |         return rememberMeClass; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,58 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Thrown if an authentication request is rejected because the credentials are | ||||||
|  |  * not sufficiently trusted. | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * {{@link net.sf.acegisecurity.vote.AccessDecisionVoter}s will typically throw | ||||||
|  |  * this exception if they are dissatisfied with the level of the | ||||||
|  |  * authentication, such as if performed using a remember-me mechnanism or | ||||||
|  |  * anonymously. The commonly used {@link | ||||||
|  |  * net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter} will thus | ||||||
|  |  * cause the <code>AuthenticationEntryPoint</code> to be called, allowing the | ||||||
|  |  * principal to authenticate with a stronger level of authentication. } | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class InsufficientAuthenticationException extends AuthenticationException { | ||||||
|  |     //~ Constructors =========================================================== | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs an <code>InsufficientAuthenticationException</code> with the | ||||||
|  |      * specified message. | ||||||
|  |      * | ||||||
|  |      * @param msg the detail message | ||||||
|  |      */ | ||||||
|  |     public InsufficientAuthenticationException(String msg) { | ||||||
|  |         super(msg); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructs an <code>InsufficientAuthenticationException</code> with the | ||||||
|  |      * specified message and root cause. | ||||||
|  |      * | ||||||
|  |      * @param msg the detail message | ||||||
|  |      * @param t root cause | ||||||
|  |      */ | ||||||
|  |     public InsufficientAuthenticationException(String msg, Throwable t) { | ||||||
|  |         super(msg, t); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright 2004 Acegi Technology Pty Limited | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -17,6 +17,9 @@ package net.sf.acegisecurity.intercept.web; | |||||||
| 
 | 
 | ||||||
| import net.sf.acegisecurity.AccessDeniedException; | import net.sf.acegisecurity.AccessDeniedException; | ||||||
| import net.sf.acegisecurity.AuthenticationException; | import net.sf.acegisecurity.AuthenticationException; | ||||||
|  | import net.sf.acegisecurity.AuthenticationTrustResolver; | ||||||
|  | import net.sf.acegisecurity.AuthenticationTrustResolverImpl; | ||||||
|  | import net.sf.acegisecurity.context.security.SecureContextUtils; | ||||||
| import net.sf.acegisecurity.ui.AbstractProcessingFilter; | import net.sf.acegisecurity.ui.AbstractProcessingFilter; | ||||||
| import net.sf.acegisecurity.util.PortResolver; | import net.sf.acegisecurity.util.PortResolver; | ||||||
| import net.sf.acegisecurity.util.PortResolverImpl; | import net.sf.acegisecurity.util.PortResolverImpl; | ||||||
| @ -26,6 +29,8 @@ import org.apache.commons.logging.LogFactory; | |||||||
| 
 | 
 | ||||||
| import org.springframework.beans.factory.InitializingBean; | import org.springframework.beans.factory.InitializingBean; | ||||||
| 
 | 
 | ||||||
|  | import org.springframework.util.Assert; | ||||||
|  | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| 
 | 
 | ||||||
| import javax.servlet.Filter; | import javax.servlet.Filter; | ||||||
| @ -54,10 +59,13 @@ import javax.servlet.http.HttpServletResponse; | |||||||
|  * </p> |  * </p> | ||||||
|  *  |  *  | ||||||
|  * <p> |  * <p> | ||||||
|  * If an {@link AccessDeniedException} is detected, the filter will respond |  * If an {@link AccessDeniedException} is detected, the filter will determine | ||||||
|  * with a <code>HttpServletResponse.SC_FORBIDDEN</code> (403 error).  In |  * whether or not the user is an anonymous user. If they are an anonymous | ||||||
|  * addition, the <code>AccessDeniedException</code> itself will be placed in |  * user, the <code>authenticationEntryPoint</code> will be launched. If they | ||||||
|  * the <code>HttpSession</code> attribute keyed against {@link |  * are not an anonymous user, the filter will respond with a | ||||||
|  |  * <code>HttpServletResponse.SC_FORBIDDEN</code> (403 error).  In addition, | ||||||
|  |  * the <code>AccessDeniedException</code> itself will be placed in the | ||||||
|  |  * <code>HttpSession</code> attribute keyed against {@link | ||||||
|  * #ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY} (to allow access to the stack |  * #ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY} (to allow access to the stack | ||||||
|  * trace etc). Again, this allows common access denied handling irrespective |  * trace etc). Again, this allows common access denied handling irrespective | ||||||
|  * of the originating security interceptor. |  * of the originating security interceptor. | ||||||
| @ -104,6 +112,7 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { | |||||||
|     //~ Instance fields ======================================================== |     //~ Instance fields ======================================================== | ||||||
| 
 | 
 | ||||||
|     private AuthenticationEntryPoint authenticationEntryPoint; |     private AuthenticationEntryPoint authenticationEntryPoint; | ||||||
|  |     private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); | ||||||
|     private FilterSecurityInterceptor filterSecurityInterceptor; |     private FilterSecurityInterceptor filterSecurityInterceptor; | ||||||
|     private PortResolver portResolver = new PortResolverImpl(); |     private PortResolver portResolver = new PortResolverImpl(); | ||||||
| 
 | 
 | ||||||
| @ -118,6 +127,15 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { | |||||||
|         return authenticationEntryPoint; |         return authenticationEntryPoint; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public void setAuthenticationTrustResolver( | ||||||
|  |         AuthenticationTrustResolver authenticationTrustResolver) { | ||||||
|  |         this.authenticationTrustResolver = authenticationTrustResolver; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public AuthenticationTrustResolver getAuthenticationTrustResolver() { | ||||||
|  |         return authenticationTrustResolver; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public void setFilterSecurityInterceptor( |     public void setFilterSecurityInterceptor( | ||||||
|         FilterSecurityInterceptor filterSecurityInterceptor) { |         FilterSecurityInterceptor filterSecurityInterceptor) { | ||||||
|         this.filterSecurityInterceptor = filterSecurityInterceptor; |         this.filterSecurityInterceptor = filterSecurityInterceptor; | ||||||
| @ -136,19 +154,13 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void afterPropertiesSet() throws Exception { |     public void afterPropertiesSet() throws Exception { | ||||||
|         if (authenticationEntryPoint == null) { |         Assert.notNull(authenticationEntryPoint, | ||||||
|             throw new IllegalArgumentException( |             "authenticationEntryPoint must be specified"); | ||||||
|                 "authenticationEntryPoint must be specified"); |         Assert.notNull(filterSecurityInterceptor, | ||||||
|         } |             "filterSecurityInterceptor must be specified"); | ||||||
| 
 |         Assert.notNull(portResolver, "portResolver must be specified"); | ||||||
|         if (filterSecurityInterceptor == null) { |         Assert.notNull(authenticationTrustResolver, | ||||||
|             throw new IllegalArgumentException( |             "authenticationTrustResolver must be specified"); | ||||||
|                 "filterSecurityInterceptor must be specified"); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (portResolver == null) { |  | ||||||
|             throw new IllegalArgumentException("portResolver must be specified"); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void destroy() {} |     public void destroy() {} | ||||||
| @ -172,43 +184,29 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { | |||||||
|                 logger.debug("Chain processed normally"); |                 logger.debug("Chain processed normally"); | ||||||
|             } |             } | ||||||
|         } catch (AuthenticationException authentication) { |         } catch (AuthenticationException authentication) { | ||||||
|             HttpServletRequest httpRequest = (HttpServletRequest) request; |  | ||||||
| 
 |  | ||||||
|             int port = portResolver.getServerPort(request); |  | ||||||
|             boolean includePort = true; |  | ||||||
| 
 |  | ||||||
|             if ("http".equals(request.getScheme().toLowerCase()) |  | ||||||
|                 && (port == 80)) { |  | ||||||
|                 includePort = false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if ("https".equals(request.getScheme().toLowerCase()) |  | ||||||
|                 && (port == 443)) { |  | ||||||
|                 includePort = false; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             String targetUrl = request.getScheme() + "://" |  | ||||||
|                 + request.getServerName() + ((includePort) ? (":" + port) : "") |  | ||||||
|                 + httpRequest.getContextPath() + fi.getRequestUrl(); |  | ||||||
| 
 |  | ||||||
|             if (logger.isDebugEnabled()) { |             if (logger.isDebugEnabled()) { | ||||||
|                 logger.debug( |                 logger.debug("Authentication exception occurred; redirecting to authentication entry point", | ||||||
|                     "Authentication failed - adding target URL to Session: " |                     authentication); | ||||||
|                     + targetUrl, authentication); |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             ((HttpServletRequest) request).getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY, |             sendStartAuthentication(fi, authentication); | ||||||
|                 targetUrl); |  | ||||||
|             authenticationEntryPoint.commence(request, response, authentication); |  | ||||||
|         } catch (AccessDeniedException accessDenied) { |         } catch (AccessDeniedException accessDenied) { | ||||||
|             if (logger.isDebugEnabled()) { |             if (authenticationTrustResolver.isAnonymous( | ||||||
|                 logger.debug( |                     SecureContextUtils.getSecureContext().getAuthentication())) { | ||||||
|                     "Access is denied - sending back forbidden response"); |                 if (logger.isDebugEnabled()) { | ||||||
|             } |                     logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point", | ||||||
|  |                         accessDenied); | ||||||
|  |                 } | ||||||
| 
 | 
 | ||||||
|             ((HttpServletRequest) request).getSession().setAttribute(ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY, |                 sendStartAuthentication(fi, null); | ||||||
|                 accessDenied); |             } else { | ||||||
|             sendAccessDeniedError(request, response, accessDenied); |                 if (logger.isDebugEnabled()) { | ||||||
|  |                     logger.debug("Access is denied (user is not anonymous); sending back forbidden response", | ||||||
|  |                         accessDenied); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 sendAccessDeniedError(fi, accessDenied); | ||||||
|  |             } | ||||||
|         } catch (Throwable otherException) { |         } catch (Throwable otherException) { | ||||||
|             throw new ServletException(otherException); |             throw new ServletException(otherException); | ||||||
|         } |         } | ||||||
| @ -216,19 +214,43 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { | |||||||
| 
 | 
 | ||||||
|     public void init(FilterConfig filterConfig) throws ServletException {} |     public void init(FilterConfig filterConfig) throws ServletException {} | ||||||
| 
 | 
 | ||||||
|     /** |     protected void sendAccessDeniedError(FilterInvocation fi, | ||||||
|      * Allows subclasses to override if required |         AccessDeniedException accessDenied) | ||||||
|      * |         throws ServletException, IOException { | ||||||
|      * @param request |         ((HttpServletRequest) fi.getRequest()).getSession().setAttribute(ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY, | ||||||
|      * @param response |             accessDenied); | ||||||
|      * @param accessDenied |         ((HttpServletResponse) fi.getResponse()).sendError(HttpServletResponse.SC_FORBIDDEN, | ||||||
|      * |  | ||||||
|      * @throws IOException |  | ||||||
|      */ |  | ||||||
|     protected void sendAccessDeniedError(ServletRequest request, |  | ||||||
|         ServletResponse response, AccessDeniedException accessDenied) |  | ||||||
|         throws IOException { |  | ||||||
|         ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, |  | ||||||
|             accessDenied.getMessage()); // 403 |             accessDenied.getMessage()); // 403 | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     protected void sendStartAuthentication(FilterInvocation fi, | ||||||
|  |         AuthenticationException reason) throws ServletException, IOException { | ||||||
|  |         HttpServletRequest request = (HttpServletRequest) fi.getRequest(); | ||||||
|  | 
 | ||||||
|  |         int port = portResolver.getServerPort(request); | ||||||
|  |         boolean includePort = true; | ||||||
|  | 
 | ||||||
|  |         if ("http".equals(request.getScheme().toLowerCase()) && (port == 80)) { | ||||||
|  |             includePort = false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if ("https".equals(request.getScheme().toLowerCase()) && (port == 443)) { | ||||||
|  |             includePort = false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         String targetUrl = request.getScheme() + "://" | ||||||
|  |             + request.getServerName() + ((includePort) ? (":" + port) : "") | ||||||
|  |             + request.getContextPath() + fi.getRequestUrl(); | ||||||
|  | 
 | ||||||
|  |         if (logger.isDebugEnabled()) { | ||||||
|  |             logger.debug( | ||||||
|  |                 "Authentication entry point being called; target URL added to Session: " | ||||||
|  |                 + targetUrl); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         ((HttpServletRequest) request).getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY, | ||||||
|  |             targetUrl); | ||||||
|  |         authenticationEntryPoint.commence(request, | ||||||
|  |             (HttpServletResponse) fi.getResponse(), reason); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,86 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity.providers.anonymous; | ||||||
|  | 
 | ||||||
|  | import net.sf.acegisecurity.Authentication; | ||||||
|  | import net.sf.acegisecurity.AuthenticationException; | ||||||
|  | import net.sf.acegisecurity.BadCredentialsException; | ||||||
|  | import net.sf.acegisecurity.providers.AuthenticationProvider; | ||||||
|  | 
 | ||||||
|  | import org.apache.commons.logging.Log; | ||||||
|  | import org.apache.commons.logging.LogFactory; | ||||||
|  | 
 | ||||||
|  | import org.springframework.beans.factory.InitializingBean; | ||||||
|  | 
 | ||||||
|  | import org.springframework.util.Assert; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An {@link AuthenticationProvider} implementation that validates {@link | ||||||
|  |  * net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationToken}s. | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * To be successfully validated, the  {@link | ||||||
|  |  * net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationToken#getKeyHash()} | ||||||
|  |  * must match this class' {@link #getKey()}. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class AnonymousAuthenticationProvider implements AuthenticationProvider, | ||||||
|  |     InitializingBean { | ||||||
|  |     //~ Static fields/initializers ============================================= | ||||||
|  | 
 | ||||||
|  |     private static final Log logger = LogFactory.getLog(AnonymousAuthenticationProvider.class); | ||||||
|  | 
 | ||||||
|  |     //~ Instance fields ======================================================== | ||||||
|  | 
 | ||||||
|  |     private String key; | ||||||
|  | 
 | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     public void setKey(String key) { | ||||||
|  |         this.key = key; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getKey() { | ||||||
|  |         return key; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void afterPropertiesSet() throws Exception { | ||||||
|  |         Assert.hasLength(key); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Authentication authenticate(Authentication authentication) | ||||||
|  |         throws AuthenticationException { | ||||||
|  |         if (!supports(authentication.getClass())) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (this.key.hashCode() != ((AnonymousAuthenticationToken) authentication) | ||||||
|  |             .getKeyHash()) { | ||||||
|  |             throw new BadCredentialsException( | ||||||
|  |                 "The presented AnonymousAuthenticationToken does not contain the expected key"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return authentication; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean supports(Class authentication) { | ||||||
|  |         return (AnonymousAuthenticationToken.class.isAssignableFrom(authentication)); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,133 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity.providers.anonymous; | ||||||
|  | 
 | ||||||
|  | import net.sf.acegisecurity.GrantedAuthority; | ||||||
|  | import net.sf.acegisecurity.providers.AbstractAuthenticationToken; | ||||||
|  | 
 | ||||||
|  | import java.io.Serializable; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Represents an anonymous <code>Authentication</code>. | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class AnonymousAuthenticationToken extends AbstractAuthenticationToken | ||||||
|  |     implements Serializable { | ||||||
|  |     //~ Instance fields ======================================================== | ||||||
|  | 
 | ||||||
|  |     private Object principal; | ||||||
|  |     private GrantedAuthority[] authorities; | ||||||
|  |     private int keyHash; | ||||||
|  | 
 | ||||||
|  |     //~ Constructors =========================================================== | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Constructor. | ||||||
|  |      * | ||||||
|  |      * @param key to identify if this object made by an authorised client | ||||||
|  |      * @param principal the principal (typically a <code>UserDetails</code>) | ||||||
|  |      * @param authorities the authorities granted to the principal | ||||||
|  |      * | ||||||
|  |      * @throws IllegalArgumentException if a <code>null</code> was passed | ||||||
|  |      */ | ||||||
|  |     public AnonymousAuthenticationToken(String key, Object principal, | ||||||
|  |         GrantedAuthority[] authorities) { | ||||||
|  |         if ((key == null) || ("".equals(key)) || (principal == null) | ||||||
|  |             || "".equals(principal) || (authorities == null) | ||||||
|  |             || (authorities.length == 0)) { | ||||||
|  |             throw new IllegalArgumentException( | ||||||
|  |                 "Cannot pass null or empty values to constructor"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (int i = 0; i < authorities.length; i++) { | ||||||
|  |             if (authorities[i] == null) { | ||||||
|  |                 throw new IllegalArgumentException("Granted authority element " | ||||||
|  |                     + i | ||||||
|  |                     + " is null - GrantedAuthority[] cannot contain any null elements"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.keyHash = key.hashCode(); | ||||||
|  |         this.principal = principal; | ||||||
|  |         this.authorities = authorities; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected AnonymousAuthenticationToken() { | ||||||
|  |         throw new IllegalArgumentException("Cannot use default constructor"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Ignored (always <code>true</code>). | ||||||
|  |      * | ||||||
|  |      * @param isAuthenticated ignored | ||||||
|  |      */ | ||||||
|  |     public void setAuthenticated(boolean isAuthenticated) { | ||||||
|  |         // ignored | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Always returns <code>true</code>. | ||||||
|  |      * | ||||||
|  |      * @return true | ||||||
|  |      */ | ||||||
|  |     public boolean isAuthenticated() { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public GrantedAuthority[] getAuthorities() { | ||||||
|  |         return this.authorities; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Always returns an empty <code>String</code> | ||||||
|  |      * | ||||||
|  |      * @return an empty String | ||||||
|  |      */ | ||||||
|  |     public Object getCredentials() { | ||||||
|  |         return ""; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public int getKeyHash() { | ||||||
|  |         return this.keyHash; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public Object getPrincipal() { | ||||||
|  |         return this.principal; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public boolean equals(Object obj) { | ||||||
|  |         if (!super.equals(obj)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (obj instanceof AnonymousAuthenticationToken) { | ||||||
|  |             AnonymousAuthenticationToken test = (AnonymousAuthenticationToken) obj; | ||||||
|  | 
 | ||||||
|  |             if (this.getKeyHash() != test.getKeyHash()) { | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,169 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity.providers.anonymous; | ||||||
|  | 
 | ||||||
|  | import net.sf.acegisecurity.Authentication; | ||||||
|  | import net.sf.acegisecurity.context.security.SecureContext; | ||||||
|  | import net.sf.acegisecurity.context.security.SecureContextUtils; | ||||||
|  | import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint; | ||||||
|  | import net.sf.acegisecurity.providers.dao.memory.UserAttribute; | ||||||
|  | import net.sf.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint; | ||||||
|  | 
 | ||||||
|  | import org.apache.commons.logging.Log; | ||||||
|  | import org.apache.commons.logging.LogFactory; | ||||||
|  | 
 | ||||||
|  | import org.springframework.beans.factory.InitializingBean; | ||||||
|  | 
 | ||||||
|  | import org.springframework.util.Assert; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | 
 | ||||||
|  | import javax.servlet.Filter; | ||||||
|  | import javax.servlet.FilterChain; | ||||||
|  | import javax.servlet.FilterConfig; | ||||||
|  | import javax.servlet.ServletException; | ||||||
|  | import javax.servlet.ServletRequest; | ||||||
|  | import javax.servlet.ServletResponse; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Detects if there is no <code>Authentication</code> object in the | ||||||
|  |  * <code>ContextHolder</code>,  and populates it with one if needed. | ||||||
|  |  *  | ||||||
|  |  * <P></p> | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * In summary, this filter is responsible for processing any request that has a | ||||||
|  |  * HTTP request header of <code>Authorization</code> with an authentication | ||||||
|  |  * scheme of <code>Basic</code> and a Base64-encoded | ||||||
|  |  * <code>username:password</code> token. For example, to authenticate user | ||||||
|  |  * "Aladdin" with password "open sesame" the following header would be | ||||||
|  |  * presented: | ||||||
|  |  * </p> | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * <code>Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==</code>. | ||||||
|  |  * </p> | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * This filter can be used to provide BASIC authentication services to both | ||||||
|  |  * remoting protocol clients (such as Hessian and SOAP) as well as standard | ||||||
|  |  * user agents (such as Internet Explorer and Netscape). | ||||||
|  |  * </p> | ||||||
|  |  *  | ||||||
|  |  * <P> | ||||||
|  |  * If authentication is successful, the resulting {@link Authentication} object | ||||||
|  |  * will be placed into the <code>ContextHolder</code>. | ||||||
|  |  * </p> | ||||||
|  |  *  | ||||||
|  |  * <p> | ||||||
|  |  * If authentication fails, an {@link AuthenticationEntryPoint} implementation | ||||||
|  |  * is called. Usually this should be {@link BasicProcessingFilterEntryPoint}, | ||||||
|  |  * which will prompt the user to authenticate again via BASIC authentication. | ||||||
|  |  * </p> | ||||||
|  |  *  | ||||||
|  |  * <P> | ||||||
|  |  * Basic authentication is an attractive protocol because it is simple and | ||||||
|  |  * widely deployed. However, it still transmits a password in clear text and | ||||||
|  |  * as such is undesirable in many situations. Digest authentication is also | ||||||
|  |  * provided by Acegi Security and should be used instead of Basic | ||||||
|  |  * authentication wherever possible. See {@link | ||||||
|  |  * net.sf.acegisecurity.ui.digestauth.DigestProcessingFilter}. | ||||||
|  |  * </p> | ||||||
|  |  *  | ||||||
|  |  * <P> | ||||||
|  |  * <B>Do not use this class directly.</B> Instead configure | ||||||
|  |  * <code>web.xml</code> to use the {@link | ||||||
|  |  * net.sf.acegisecurity.util.FilterToBeanProxy}. | ||||||
|  |  * </p> | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class AnonymousProcessingFilter implements Filter, InitializingBean { | ||||||
|  |     //~ Static fields/initializers ============================================= | ||||||
|  | 
 | ||||||
|  |     private static final Log logger = LogFactory.getLog(AnonymousProcessingFilter.class); | ||||||
|  | 
 | ||||||
|  |     //~ Instance fields ======================================================== | ||||||
|  | 
 | ||||||
|  |     private String key; | ||||||
|  |     private UserAttribute userAttribute; | ||||||
|  | 
 | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     public void setKey(String key) { | ||||||
|  |         this.key = key; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public String getKey() { | ||||||
|  |         return key; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void setUserAttribute(UserAttribute userAttributeDefinition) { | ||||||
|  |         this.userAttribute = userAttributeDefinition; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public UserAttribute getUserAttribute() { | ||||||
|  |         return userAttribute; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void afterPropertiesSet() throws Exception { | ||||||
|  |         Assert.notNull(userAttribute); | ||||||
|  |         Assert.hasLength(key); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Does nothing - we reply on IoC lifecycle services instead. | ||||||
|  |      */ | ||||||
|  |     public void destroy() {} | ||||||
|  | 
 | ||||||
|  |     public void doFilter(ServletRequest request, ServletResponse response, | ||||||
|  |         FilterChain chain) throws IOException, ServletException { | ||||||
|  |         SecureContext sc = SecureContextUtils.getSecureContext(); | ||||||
|  | 
 | ||||||
|  |         if (sc.getAuthentication() == null) { | ||||||
|  |             sc.setAuthentication(createAuthentication(request)); | ||||||
|  | 
 | ||||||
|  |             if (logger.isDebugEnabled()) { | ||||||
|  |                 logger.debug("Replaced ContextHolder with anonymous token: '" | ||||||
|  |                     + sc.getAuthentication() + "'"); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             if (logger.isDebugEnabled()) { | ||||||
|  |                 logger.debug( | ||||||
|  |                     "ContextHolder not replaced with anonymous token, as ContextHolder already contained: '" | ||||||
|  |                     + sc.getAuthentication() + "'"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         chain.doFilter(request, response); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Does nothing - we reply on IoC lifecycle services instead. | ||||||
|  |      * | ||||||
|  |      * @param arg0 DOCUMENT ME! | ||||||
|  |      * | ||||||
|  |      * @throws ServletException DOCUMENT ME! | ||||||
|  |      */ | ||||||
|  |     public void init(FilterConfig arg0) throws ServletException {} | ||||||
|  | 
 | ||||||
|  |     protected Authentication createAuthentication(ServletRequest request) { | ||||||
|  |         return new AnonymousAuthenticationToken(key, | ||||||
|  |             userAttribute.getPassword(), userAttribute.getAuthorities()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,7 @@ | |||||||
|  | <html> | ||||||
|  | <body> | ||||||
|  | Allows you to secure every invocation (especially useful for web request | ||||||
|  | URI security) by always having either an actual principal or an anonymous | ||||||
|  | principal authenticated. | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright 2004 Acegi Technology Pty Limited | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -29,7 +29,7 @@ import java.util.Vector; | |||||||
|  * @author Ben Alex |  * @author Ben Alex | ||||||
|  * @version $Id$ |  * @version $Id$ | ||||||
|  */ |  */ | ||||||
| public class UserAttributeDefinition { | public class UserAttribute { | ||||||
|     //~ Instance fields ======================================================== |     //~ Instance fields ======================================================== | ||||||
| 
 | 
 | ||||||
|     private List authorities = new Vector(); |     private List authorities = new Vector(); | ||||||
| @ -38,7 +38,7 @@ public class UserAttributeDefinition { | |||||||
| 
 | 
 | ||||||
|     //~ Constructors =========================================================== |     //~ Constructors =========================================================== | ||||||
| 
 | 
 | ||||||
|     public UserAttributeDefinition() { |     public UserAttribute() { | ||||||
|         super(); |         super(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright 2004 Acegi Technology Pty Limited | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -23,8 +23,8 @@ import java.beans.PropertyEditorSupport; | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Property editor that creates a {@link UserAttributeDefinition} from a  comma |  * Property editor that creates a {@link UserAttribute} from a  comma separated | ||||||
|  * separated list of values. |  * list of values. | ||||||
|  * |  * | ||||||
|  * @author Ben Alex |  * @author Ben Alex | ||||||
|  * @version $Id$ |  * @version $Id$ | ||||||
| @ -37,7 +37,7 @@ public class UserAttributeEditor extends PropertyEditorSupport { | |||||||
|             setValue(null); |             setValue(null); | ||||||
|         } else { |         } else { | ||||||
|             String[] tokens = StringUtils.commaDelimitedListToStringArray(s); |             String[] tokens = StringUtils.commaDelimitedListToStringArray(s); | ||||||
|             UserAttributeDefinition userAttrib = new UserAttributeDefinition(); |             UserAttribute userAttrib = new UserAttribute(); | ||||||
| 
 | 
 | ||||||
|             for (int i = 0; i < tokens.length; i++) { |             for (int i = 0; i < tokens.length; i++) { | ||||||
|                 String currentToken = tokens[i]; |                 String currentToken = tokens[i]; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright 2004 Acegi Technology Pty Limited | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -91,8 +91,7 @@ public class UserMapEditor extends PropertyEditorSupport { | |||||||
|                 // Convert value to a password, enabled setting, and list of granted authorities |                 // Convert value to a password, enabled setting, and list of granted authorities | ||||||
|                 configAttribEd.setAsText(value); |                 configAttribEd.setAsText(value); | ||||||
| 
 | 
 | ||||||
|                 UserAttributeDefinition attr = (UserAttributeDefinition) configAttribEd |                 UserAttribute attr = (UserAttribute) configAttribEd.getValue(); | ||||||
|                     .getValue(); |  | ||||||
| 
 | 
 | ||||||
|                 // Make a user object, assuming the properties were properly provided |                 // Make a user object, assuming the properties were properly provided | ||||||
|                 if (attr != null) { |                 if (attr != null) { | ||||||
|  | |||||||
| @ -0,0 +1,67 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity; | ||||||
|  | 
 | ||||||
|  | import junit.framework.TestCase; | ||||||
|  | 
 | ||||||
|  | import net.sf.acegisecurity.providers.TestingAuthenticationToken; | ||||||
|  | import net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Tests {@link net.sf.acegisecurity.AuthenticationTrustResolverImpl}. | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class AuthenticationTrustResolverImplTests extends TestCase { | ||||||
|  |     //~ Constructors =========================================================== | ||||||
|  | 
 | ||||||
|  |     public AuthenticationTrustResolverImplTests() { | ||||||
|  |         super(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public AuthenticationTrustResolverImplTests(String arg0) { | ||||||
|  |         super(arg0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         junit.textui.TestRunner.run(AuthenticationTrustResolverImplTests.class); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testCorrectOperationIsAnonymous() { | ||||||
|  |         AuthenticationTrustResolverImpl trustResolver = new AuthenticationTrustResolverImpl(); | ||||||
|  |         assertTrue(trustResolver.isAnonymous( | ||||||
|  |                 new AnonymousAuthenticationToken("ignored", "ignored", | ||||||
|  |                     new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}))); | ||||||
|  |         assertFalse(trustResolver.isAnonymous( | ||||||
|  |                 new TestingAuthenticationToken("ignored", "ignored", | ||||||
|  |                     new GrantedAuthority[] {new GrantedAuthorityImpl("ignored")}))); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testGettersSetters() { | ||||||
|  |         AuthenticationTrustResolverImpl trustResolver = new AuthenticationTrustResolverImpl(); | ||||||
|  | 
 | ||||||
|  |         assertEquals(AnonymousAuthenticationToken.class, | ||||||
|  |             trustResolver.getAnonymousClass()); | ||||||
|  |         trustResolver.setAnonymousClass(String.class); | ||||||
|  |         assertEquals(String.class, trustResolver.getAnonymousClass()); | ||||||
|  | 
 | ||||||
|  |         assertNull(trustResolver.getRememberMeClass()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright 2004 Acegi Technology Pty Limited | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -19,11 +19,17 @@ import junit.framework.TestCase; | |||||||
| 
 | 
 | ||||||
| import net.sf.acegisecurity.AccessDeniedException; | import net.sf.acegisecurity.AccessDeniedException; | ||||||
| import net.sf.acegisecurity.BadCredentialsException; | import net.sf.acegisecurity.BadCredentialsException; | ||||||
|  | import net.sf.acegisecurity.GrantedAuthority; | ||||||
|  | import net.sf.acegisecurity.GrantedAuthorityImpl; | ||||||
| import net.sf.acegisecurity.MockAuthenticationEntryPoint; | import net.sf.acegisecurity.MockAuthenticationEntryPoint; | ||||||
| import net.sf.acegisecurity.MockHttpServletRequest; | import net.sf.acegisecurity.MockHttpServletRequest; | ||||||
| import net.sf.acegisecurity.MockHttpServletResponse; | import net.sf.acegisecurity.MockHttpServletResponse; | ||||||
| import net.sf.acegisecurity.MockHttpSession; | import net.sf.acegisecurity.MockHttpSession; | ||||||
| import net.sf.acegisecurity.MockPortResolver; | import net.sf.acegisecurity.MockPortResolver; | ||||||
|  | import net.sf.acegisecurity.context.ContextHolder; | ||||||
|  | import net.sf.acegisecurity.context.security.SecureContext; | ||||||
|  | import net.sf.acegisecurity.context.security.SecureContextImpl; | ||||||
|  | import net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationToken; | ||||||
| import net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter; | import net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter; | ||||||
| 
 | 
 | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| @ -62,8 +68,47 @@ public class SecurityEnforcementFilterTests extends TestCase { | |||||||
|         junit.textui.TestRunner.run(SecurityEnforcementFilterTests.class); |         junit.textui.TestRunner.run(SecurityEnforcementFilterTests.class); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void testAccessDeniedWhenAccessDeniedException() |     public void testAccessDeniedWhenAnonymous() throws Exception { | ||||||
|         throws Exception { |         // Setup our HTTP request | ||||||
|  |         HttpSession session = new MockHttpSession(); | ||||||
|  |         MockHttpServletRequest request = new MockHttpServletRequest(null, | ||||||
|  |                 session); | ||||||
|  |         request.setServletPath("/secure/page.html"); | ||||||
|  |         request.setServerPort(80); | ||||||
|  |         request.setScheme("http"); | ||||||
|  |         request.setServerName("www.example.com"); | ||||||
|  |         request.setContextPath("/mycontext"); | ||||||
|  |         request.setRequestURL( | ||||||
|  |             "http://www.example.com/mycontext/secure/page.html"); | ||||||
|  | 
 | ||||||
|  |         // Setup our expectation that the filter chain will not be invoked, as access is denied | ||||||
|  |         MockFilterChain chain = new MockFilterChain(false); | ||||||
|  | 
 | ||||||
|  |         // Setup the FilterSecurityInterceptor thrown an access denied exception | ||||||
|  |         MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(true, | ||||||
|  |                 false); | ||||||
|  | 
 | ||||||
|  |         // Setup ContextHolder, as filter needs to check if user is anonymous | ||||||
|  |         SecureContext sc = new SecureContextImpl(); | ||||||
|  |         sc.setAuthentication(new AnonymousAuthenticationToken("ignored", | ||||||
|  |                 "ignored", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("IGNORED")})); | ||||||
|  |         ContextHolder.setContext(sc); | ||||||
|  | 
 | ||||||
|  |         // Test | ||||||
|  |         SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); | ||||||
|  |         filter.setFilterSecurityInterceptor(interceptor); | ||||||
|  |         filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint( | ||||||
|  |                 "/login.jsp")); | ||||||
|  | 
 | ||||||
|  |         MockHttpServletResponse response = new MockHttpServletResponse(); | ||||||
|  |         filter.doFilter(request, response, chain); | ||||||
|  |         assertEquals("/mycontext/login.jsp", response.getRedirect()); | ||||||
|  |         assertEquals("http://www.example.com/mycontext/secure/page.html", | ||||||
|  |             request.getSession().getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testAccessDeniedWhenNonAnonymous() throws Exception { | ||||||
|         // Setup our HTTP request |         // Setup our HTTP request | ||||||
|         HttpSession session = new MockHttpSession(); |         HttpSession session = new MockHttpSession(); | ||||||
|         MockHttpServletRequest request = new MockHttpServletRequest(null, |         MockHttpServletRequest request = new MockHttpServletRequest(null, | ||||||
| @ -77,6 +122,11 @@ public class SecurityEnforcementFilterTests extends TestCase { | |||||||
|         MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(true, |         MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(true, | ||||||
|                 false); |                 false); | ||||||
| 
 | 
 | ||||||
|  |         // Setup ContextHolder, as filter needs to check if user is anonymous | ||||||
|  |         SecureContext sc = new SecureContextImpl(); | ||||||
|  |         sc.setAuthentication(null); | ||||||
|  |         ContextHolder.setContext(sc); | ||||||
|  | 
 | ||||||
|         // Test |         // Test | ||||||
|         SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); |         SecurityEnforcementFilter filter = new SecurityEnforcementFilter(); | ||||||
|         filter.setFilterSecurityInterceptor(interceptor); |         filter.setFilterSecurityInterceptor(interceptor); | ||||||
| @ -281,6 +331,11 @@ public class SecurityEnforcementFilterTests extends TestCase { | |||||||
|         assertTrue(true); |         assertTrue(true); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     protected void tearDown() throws Exception { | ||||||
|  |         super.tearDown(); | ||||||
|  |         ContextHolder.setContext(null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     //~ Inner Classes ========================================================== |     //~ Inner Classes ========================================================== | ||||||
| 
 | 
 | ||||||
|     private class MockFilterChain implements FilterChain { |     private class MockFilterChain implements FilterChain { | ||||||
|  | |||||||
| @ -0,0 +1,122 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity.providers.anonymous; | ||||||
|  | 
 | ||||||
|  | import junit.framework.TestCase; | ||||||
|  | 
 | ||||||
|  | import net.sf.acegisecurity.Authentication; | ||||||
|  | import net.sf.acegisecurity.BadCredentialsException; | ||||||
|  | import net.sf.acegisecurity.GrantedAuthority; | ||||||
|  | import net.sf.acegisecurity.GrantedAuthorityImpl; | ||||||
|  | import net.sf.acegisecurity.providers.TestingAuthenticationToken; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Tests {@link AnonymousAuthenticationProvider}. | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class AnonymousAuthenticationProviderTests extends TestCase { | ||||||
|  |     //~ Constructors =========================================================== | ||||||
|  | 
 | ||||||
|  |     public AnonymousAuthenticationProviderTests() { | ||||||
|  |         super(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public AnonymousAuthenticationProviderTests(String arg0) { | ||||||
|  |         super(arg0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     public final void setUp() throws Exception { | ||||||
|  |         super.setUp(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         junit.textui.TestRunner.run(AnonymousAuthenticationProviderTests.class); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testDetectsAnInvalidKey() throws Exception { | ||||||
|  |         AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); | ||||||
|  |         aap.setKey("qwerty"); | ||||||
|  | 
 | ||||||
|  |         AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("WRONG_KEY", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             Authentication result = aap.authenticate(token); | ||||||
|  |             fail("Should have thrown BadCredentialsException"); | ||||||
|  |         } catch (BadCredentialsException expected) { | ||||||
|  |             assertEquals("The presented AnonymousAuthenticationToken does not contain the expected key", | ||||||
|  |                 expected.getMessage()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testDetectsMissingKey() throws Exception { | ||||||
|  |         AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             aap.afterPropertiesSet(); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testGettersSetters() throws Exception { | ||||||
|  |         AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); | ||||||
|  |         aap.setKey("qwerty"); | ||||||
|  |         aap.afterPropertiesSet(); | ||||||
|  |         assertEquals("qwerty", aap.getKey()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testIgnoresClassesItDoesNotSupport() throws Exception { | ||||||
|  |         AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); | ||||||
|  |         aap.setKey("qwerty"); | ||||||
|  | 
 | ||||||
|  |         TestingAuthenticationToken token = new TestingAuthenticationToken("user", | ||||||
|  |                 "password", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")}); | ||||||
|  |         assertFalse(aap.supports(TestingAuthenticationToken.class)); | ||||||
|  | 
 | ||||||
|  |         // Try it anyway | ||||||
|  |         assertNull(aap.authenticate(token)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testNormalOperation() throws Exception { | ||||||
|  |         AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); | ||||||
|  |         aap.setKey("qwerty"); | ||||||
|  | 
 | ||||||
|  |         AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("qwerty", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         Authentication result = aap.authenticate(token); | ||||||
|  | 
 | ||||||
|  |         assertEquals(result, token); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testSupports() { | ||||||
|  |         AnonymousAuthenticationProvider aap = new AnonymousAuthenticationProvider(); | ||||||
|  |         assertTrue(aap.supports(AnonymousAuthenticationToken.class)); | ||||||
|  |         assertFalse(aap.supports(TestingAuthenticationToken.class)); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,190 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity.providers.anonymous; | ||||||
|  | 
 | ||||||
|  | import junit.framework.TestCase; | ||||||
|  | 
 | ||||||
|  | import net.sf.acegisecurity.GrantedAuthority; | ||||||
|  | import net.sf.acegisecurity.GrantedAuthorityImpl; | ||||||
|  | import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; | ||||||
|  | 
 | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Vector; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Tests {@link AnonymousAuthenticationToken}. | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class AnonymousAuthenticationTokenTests extends TestCase { | ||||||
|  |     //~ Constructors =========================================================== | ||||||
|  | 
 | ||||||
|  |     public AnonymousAuthenticationTokenTests() { | ||||||
|  |         super(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public AnonymousAuthenticationTokenTests(String arg0) { | ||||||
|  |         super(arg0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     public final void setUp() throws Exception { | ||||||
|  |         super.setUp(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         junit.textui.TestRunner.run(AnonymousAuthenticationTokenTests.class); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testConstructorRejectsNulls() { | ||||||
|  |         try { | ||||||
|  |             new AnonymousAuthenticationToken(null, "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             new AnonymousAuthenticationToken("key", null, | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             new AnonymousAuthenticationToken("key", "Test", null); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             new AnonymousAuthenticationToken("key", "Test", | ||||||
|  |                 new GrantedAuthority[] {null}); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             new AnonymousAuthenticationToken("key", "Test", | ||||||
|  |                 new GrantedAuthority[] {}); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testEqualsWhenEqual() { | ||||||
|  |         List proxyList1 = new Vector(); | ||||||
|  |         proxyList1.add("https://localhost/newPortal/j_acegi_cas_security_check"); | ||||||
|  | 
 | ||||||
|  |         AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("key", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         assertEquals(token1, token2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testGetters() { | ||||||
|  |         AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         assertEquals("key".hashCode(), token.getKeyHash()); | ||||||
|  |         assertEquals("Test", token.getPrincipal()); | ||||||
|  |         assertEquals("", token.getCredentials()); | ||||||
|  |         assertEquals("ROLE_ONE", token.getAuthorities()[0].getAuthority()); | ||||||
|  |         assertEquals("ROLE_TWO", token.getAuthorities()[1].getAuthority()); | ||||||
|  |         assertTrue(token.isAuthenticated()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testNoArgConstructor() { | ||||||
|  |         try { | ||||||
|  |             new AnonymousAuthenticationToken(); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testNotEqualsDueToAbstractParentEqualsCheck() { | ||||||
|  |         AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("key", | ||||||
|  |                 "DIFFERENT_PRINCIPAL", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         assertFalse(token1.equals(token2)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testNotEqualsDueToDifferentAuthenticationClass() { | ||||||
|  |         AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         UsernamePasswordAuthenticationToken token2 = new UsernamePasswordAuthenticationToken("Test", | ||||||
|  |                 "Password", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  |         token2.setAuthenticated(true); | ||||||
|  | 
 | ||||||
|  |         assertFalse(token1.equals(token2)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testNotEqualsDueToKey() { | ||||||
|  |         AnonymousAuthenticationToken token1 = new AnonymousAuthenticationToken("key", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         AnonymousAuthenticationToken token2 = new AnonymousAuthenticationToken("DIFFERENT_KEY", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  | 
 | ||||||
|  |         assertFalse(token1.equals(token2)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testSetAuthenticatedIgnored() { | ||||||
|  |         AnonymousAuthenticationToken token = new AnonymousAuthenticationToken("key", | ||||||
|  |                 "Test", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl( | ||||||
|  |                         "ROLE_TWO")}); | ||||||
|  |         assertTrue(token.isAuthenticated()); | ||||||
|  |         token.setAuthenticated(false); // ignored | ||||||
|  |         assertTrue(token.isAuthenticated()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,200 @@ | |||||||
|  | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  |  * | ||||||
|  |  * 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 net.sf.acegisecurity.providers.anonymous; | ||||||
|  | 
 | ||||||
|  | import junit.framework.TestCase; | ||||||
|  | 
 | ||||||
|  | import net.sf.acegisecurity.Authentication; | ||||||
|  | import net.sf.acegisecurity.GrantedAuthority; | ||||||
|  | import net.sf.acegisecurity.GrantedAuthorityImpl; | ||||||
|  | import net.sf.acegisecurity.MockFilterConfig; | ||||||
|  | import net.sf.acegisecurity.MockHttpServletRequest; | ||||||
|  | import net.sf.acegisecurity.MockHttpServletResponse; | ||||||
|  | import net.sf.acegisecurity.context.ContextHolder; | ||||||
|  | import net.sf.acegisecurity.context.security.SecureContext; | ||||||
|  | import net.sf.acegisecurity.context.security.SecureContextImpl; | ||||||
|  | import net.sf.acegisecurity.context.security.SecureContextUtils; | ||||||
|  | import net.sf.acegisecurity.providers.TestingAuthenticationToken; | ||||||
|  | import net.sf.acegisecurity.providers.dao.memory.UserAttribute; | ||||||
|  | 
 | ||||||
|  | import java.io.IOException; | ||||||
|  | 
 | ||||||
|  | import javax.servlet.Filter; | ||||||
|  | import javax.servlet.FilterChain; | ||||||
|  | import javax.servlet.FilterConfig; | ||||||
|  | import javax.servlet.ServletException; | ||||||
|  | import javax.servlet.ServletRequest; | ||||||
|  | import javax.servlet.ServletResponse; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Tests {@link AnonymousProcessingFilter}. | ||||||
|  |  * | ||||||
|  |  * @author Ben Alex | ||||||
|  |  * @version $Id$ | ||||||
|  |  */ | ||||||
|  | public class AnonymousProcessingFilterTests extends TestCase { | ||||||
|  |     //~ Constructors =========================================================== | ||||||
|  | 
 | ||||||
|  |     public AnonymousProcessingFilterTests() { | ||||||
|  |         super(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public AnonymousProcessingFilterTests(String arg0) { | ||||||
|  |         super(arg0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //~ Methods ================================================================ | ||||||
|  | 
 | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         junit.textui.TestRunner.run(AnonymousProcessingFilterTests.class); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testDetectsMissingKey() throws Exception { | ||||||
|  |         UserAttribute user = new UserAttribute(); | ||||||
|  |         user.setPassword("anonymousUsername"); | ||||||
|  |         user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS")); | ||||||
|  | 
 | ||||||
|  |         AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); | ||||||
|  |         filter.setUserAttribute(user); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             filter.afterPropertiesSet(); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testDetectsUserAttribute() throws Exception { | ||||||
|  |         AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); | ||||||
|  |         filter.setKey("qwerty"); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             filter.afterPropertiesSet(); | ||||||
|  |             fail("Should have thrown IllegalArgumentException"); | ||||||
|  |         } catch (IllegalArgumentException expected) { | ||||||
|  |             assertTrue(true); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testGettersSetters() throws Exception { | ||||||
|  |         UserAttribute user = new UserAttribute(); | ||||||
|  |         user.setPassword("anonymousUsername"); | ||||||
|  |         user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS")); | ||||||
|  | 
 | ||||||
|  |         AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); | ||||||
|  |         filter.setKey("qwerty"); | ||||||
|  |         filter.setUserAttribute(user); | ||||||
|  |         filter.afterPropertiesSet(); | ||||||
|  | 
 | ||||||
|  |         assertEquals("qwerty", filter.getKey()); | ||||||
|  |         assertEquals(user, filter.getUserAttribute()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testOperationWhenAuthenticationExistsInContextHolder() | ||||||
|  |         throws Exception { | ||||||
|  |         // Put an Authentication object into the ContextHolder | ||||||
|  |         SecureContext sc = SecureContextUtils.getSecureContext(); | ||||||
|  |         Authentication originalAuth = new TestingAuthenticationToken("user", | ||||||
|  |                 "password", | ||||||
|  |                 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_A")}); | ||||||
|  |         sc.setAuthentication(originalAuth); | ||||||
|  |         ContextHolder.setContext(sc); | ||||||
|  | 
 | ||||||
|  |         // Setup our filter correctly | ||||||
|  |         UserAttribute user = new UserAttribute(); | ||||||
|  |         user.setPassword("anonymousUsername"); | ||||||
|  |         user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS")); | ||||||
|  | 
 | ||||||
|  |         AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); | ||||||
|  |         filter.setKey("qwerty"); | ||||||
|  |         filter.setUserAttribute(user); | ||||||
|  |         filter.afterPropertiesSet(); | ||||||
|  | 
 | ||||||
|  |         // Test | ||||||
|  |         executeFilterInContainerSimulator(new MockFilterConfig(), filter, | ||||||
|  |             new MockHttpServletRequest("x"), new MockHttpServletResponse(), | ||||||
|  |             new MockFilterChain(true)); | ||||||
|  | 
 | ||||||
|  |         // Ensure filter didn't change our original object | ||||||
|  |         assertEquals(originalAuth, | ||||||
|  |             SecureContextUtils.getSecureContext().getAuthentication()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public void testOperationWhenNoAuthenticationInContextHolder() | ||||||
|  |         throws Exception { | ||||||
|  |         UserAttribute user = new UserAttribute(); | ||||||
|  |         user.setPassword("anonymousUsername"); | ||||||
|  |         user.addAuthority(new GrantedAuthorityImpl("ROLE_ANONYMOUS")); | ||||||
|  | 
 | ||||||
|  |         AnonymousProcessingFilter filter = new AnonymousProcessingFilter(); | ||||||
|  |         filter.setKey("qwerty"); | ||||||
|  |         filter.setUserAttribute(user); | ||||||
|  |         filter.afterPropertiesSet(); | ||||||
|  | 
 | ||||||
|  |         executeFilterInContainerSimulator(new MockFilterConfig(), filter, | ||||||
|  |             new MockHttpServletRequest("x"), new MockHttpServletResponse(), | ||||||
|  |             new MockFilterChain(true)); | ||||||
|  | 
 | ||||||
|  |         Authentication auth = SecureContextUtils.getSecureContext() | ||||||
|  |                                                 .getAuthentication(); | ||||||
|  |         assertEquals("anonymousUsername", auth.getPrincipal()); | ||||||
|  |         assertEquals(new GrantedAuthorityImpl("ROLE_ANONYMOUS"), | ||||||
|  |             auth.getAuthorities()[0]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected void setUp() throws Exception { | ||||||
|  |         super.setUp(); | ||||||
|  |         ContextHolder.setContext(new SecureContextImpl()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     protected void tearDown() throws Exception { | ||||||
|  |         super.tearDown(); | ||||||
|  |         ContextHolder.setContext(null); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private void executeFilterInContainerSimulator(FilterConfig filterConfig, | ||||||
|  |         Filter filter, ServletRequest request, ServletResponse response, | ||||||
|  |         FilterChain filterChain) throws ServletException, IOException { | ||||||
|  |         filter.init(filterConfig); | ||||||
|  |         filter.doFilter(request, response, filterChain); | ||||||
|  |         filter.destroy(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     //~ Inner Classes ========================================================== | ||||||
|  | 
 | ||||||
|  |     private class MockFilterChain implements FilterChain { | ||||||
|  |         private boolean expectToProceed; | ||||||
|  | 
 | ||||||
|  |         public MockFilterChain(boolean expectToProceed) { | ||||||
|  |             this.expectToProceed = expectToProceed; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         private MockFilterChain() { | ||||||
|  |             super(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         public void doFilter(ServletRequest request, ServletResponse response) | ||||||
|  |             throws IOException, ServletException { | ||||||
|  |             if (expectToProceed) { | ||||||
|  |                 assertTrue(true); | ||||||
|  |             } else { | ||||||
|  |                 fail("Did not expect filter chain to proceed"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,4 +1,4 @@ | |||||||
| /* Copyright 2004 Acegi Technology Pty Limited | /* Copyright 2004, 2005 Acegi Technology Pty Limited | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -19,8 +19,7 @@ import junit.framework.TestCase; | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Tests {@link UserAttributeEditor} and associated {@link |  * Tests {@link UserAttributeEditor} and associated {@link UserAttribute}. | ||||||
|  * UserAttributeDefinition}. |  | ||||||
|  * |  * | ||||||
|  * @author Ben Alex |  * @author Ben Alex | ||||||
|  * @version $Id$ |  * @version $Id$ | ||||||
| @ -50,8 +49,7 @@ public class UserAttributeEditorTests extends TestCase { | |||||||
|         UserAttributeEditor editor = new UserAttributeEditor(); |         UserAttributeEditor editor = new UserAttributeEditor(); | ||||||
|         editor.setAsText("password,ROLE_ONE,ROLE_TWO"); |         editor.setAsText("password,ROLE_ONE,ROLE_TWO"); | ||||||
| 
 | 
 | ||||||
|         UserAttributeDefinition user = (UserAttributeDefinition) editor |         UserAttribute user = (UserAttribute) editor.getValue(); | ||||||
|             .getValue(); |  | ||||||
|         assertTrue(user.isValid()); |         assertTrue(user.isValid()); | ||||||
|         assertTrue(user.isEnabled()); // default |         assertTrue(user.isEnabled()); // default | ||||||
|         assertEquals("password", user.getPassword()); |         assertEquals("password", user.getPassword()); | ||||||
| @ -64,8 +62,7 @@ public class UserAttributeEditorTests extends TestCase { | |||||||
|         UserAttributeEditor editor = new UserAttributeEditor(); |         UserAttributeEditor editor = new UserAttributeEditor(); | ||||||
|         editor.setAsText("password,disabled,ROLE_ONE,ROLE_TWO"); |         editor.setAsText("password,disabled,ROLE_ONE,ROLE_TWO"); | ||||||
| 
 | 
 | ||||||
|         UserAttributeDefinition user = (UserAttributeDefinition) editor |         UserAttribute user = (UserAttribute) editor.getValue(); | ||||||
|             .getValue(); |  | ||||||
|         assertTrue(user.isValid()); |         assertTrue(user.isValid()); | ||||||
|         assertTrue(!user.isEnabled()); |         assertTrue(!user.isEnabled()); | ||||||
|         assertEquals("password", user.getPassword()); |         assertEquals("password", user.getPassword()); | ||||||
| @ -78,8 +75,7 @@ public class UserAttributeEditorTests extends TestCase { | |||||||
|         UserAttributeEditor editor = new UserAttributeEditor(); |         UserAttributeEditor editor = new UserAttributeEditor(); | ||||||
|         editor.setAsText(""); |         editor.setAsText(""); | ||||||
| 
 | 
 | ||||||
|         UserAttributeDefinition user = (UserAttributeDefinition) editor |         UserAttribute user = (UserAttribute) editor.getValue(); | ||||||
|             .getValue(); |  | ||||||
|         assertTrue(user == null); |         assertTrue(user == null); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -87,8 +83,7 @@ public class UserAttributeEditorTests extends TestCase { | |||||||
|         UserAttributeEditor editor = new UserAttributeEditor(); |         UserAttributeEditor editor = new UserAttributeEditor(); | ||||||
|         editor.setAsText("password,ROLE_ONE,enabled,ROLE_TWO"); |         editor.setAsText("password,ROLE_ONE,enabled,ROLE_TWO"); | ||||||
| 
 | 
 | ||||||
|         UserAttributeDefinition user = (UserAttributeDefinition) editor |         UserAttribute user = (UserAttribute) editor.getValue(); | ||||||
|             .getValue(); |  | ||||||
|         assertTrue(user.isValid()); |         assertTrue(user.isValid()); | ||||||
|         assertTrue(user.isEnabled()); |         assertTrue(user.isEnabled()); | ||||||
|         assertEquals("password", user.getPassword()); |         assertEquals("password", user.getPassword()); | ||||||
| @ -101,8 +96,7 @@ public class UserAttributeEditorTests extends TestCase { | |||||||
|         UserAttributeEditor editor = new UserAttributeEditor(); |         UserAttributeEditor editor = new UserAttributeEditor(); | ||||||
|         editor.setAsText("MALFORMED_STRING"); |         editor.setAsText("MALFORMED_STRING"); | ||||||
| 
 | 
 | ||||||
|         UserAttributeDefinition user = (UserAttributeDefinition) editor |         UserAttribute user = (UserAttribute) editor.getValue(); | ||||||
|             .getValue(); |  | ||||||
|         assertTrue(user == null); |         assertTrue(user == null); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -110,8 +104,7 @@ public class UserAttributeEditorTests extends TestCase { | |||||||
|         UserAttributeEditor editor = new UserAttributeEditor(); |         UserAttributeEditor editor = new UserAttributeEditor(); | ||||||
|         editor.setAsText("disabled"); |         editor.setAsText("disabled"); | ||||||
| 
 | 
 | ||||||
|         UserAttributeDefinition user = (UserAttributeDefinition) editor |         UserAttribute user = (UserAttribute) editor.getValue(); | ||||||
|             .getValue(); |  | ||||||
|         assertTrue(user == null); |         assertTrue(user == null); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -119,8 +112,7 @@ public class UserAttributeEditorTests extends TestCase { | |||||||
|         UserAttributeEditor editor = new UserAttributeEditor(); |         UserAttributeEditor editor = new UserAttributeEditor(); | ||||||
|         editor.setAsText("password,enabled"); |         editor.setAsText("password,enabled"); | ||||||
| 
 | 
 | ||||||
|         UserAttributeDefinition user = (UserAttributeDefinition) editor |         UserAttribute user = (UserAttribute) editor.getValue(); | ||||||
|             .getValue(); |  | ||||||
|         assertTrue(user == null); |         assertTrue(user == null); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -128,8 +120,7 @@ public class UserAttributeEditorTests extends TestCase { | |||||||
|         UserAttributeEditor editor = new UserAttributeEditor(); |         UserAttributeEditor editor = new UserAttributeEditor(); | ||||||
|         editor.setAsText(null); |         editor.setAsText(null); | ||||||
| 
 | 
 | ||||||
|         UserAttributeDefinition user = (UserAttributeDefinition) editor |         UserAttribute user = (UserAttribute) editor.getValue(); | ||||||
|             .getValue(); |  | ||||||
|         assertTrue(user == null); |         assertTrue(user == null); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2485,7 +2485,7 @@ public boolean supports(Class clazz);</programlisting></para> | |||||||
|         <para><programlisting>base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) |         <para><programlisting>base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key)) | ||||||
| 
 | 
 | ||||||
| expirationTime:   The date and time when the nonce expires, expressed in milliseconds | expirationTime:   The date and time when the nonce expires, expressed in milliseconds | ||||||
| key:              A private key to prevent modification of the nounce token | key:              A private key to prevent modification of the nonce token | ||||||
| </programlisting></para> | </programlisting></para> | ||||||
| 
 | 
 | ||||||
|         <para>The <literal>DigestProcessingFilterEntryPoint</literal> has a |         <para>The <literal>DigestProcessingFilterEntryPoint</literal> has a | ||||||
| @ -2548,7 +2548,7 @@ key:              A private key to prevent modification of the nounce token | |||||||
|         <para>The configured <literal>AuthenticationDao</literal> is needed |         <para>The configured <literal>AuthenticationDao</literal> is needed | ||||||
|         because <literal>DigestProcessingFilter</literal> must have direct |         because <literal>DigestProcessingFilter</literal> must have direct | ||||||
|         access to the clear text password of a user. Digest Authentication |         access to the clear text password of a user. Digest Authentication | ||||||
|         will NOT work if you are using encoded passwords ni your DAO. The DAO |         will NOT work if you are using encoded passwords in your DAO. The DAO | ||||||
|         collaborator, along with the <literal>UserCache</literal>, are |         collaborator, along with the <literal>UserCache</literal>, are | ||||||
|         typically shared directly with a |         typically shared directly with a | ||||||
|         <literal>DaoAuthenticationProvider</literal>. The |         <literal>DaoAuthenticationProvider</literal>. The | ||||||
| @ -2556,7 +2556,7 @@ key:              A private key to prevent modification of the nounce token | |||||||
|         <literal>DigestProcessingFilterEntryPoint</literal>, so that |         <literal>DigestProcessingFilterEntryPoint</literal>, so that | ||||||
|         <literal>DigestProcessingFilter</literal> can obtain the correct |         <literal>DigestProcessingFilter</literal> can obtain the correct | ||||||
|         <literal>realmName</literal> and <literal>key</literal> for digest |         <literal>realmName</literal> and <literal>key</literal> for digest | ||||||
|         calculations. </para> |         calculations.</para> | ||||||
| 
 | 
 | ||||||
|         <para>Like <literal>BasicAuthenticationFilter</literal>, if |         <para>Like <literal>BasicAuthenticationFilter</literal>, if | ||||||
|         authentication is successful an <literal>Authentication</literal> |         authentication is successful an <literal>Authentication</literal> | ||||||
| @ -2580,6 +2580,95 @@ key:              A private key to prevent modification of the nounce token | |||||||
|         does comply with the minimum standards of this RFC.</para> |         does comply with the minimum standards of this RFC.</para> | ||||||
|       </sect2> |       </sect2> | ||||||
| 
 | 
 | ||||||
|  |       <sect2 id="security-ui-anonymous"> | ||||||
|  |         <title>Anonymous Authentication</title> | ||||||
|  | 
 | ||||||
|  |         <para>Particularly in the case of web request URI security, sometimes | ||||||
|  |         it is more convenient to assign configuration attributes against every | ||||||
|  |         possible secure object invocation. Put differently, sometimes it is | ||||||
|  |         nice to say <literal>ROLE_SOMETHING</literal> is required by default | ||||||
|  |         and only allow certain exceptions to this rule, such as for login, | ||||||
|  |         logout and home pages of an application. There are also other | ||||||
|  |         situations where anonymous authentication would be desired, such as | ||||||
|  |         when an auditing interceptor queries the | ||||||
|  |         <literal>ContextHolder</literal> to identify which principal was | ||||||
|  |         responsible for a given operation. Such classes can be authored with | ||||||
|  |         more robustness if they know the <literal>ContextHolder</literal> | ||||||
|  |         always contains an <literal>Authentication</literal> object, and never | ||||||
|  |         <literal>null</literal>.</para> | ||||||
|  | 
 | ||||||
|  |         <para>Acegi Security provides three classes that together provide an | ||||||
|  |         anoymous authentication feature. | ||||||
|  |         <literal>AnonymousAuthenticationToken</literal> is an implementation | ||||||
|  |         of <literal>Authentication</literal>, and stores the | ||||||
|  |         <literal>GrantedAuthority</literal>[]s which apply to the anonymous | ||||||
|  |         principal. There is a corresponding | ||||||
|  |         <literal>AnonymousAuthenticationProvider</literal>, which is chained | ||||||
|  |         into the <literal>ProviderManager</literal> so that | ||||||
|  |         <literal>AnonymousAuthenticationTokens</literal> are accepted. | ||||||
|  |         Finally, there is an AnonymousProcessingFilter, which is chained after | ||||||
|  |         the normal authentication mechanisms and automatically add an | ||||||
|  |         <literal>AnonymousAuthenticationToken</literal> to the | ||||||
|  |         <literal>ContextHolder</literal> if there is no existing | ||||||
|  |         <literal>Authentication</literal> held there. The definition of the | ||||||
|  |         filter and authentication provider appears as follows:</para> | ||||||
|  | 
 | ||||||
|  |         <para><programlisting><bean id="anonymousProcessingFilter" class="net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter"> | ||||||
|  |   <property name="key"><value>foobar</value></property> | ||||||
|  |   <property name="userAttribute"><value>anonymousUser,ROLE_ANONYMOUS</value></property> | ||||||
|  | </bean> | ||||||
|  | 
 | ||||||
|  | <bean id="anonymousAuthenticationProvider" class="net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider"> | ||||||
|  |   <property name="key"><value>foobar</value></property> | ||||||
|  | </bean></programlisting></para> | ||||||
|  | 
 | ||||||
|  |         <para>The <literal>key</literal> is shared between the filter and | ||||||
|  |         authentication provider, so that tokens created by the former are | ||||||
|  |         accepted by the latter. The <literal>userAttribute</literal> is | ||||||
|  |         expressed in the form of | ||||||
|  |         <literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>. | ||||||
|  |         This is the same syntax as used after the equals sign for | ||||||
|  |         <literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal> | ||||||
|  |         property.</para> | ||||||
|  | 
 | ||||||
|  |         <para>As explained earlier, the benefit of anonymous authentication is | ||||||
|  |         that all URI patterns can have security applied to them. For | ||||||
|  |         example:</para> | ||||||
|  | 
 | ||||||
|  |         <para><programlisting><bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"> | ||||||
|  |   <property name="authenticationManager"><ref bean="authenticationManager"/></property> | ||||||
|  |   <property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/></property> | ||||||
|  |   <property name="objectDefinitionSource"> | ||||||
|  |     <value> | ||||||
|  |       CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON | ||||||
|  |       PATTERN_TYPE_APACHE_ANT | ||||||
|  |       /index.jsp=ROLE_ANONYMOUS,ROLE_USER | ||||||
|  |       /hello.htm=ROLE_ANONYMOUS,ROLE_USER | ||||||
|  |       /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER | ||||||
|  |       /acegilogin.jsp=ROLE_ANONYMOUS,ROLE_USER | ||||||
|  |       /**=ROLE_USER | ||||||
|  |     </value> | ||||||
|  |   </property> | ||||||
|  | </bean></programlisting>Rounding out the anonymous authentication | ||||||
|  |         discussion is the <literal>AuthenticationTrustResolver</literal> | ||||||
|  |         interface, with its corresponding | ||||||
|  |         <literal>AuthenticationTrustResolverImpl</literal> implementation. | ||||||
|  |         This interface provides an | ||||||
|  |         <literal>isAnonymous(Authentication)</literal> method, which allows | ||||||
|  |         interested classes to take into account this special type of | ||||||
|  |         authentication status. The | ||||||
|  |         <literal>SecurityEnforcementFilter</literal> uses this interface in | ||||||
|  |         processing <literal>AccessDeniedException</literal>s. If an | ||||||
|  |         <literal>AccessDeniedException</literal> is thrown, and the | ||||||
|  |         authentication is of an anonymous type, instead of throwing a 403 | ||||||
|  |         (forbidden) response, the filter will instead commence the | ||||||
|  |         <literal>AuthenticationEntryPoint</literal> so the principal can | ||||||
|  |         authenticate properly. This is a necessary distinction, otherwise | ||||||
|  |         principals would always be deemed "authenticated" and never be given | ||||||
|  |         an opportunity to login via form, basic, digest or some other normal | ||||||
|  |         authentication mechanism.</para> | ||||||
|  |       </sect2> | ||||||
|  | 
 | ||||||
|       <sect2 id="security-ui-well-known"> |       <sect2 id="security-ui-well-known"> | ||||||
|         <title>Well-Known Locations</title> |         <title>Well-Known Locations</title> | ||||||
| 
 | 
 | ||||||
| @ -4393,6 +4482,13 @@ INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para> | |||||||
|             container</para> |             container</para> | ||||||
|           </listitem> |           </listitem> | ||||||
| 
 | 
 | ||||||
|  |           <listitem> | ||||||
|  |             <para><literal>AnonymousProcessingFilter</literal>, so that if no | ||||||
|  |             earlier authentication processing mechanism updated the | ||||||
|  |             <literal>ContextHolder</literal>, an anonymous | ||||||
|  |             <literal>Authentication</literal> object will be put there</para> | ||||||
|  |           </listitem> | ||||||
|  | 
 | ||||||
|           <listitem> |           <listitem> | ||||||
|             <para><literal>SecurityEnforcementFilter</literal>, to protect web |             <para><literal>SecurityEnforcementFilter</literal>, to protect web | ||||||
|             URIs and catch any Acegi Security exceptions so that an |             URIs and catch any Acegi Security exceptions so that an | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ | |||||||
|          <value> |          <value> | ||||||
| 		    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON | 		    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON | ||||||
| 		    PATTERN_TYPE_APACHE_ANT | 		    PATTERN_TYPE_APACHE_ANT | ||||||
|             /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,basicProcessingFilter,securityEnforcementFilter |             /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,basicProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter | ||||||
|          </value> |          </value> | ||||||
|       </property> |       </property> | ||||||
|     </bean> |     </bean> | ||||||
| @ -32,6 +32,7 @@ | |||||||
|       <property name="providers"> |       <property name="providers"> | ||||||
|          <list> |          <list> | ||||||
|             <ref local="daoAuthenticationProvider"/> |             <ref local="daoAuthenticationProvider"/> | ||||||
|  |             <ref local="anonymousAuthenticationProvider"/> | ||||||
|          </list> |          </list> | ||||||
|       </property> |       </property> | ||||||
|    </bean> |    </bean> | ||||||
| @ -75,6 +76,15 @@ | |||||||
|       <property name="realmName"><value>Contacts Realm</value></property> |       <property name="realmName"><value>Contacts Realm</value></property> | ||||||
|    </bean> |    </bean> | ||||||
| 
 | 
 | ||||||
|  |    <bean id="anonymousProcessingFilter" class="net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter"> | ||||||
|  |       <property name="key"><value>foobar</value></property> | ||||||
|  |       <property name="userAttribute"><value>anonymousUser,ROLE_ANONYMOUS</value></property> | ||||||
|  |    </bean> | ||||||
|  | 
 | ||||||
|  |    <bean id="anonymousAuthenticationProvider" class="net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider"> | ||||||
|  |       <property name="key"><value>foobar</value></property> | ||||||
|  |    </bean> | ||||||
|  | 
 | ||||||
|    <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter"> |    <bean id="httpSessionContextIntegrationFilter" class="net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter"> | ||||||
|       <property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property> |       <property name="context"><value>net.sf.acegisecurity.context.security.SecureContextImpl</value></property> | ||||||
|    </bean> |    </bean> | ||||||
| @ -146,33 +156,14 @@ | |||||||
|       <property name="objectDefinitionSource"> |       <property name="objectDefinitionSource"> | ||||||
|          <value> |          <value> | ||||||
| 			    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON | 			    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON | ||||||
| 				\A/secure/super.*\Z=ROLE_WE_DONT_HAVE | 			    PATTERN_TYPE_APACHE_ANT | ||||||
| 				\A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_USER | 			    /index.jsp=ROLE_ANONYMOUS,ROLE_USER | ||||||
|  | 			    /hello.htm=ROLE_ANONYMOUS,ROLE_USER | ||||||
|  | 			    /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER | ||||||
|  | 			    /acegilogin.jsp=ROLE_ANONYMOUS,ROLE_USER | ||||||
|  | 				/**=ROLE_USER | ||||||
|          </value> |          </value> | ||||||
|       </property> |       </property> | ||||||
|    </bean> |    </bean> | ||||||
| 
 | 
 | ||||||
|    <!-- BASIC Regular Expression Syntax (for beginners): |  | ||||||
| 
 |  | ||||||
|         \A means the start of the string (ie the beginning of the URL) |  | ||||||
|         \Z means the end of the string (ie the end of the URL) |  | ||||||
|         .  means any single character |  | ||||||
|         *  means null or any number of repetitions of the last expression (so .* means zero or more characters) |  | ||||||
| 
 |  | ||||||
|         Some examples: |  | ||||||
| 
 |  | ||||||
|         Expression:   \A/my/directory/.*\Z |  | ||||||
|         Would match:    /my/directory/ |  | ||||||
|                         /my/directory/hello.html |  | ||||||
| 
 |  | ||||||
|         Expression:   \A/.*\Z |  | ||||||
|         Would match:    /hello.html |  | ||||||
|                         / |  | ||||||
| 
 |  | ||||||
|         Expression:   \A/.*/secret.html\Z |  | ||||||
|         Would match:    /some/directory/secret.html |  | ||||||
|                         /another/secret.html |  | ||||||
|         Not match:      /anothersecret.html (missing required /) |  | ||||||
|    --> |  | ||||||
| 
 |  | ||||||
| </beans> | </beans> | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user