1
0
mirror of synced 2026-08-05 17:57:15 +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:
Ben Alex
2005-02-23 06:09:56 +00:00
parent 3c4faf58c7
commit 693ac5a24a
21 changed files with 1467 additions and 135 deletions
@@ -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");
* 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
* 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,
ConfigAttributeDefinition config) throws AccessDeniedException;
ConfigAttributeDefinition config)
throws AccessDeniedException, InsufficientAuthenticationException;
/**
* 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");
* you may not use this file except in compliance with the License.
@@ -16,9 +16,8 @@
package net.sf.acegisecurity;
/**
* Abstract superclass for all exceptions related to the {@link
* AuthenticationManager} being unable to authenticate an {@link
* Authentication} object.
* Abstract superclass for all exceptions related an {@link Authentication}
* object being invalid for whatever reason.
*
* @author Ben Alex
* @version $Id$
@@ -57,11 +56,11 @@ public abstract class AuthenticationException extends AcegiSecurityException {
//~ Methods ================================================================
void setAuthentication(Authentication authentication) {
this.authentication = authentication;
}
public Authentication getAuthentication() {
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");
* 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.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.util.PortResolver;
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.util.Assert;
import java.io.IOException;
import javax.servlet.Filter;
@@ -54,10 +59,13 @@ import javax.servlet.http.HttpServletResponse;
* </p>
*
* <p>
* If an {@link AccessDeniedException} is detected, 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
* If an {@link AccessDeniedException} is detected, the filter will determine
* whether or not the user is an anonymous user. If they are an anonymous
* user, the <code>authenticationEntryPoint</code> will be launched. If they
* 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
* trace etc). Again, this allows common access denied handling irrespective
* of the originating security interceptor.
@@ -104,6 +112,7 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean {
//~ Instance fields ========================================================
private AuthenticationEntryPoint authenticationEntryPoint;
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
private FilterSecurityInterceptor filterSecurityInterceptor;
private PortResolver portResolver = new PortResolverImpl();
@@ -118,6 +127,15 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean {
return authenticationEntryPoint;
}
public void setAuthenticationTrustResolver(
AuthenticationTrustResolver authenticationTrustResolver) {
this.authenticationTrustResolver = authenticationTrustResolver;
}
public AuthenticationTrustResolver getAuthenticationTrustResolver() {
return authenticationTrustResolver;
}
public void setFilterSecurityInterceptor(
FilterSecurityInterceptor filterSecurityInterceptor) {
this.filterSecurityInterceptor = filterSecurityInterceptor;
@@ -136,19 +154,13 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean {
}
public void afterPropertiesSet() throws Exception {
if (authenticationEntryPoint == null) {
throw new IllegalArgumentException(
"authenticationEntryPoint must be specified");
}
if (filterSecurityInterceptor == null) {
throw new IllegalArgumentException(
"filterSecurityInterceptor must be specified");
}
if (portResolver == null) {
throw new IllegalArgumentException("portResolver must be specified");
}
Assert.notNull(authenticationEntryPoint,
"authenticationEntryPoint must be specified");
Assert.notNull(filterSecurityInterceptor,
"filterSecurityInterceptor must be specified");
Assert.notNull(portResolver, "portResolver must be specified");
Assert.notNull(authenticationTrustResolver,
"authenticationTrustResolver must be specified");
}
public void destroy() {}
@@ -172,43 +184,29 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean {
logger.debug("Chain processed normally");
}
} 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()) {
logger.debug(
"Authentication failed - adding target URL to Session: "
+ targetUrl, authentication);
logger.debug("Authentication exception occurred; redirecting to authentication entry point",
authentication);
}
((HttpServletRequest) request).getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY,
targetUrl);
authenticationEntryPoint.commence(request, response, authentication);
sendStartAuthentication(fi, authentication);
} catch (AccessDeniedException accessDenied) {
if (logger.isDebugEnabled()) {
logger.debug(
"Access is denied - sending back forbidden response");
}
if (authenticationTrustResolver.isAnonymous(
SecureContextUtils.getSecureContext().getAuthentication())) {
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,
accessDenied);
sendAccessDeniedError(request, response, accessDenied);
sendStartAuthentication(fi, null);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Access is denied (user is not anonymous); sending back forbidden response",
accessDenied);
}
sendAccessDeniedError(fi, accessDenied);
}
} catch (Throwable otherException) {
throw new ServletException(otherException);
}
@@ -216,19 +214,43 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean {
public void init(FilterConfig filterConfig) throws ServletException {}
/**
* Allows subclasses to override if required
*
* @param request
* @param response
* @param accessDenied
*
* @throws IOException
*/
protected void sendAccessDeniedError(ServletRequest request,
ServletResponse response, AccessDeniedException accessDenied)
throws IOException {
((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN,
protected void sendAccessDeniedError(FilterInvocation fi,
AccessDeniedException accessDenied)
throws ServletException, IOException {
((HttpServletRequest) fi.getRequest()).getSession().setAttribute(ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY,
accessDenied);
((HttpServletResponse) fi.getResponse()).sendError(HttpServletResponse.SC_FORBIDDEN,
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");
* you may not use this file except in compliance with the License.
@@ -29,7 +29,7 @@ import java.util.Vector;
* @author Ben Alex
* @version $Id$
*/
public class UserAttributeDefinition {
public class UserAttribute {
//~ Instance fields ========================================================
private List authorities = new Vector();
@@ -38,7 +38,7 @@ public class UserAttributeDefinition {
//~ Constructors ===========================================================
public UserAttributeDefinition() {
public UserAttribute() {
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");
* 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
* separated list of values.
* Property editor that creates a {@link UserAttribute} from a comma separated
* list of values.
*
* @author Ben Alex
* @version $Id$
@@ -37,7 +37,7 @@ public class UserAttributeEditor extends PropertyEditorSupport {
setValue(null);
} else {
String[] tokens = StringUtils.commaDelimitedListToStringArray(s);
UserAttributeDefinition userAttrib = new UserAttributeDefinition();
UserAttribute userAttrib = new UserAttribute();
for (int i = 0; i < tokens.length; 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");
* 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
configAttribEd.setAsText(value);
UserAttributeDefinition attr = (UserAttributeDefinition) configAttribEd
.getValue();
UserAttribute attr = (UserAttribute) configAttribEd.getValue();
// Make a user object, assuming the properties were properly provided
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");
* 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.BadCredentialsException;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import net.sf.acegisecurity.MockAuthenticationEntryPoint;
import net.sf.acegisecurity.MockHttpServletRequest;
import net.sf.acegisecurity.MockHttpServletResponse;
import net.sf.acegisecurity.MockHttpSession;
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 java.io.IOException;
@@ -62,8 +68,47 @@ public class SecurityEnforcementFilterTests extends TestCase {
junit.textui.TestRunner.run(SecurityEnforcementFilterTests.class);
}
public void testAccessDeniedWhenAccessDeniedException()
throws Exception {
public void testAccessDeniedWhenAnonymous() 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
HttpSession session = new MockHttpSession();
MockHttpServletRequest request = new MockHttpServletRequest(null,
@@ -77,6 +122,11 @@ public class SecurityEnforcementFilterTests extends TestCase {
MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(true,
false);
// Setup ContextHolder, as filter needs to check if user is anonymous
SecureContext sc = new SecureContextImpl();
sc.setAuthentication(null);
ContextHolder.setContext(sc);
// Test
SecurityEnforcementFilter filter = new SecurityEnforcementFilter();
filter.setFilterSecurityInterceptor(interceptor);
@@ -281,6 +331,11 @@ public class SecurityEnforcementFilterTests extends TestCase {
assertTrue(true);
}
protected void tearDown() throws Exception {
super.tearDown();
ContextHolder.setContext(null);
}
//~ Inner Classes ==========================================================
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");
* 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
* UserAttributeDefinition}.
* Tests {@link UserAttributeEditor} and associated {@link UserAttribute}.
*
* @author Ben Alex
* @version $Id$
@@ -50,8 +49,7 @@ public class UserAttributeEditorTests extends TestCase {
UserAttributeEditor editor = new UserAttributeEditor();
editor.setAsText("password,ROLE_ONE,ROLE_TWO");
UserAttributeDefinition user = (UserAttributeDefinition) editor
.getValue();
UserAttribute user = (UserAttribute) editor.getValue();
assertTrue(user.isValid());
assertTrue(user.isEnabled()); // default
assertEquals("password", user.getPassword());
@@ -64,8 +62,7 @@ public class UserAttributeEditorTests extends TestCase {
UserAttributeEditor editor = new UserAttributeEditor();
editor.setAsText("password,disabled,ROLE_ONE,ROLE_TWO");
UserAttributeDefinition user = (UserAttributeDefinition) editor
.getValue();
UserAttribute user = (UserAttribute) editor.getValue();
assertTrue(user.isValid());
assertTrue(!user.isEnabled());
assertEquals("password", user.getPassword());
@@ -78,8 +75,7 @@ public class UserAttributeEditorTests extends TestCase {
UserAttributeEditor editor = new UserAttributeEditor();
editor.setAsText("");
UserAttributeDefinition user = (UserAttributeDefinition) editor
.getValue();
UserAttribute user = (UserAttribute) editor.getValue();
assertTrue(user == null);
}
@@ -87,8 +83,7 @@ public class UserAttributeEditorTests extends TestCase {
UserAttributeEditor editor = new UserAttributeEditor();
editor.setAsText("password,ROLE_ONE,enabled,ROLE_TWO");
UserAttributeDefinition user = (UserAttributeDefinition) editor
.getValue();
UserAttribute user = (UserAttribute) editor.getValue();
assertTrue(user.isValid());
assertTrue(user.isEnabled());
assertEquals("password", user.getPassword());
@@ -101,8 +96,7 @@ public class UserAttributeEditorTests extends TestCase {
UserAttributeEditor editor = new UserAttributeEditor();
editor.setAsText("MALFORMED_STRING");
UserAttributeDefinition user = (UserAttributeDefinition) editor
.getValue();
UserAttribute user = (UserAttribute) editor.getValue();
assertTrue(user == null);
}
@@ -110,8 +104,7 @@ public class UserAttributeEditorTests extends TestCase {
UserAttributeEditor editor = new UserAttributeEditor();
editor.setAsText("disabled");
UserAttributeDefinition user = (UserAttributeDefinition) editor
.getValue();
UserAttribute user = (UserAttribute) editor.getValue();
assertTrue(user == null);
}
@@ -119,8 +112,7 @@ public class UserAttributeEditorTests extends TestCase {
UserAttributeEditor editor = new UserAttributeEditor();
editor.setAsText("password,enabled");
UserAttributeDefinition user = (UserAttributeDefinition) editor
.getValue();
UserAttribute user = (UserAttribute) editor.getValue();
assertTrue(user == null);
}
@@ -128,8 +120,7 @@ public class UserAttributeEditorTests extends TestCase {
UserAttributeEditor editor = new UserAttributeEditor();
editor.setAsText(null);
UserAttributeDefinition user = (UserAttributeDefinition) editor
.getValue();
UserAttribute user = (UserAttribute) editor.getValue();
assertTrue(user == null);
}
}