SEC-97: Format Acegi Security source code in accordance with latest Jalopy configuration.

This commit is contained in:
Ben Alex 2006-05-23 13:38:33 +00:00
parent 49800018e9
commit ab12817b7a
654 changed files with 17379 additions and 21566 deletions

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -18,6 +18,7 @@ package org.acegisecurity.adapters.cas;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.apache.commons.logging.Log;
@ -29,51 +30,32 @@ import javax.servlet.ServletRequest;
/**
* Provides actual CAS authentication by delegation to an
* <code>AuthenticationManager</code>.
*
* <P>
* Do not use this class directly. Instead configure CAS to use the {@link
* CasPasswordHandlerProxy}.
* </p>
* Provides actual CAS authentication by delegation to an <code>AuthenticationManager</code>.<P>Do not use this
* class directly. Instead configure CAS to use the {@link CasPasswordHandlerProxy}.</p>
*
* @author Ben Alex
* @version $Id$
*/
public final class CasPasswordHandler implements InitializingBean {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(CasPasswordHandler.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private AuthenticationManager authenticationManager;
//~ Methods ================================================================
public void setAuthenticationManager(
AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
if (this.authenticationManager == null) {
throw new IllegalArgumentException(
"An AuthenticationManager is required");
throw new IllegalArgumentException("An AuthenticationManager is required");
}
}
/**
* Called by <code>CasPasswordHandlerProxy</code> for individual
* authentication requests.
*
* <P>
* Delegates to the configured <code>AuthenticationManager</code>.
* </p>
* Called by <code>CasPasswordHandlerProxy</code> for individual authentication requests.<P>Delegates to
* the configured <code>AuthenticationManager</code>.</p>
*
* @param servletRequest as provided by CAS
* @param username provided to CAS
@ -81,8 +63,7 @@ public final class CasPasswordHandler implements InitializingBean {
*
* @return whether authentication was successful or not
*/
public boolean authenticate(ServletRequest servletRequest, String username,
String password) {
public boolean authenticate(ServletRequest servletRequest, String username, String password) {
if ((username == null) || "".equals(username)) {
return false;
}
@ -91,26 +72,31 @@ public final class CasPasswordHandler implements InitializingBean {
password = "";
}
Authentication request = new UsernamePasswordAuthenticationToken(username
.toString(), password.toString());
Authentication request = new UsernamePasswordAuthenticationToken(username.toString(), password.toString());
Authentication response = null;
try {
response = authenticationManager.authenticate(request);
} catch (AuthenticationException failed) {
if (logger.isDebugEnabled()) {
logger.debug("Authentication request for user: " + username
+ " failed: " + failed.toString());
logger.debug("Authentication request for user: " + username + " failed: " + failed.toString());
}
return false;
}
if (logger.isDebugEnabled()) {
logger.debug("Authentication request for user: " + username
+ " successful");
logger.debug("Authentication request for user: " + username + " successful");
}
return true;
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -31,62 +31,39 @@ import javax.servlet.http.HttpServletRequest;
/**
* Enables CAS to use the Acegi Security System for authentication.
*
* <P>
* This class works along with {@link CasPasswordHandler} to enable users to
* easily migrate from stand-alone Acegi Security System deployments to
* enterprise-wide CAS deployments.
* </p>
*
* <p>
* It should be noted that the Acegi Security System will operate as a CAS
* client irrespective of the <code>PasswordHandler</code> used on the CAS
* server. In other words, this class need <B>not</B> be used on the CAS
* server if not desired. It exists solely for the convenience of users
* wishing have CAS delegate to an Acegi Security System-based
* <code>AuthenticationManager</code>.
* </p>
*
* <p>
* This class works requires a properly configured
* <code>CasPasswordHandler</code>. On the first authentication request, the
* class will use Spring's {@link
* WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
* method to obtain an <code>ApplicationContext</code> instance, inside which
* must be a configured <code>CasPasswordHandler</code> instance. The
* <code>CasPasswordHandlerProxy</code> will then delegate authentication
* requests to that instance.
* </p>
*
* <p>
* To configure CAS to use this class, edit CAS' <code>web.xml</code> and
* define the <code>edu.yale.its.tp.cas.authHandler</code> context parameter
* with the value
* <code>org.acegisecurity.adapters.cas.CasPasswordHandlerProxy</code>.
* </p>
* Enables CAS to use the Acegi Security System for authentication.<P>This class works along with {@link
* CasPasswordHandler} to enable users to easily migrate from stand-alone Acegi Security System deployments to
* enterprise-wide CAS deployments.</p>
* <p>It should be noted that the Acegi Security System will operate as a CAS client irrespective of the
* <code>PasswordHandler</code> used on the CAS server. In other words, this class need <B>not</B> be used on the CAS
* server if not desired. It exists solely for the convenience of users wishing have CAS delegate to an Acegi Security
* System-based <code>AuthenticationManager</code>.</p>
* <p>This class works requires a properly configured <code>CasPasswordHandler</code>. On the first authentication
* request, the class will use Spring's {@link WebApplicationContextUtils#getWebApplicationContext(ServletContext sc)}
* method to obtain an <code>ApplicationContext</code> instance, inside which must be a configured
* <code>CasPasswordHandler</code> instance. The <code>CasPasswordHandlerProxy</code> will then delegate
* authentication requests to that instance.</p>
* <p>To configure CAS to use this class, edit CAS' <code>web.xml</code> and define the
* <code>edu.yale.its.tp.cas.authHandler</code> context parameter with the value
* <code>org.acegisecurity.adapters.cas.CasPasswordHandlerProxy</code>.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class CasPasswordHandlerProxy implements PasswordHandler {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(CasPasswordHandlerProxy.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private ApplicationContext ctx;
private CasPasswordHandler handler;
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Called by CAS when authentication is required.
*
* <P>
* Delegates to the <code>CasPasswordHandler</code>.
* </p>
* Called by CAS when authentication is required.<P>Delegates to the <code>CasPasswordHandler</code>.</p>
*
* @param request as provided by CAS
* @param username provided to CAS
@ -94,17 +71,13 @@ public class CasPasswordHandlerProxy implements PasswordHandler {
*
* @return whether authentication was successful or not
*
* @throws IllegalArgumentException if the application context does not
* contain a <code>CasPasswordHandler</code> or the
* <code>ServletRequest</code> was not of type
* <code>HttpServletRequest</code>
* @throws IllegalArgumentException if the application context does not contain a <code>CasPasswordHandler</code>
* or the <code>ServletRequest</code> was not of type <code>HttpServletRequest</code>
*/
public boolean authenticate(ServletRequest request, String username,
String password) {
public boolean authenticate(ServletRequest request, String username, String password) {
if (ctx == null) {
if (!(request instanceof HttpServletRequest)) {
throw new IllegalArgumentException(
"Can only process HttpServletRequest");
throw new IllegalArgumentException("Can only process HttpServletRequest");
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
@ -130,13 +103,11 @@ public class CasPasswordHandlerProxy implements PasswordHandler {
/**
* Allows test cases to override where application context obtained from.
*
* @param httpRequest which can be used to find the
* <code>ServletContext</code>
* @param httpRequest which can be used to find the <code>ServletContext</code>
*
* @return the Spring application context
*/
protected ApplicationContext getContext(HttpServletRequest httpRequest) {
return WebApplicationContextUtils.getRequiredWebApplicationContext(httpRequest.getSession()
.getServletContext());
return WebApplicationContextUtils.getRequiredWebApplicationContext(httpRequest.getSession().getServletContext());
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -12,90 +12,80 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.acegisecurity.adapters.cas3;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.AuthenticationHandler;
import org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.util.Assert;
/**
* <p>
* Provides JA-SIG CAS 3 authentication by delegating to the Acegi
* <code>AuthenticationManager</code>.
* </p>
* <p>
* This class would be configured in the
* <code>webapp/WEB-INF/deployerConfigContext.xml</code> file in the CAS
* distribution.
* </p>
*
* <p>Provides JA-SIG CAS 3 authentication by delegating to the Acegi <code>AuthenticationManager</code>.</p>
* <p>This class would be configured in the <code>webapp/WEB-INF/deployerConfigContext.xml</code> file in the CAS
* distribution.</p>
*
* @author Scott Battaglia
* @version $Id$
*
*
* @see AuthenticationHandler
* @see AuthenticationManager
*/
public final class CasAuthenticationHandler extends
AbstractUsernamePasswordAuthenticationHandler {
public final class CasAuthenticationHandler extends AbstractUsernamePasswordAuthenticationHandler {
//~ Instance fields ================================================================================================
private Log log = LogFactory.getLog(this.getClass());
private AuthenticationManager authenticationManager;
private Log log = LogFactory.getLog(this.getClass());
private AuthenticationManager authenticationManager;
//~ Methods ========================================================================================================
protected boolean authenticateUsernamePasswordInternal(
final UsernamePasswordCredentials credentials)
throws AuthenticationException {
protected void afterPropertiesSetInternal() throws Exception {
Assert.notNull(this.authenticationManager, "authenticationManager cannot be null.");
}
final Authentication authenticationRequest = new UsernamePasswordAuthenticationToken(
credentials.getUsername(), credentials.getPassword());
protected boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials)
throws AuthenticationException {
final Authentication authenticationRequest = new UsernamePasswordAuthenticationToken(credentials.getUsername(),
credentials.getPassword());
if (log.isDebugEnabled()) {
log.debug("Attempting to authenticate for user: "
+ credentials.getUsername());
}
if (log.isDebugEnabled()) {
log.debug("Attempting to authenticate for user: " + credentials.getUsername());
}
try {
this.authenticationManager.authenticate(authenticationRequest);
} catch (final org.acegisecurity.AuthenticationException e) {
if (log.isDebugEnabled()) {
log
.debug("Authentication request for "
+ credentials.getUsername() + "failed: "
+ e.toString());
}
return false;
}
try {
this.authenticationManager.authenticate(authenticationRequest);
} catch (final org.acegisecurity.AuthenticationException e) {
if (log.isDebugEnabled()) {
log.debug("Authentication request for " + credentials.getUsername() + "failed: " + e.toString());
}
if (log.isDebugEnabled()) {
log.debug("Authentication request for " + credentials.getUsername()
+ " successful.");
}
return false;
}
return true;
}
if (log.isDebugEnabled()) {
log.debug("Authentication request for " + credentials.getUsername() + " successful.");
}
protected void afterPropertiesSetInternal() throws Exception {
Assert.notNull(this.authenticationManager,
"authenticationManager cannot be null.");
}
return true;
}
/**
* Method to set the Acegi <code>AuthenticationManager</code> to delegate
* to.
*
* @param authenticationManager
* the Acegi AuthenticationManager that knows how to authenticate
* users.
*/
public void setAuthenticationManager(
final AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
/**
* Method to set the Acegi <code>AuthenticationManager</code> to delegate to.
*
* @param authenticationManager the Acegi AuthenticationManager that knows how to authenticate users.
*/
public void setAuthenticationManager(final AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,7 +32,7 @@ import javax.servlet.http.HttpServletRequest;
* @version $Id$
*/
public class CasPasswordHandlerProxyTests extends TestCase {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public CasPasswordHandlerProxyTests() {
super();
@ -42,16 +42,16 @@ public class CasPasswordHandlerProxyTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(CasPasswordHandlerProxyTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testDetectsIfHttpServletRequestNotPassed() {
CasPasswordHandlerProxy proxy = new MockCasPasswordHandlerProxy(
"org/acegisecurity/adapters/cas/applicationContext-valid.xml");
@ -60,8 +60,7 @@ public class CasPasswordHandlerProxyTests extends TestCase {
proxy.authenticate(null, "x", "y");
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("Can only process HttpServletRequest",
expected.getMessage());
assertEquals("Can only process HttpServletRequest", expected.getMessage());
}
}
@ -73,23 +72,19 @@ public class CasPasswordHandlerProxyTests extends TestCase {
proxy.authenticate(new MockHttpServletRequest(), "x", "y");
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("Bean context must contain at least one bean of type CasPasswordHandler",
expected.getMessage());
assertEquals("Bean context must contain at least one bean of type CasPasswordHandler", expected.getMessage());
}
}
public void testNormalOperation() {
CasPasswordHandlerProxy proxy = new MockCasPasswordHandlerProxy(
"org/acegisecurity/adapters/cas/applicationContext-valid.xml");
assertTrue(proxy.authenticate(new MockHttpServletRequest(), "marissa",
"koala"));
assertFalse(proxy.authenticate(new MockHttpServletRequest(), "marissa",
"WRONG_PASSWORD"));
assertFalse(proxy.authenticate(new MockHttpServletRequest(),
"INVALID_USER_NAME", "WRONG_PASSWORD"));
assertTrue(proxy.authenticate(new MockHttpServletRequest(), "marissa", "koala"));
assertFalse(proxy.authenticate(new MockHttpServletRequest(), "marissa", "WRONG_PASSWORD"));
assertFalse(proxy.authenticate(new MockHttpServletRequest(), "INVALID_USER_NAME", "WRONG_PASSWORD"));
}
//~ Inner Classes ==========================================================
//~ Inner Classes ==================================================================================================
/**
* Mock object so that application context source can be specified.

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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 org.springframework.mock.web.MockHttpServletRequest;
* @version $Id$
*/
public class CasPasswordHandlerTests extends TestCase {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public CasPasswordHandlerTests() {
super();
@ -39,24 +39,23 @@ public class CasPasswordHandlerTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(CasPasswordHandlerTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testDeniesAccessWhenAuthenticationManagerThrowsException()
throws Exception {
CasPasswordHandler handler = new CasPasswordHandler();
handler.setAuthenticationManager(new MockAuthenticationManager(false));
handler.afterPropertiesSet();
assertFalse(handler.authenticate(new MockHttpServletRequest(),
"username", "password"));
assertFalse(handler.authenticate(new MockHttpServletRequest(), "username", "password"));
}
public void testDetectsEmptyAuthenticationManager()
@ -67,8 +66,7 @@ public class CasPasswordHandlerTests extends TestCase {
handler.afterPropertiesSet();
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("An AuthenticationManager is required",
expected.getMessage());
assertEquals("An AuthenticationManager is required", expected.getMessage());
}
}
@ -85,14 +83,11 @@ public class CasPasswordHandlerTests extends TestCase {
handler.afterPropertiesSet();
// If empty or null username we return false
assertFalse(handler.authenticate(new MockHttpServletRequest(), "",
"password"));
assertFalse(handler.authenticate(new MockHttpServletRequest(), null,
"password"));
assertFalse(handler.authenticate(new MockHttpServletRequest(), "", "password"));
assertFalse(handler.authenticate(new MockHttpServletRequest(), null, "password"));
// We authenticate with null passwords (they might not have one)
assertTrue(handler.authenticate(new MockHttpServletRequest(), "user",
null));
assertTrue(handler.authenticate(new MockHttpServletRequest(), "user", null));
assertTrue(handler.authenticate(new MockHttpServletRequest(), "user", ""));
}
@ -101,7 +96,6 @@ public class CasPasswordHandlerTests extends TestCase {
handler.setAuthenticationManager(new MockAuthenticationManager(true));
handler.afterPropertiesSet();
assertTrue(handler.authenticate(new MockHttpServletRequest(),
"username", "password"));
assertTrue(handler.authenticate(new MockHttpServletRequest(), "username", "password"));
}
}

View File

@ -1,77 +1,97 @@
/* Copyright 2004, 2005, 2006 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 org.acegisecurity.adapters.cas3;
import org.acegisecurity.AuthenticationManager;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
/**
* Tests {@link CasAuthenticationHandler}
*
* @author Scott Battaglia
* @version $Id$
*
*/
public class CasAuthenticationHandlerTests extends AbstractDependencyInjectionSpringContextTests {
//~ Instance fields ================================================================================================
private AuthenticationManager authenticationManager;
private CasAuthenticationHandler casAuthenticationHandler;
public void setAuthenticationManager(final AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
private AuthenticationManager authenticationManager;
private CasAuthenticationHandler casAuthenticationHandler;
protected String[] getConfigLocations() {
return new String[] {"/org/acegisecurity/adapters/cas/applicationContext-valid.xml"};
}
//~ Methods ========================================================================================================
protected void onSetUp() throws Exception {
this.casAuthenticationHandler = new CasAuthenticationHandler();
this.casAuthenticationHandler.setAuthenticationManager(authenticationManager);
this.casAuthenticationHandler.afterPropertiesSet();
}
public void testAfterPropertiesSet() throws Exception {
this.casAuthenticationHandler.setAuthenticationManager(null);
try {
this.casAuthenticationHandler.afterPropertiesSet();
fail("IllegalArgumenException expected when no AuthenticationManager is set.");
} catch (final IllegalArgumentException e) {
// this is okay
}
}
public void testValidUsernamePasswordCombination() {
try {
assertTrue(this.casAuthenticationHandler.authenticate(getCredentialsFor("scott", "wombat")));
} catch (final AuthenticationException e) {
fail("AuthenticationException not expected.");
}
}
public void testInvalidUsernamePasswordCombination() {
try {
assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor("scott", "scott")));
} catch (final AuthenticationException e) {
fail("AuthenticationException not expected.");
}
}
public void testGracefullyHandlesInvalidInput() {
protected String[] getConfigLocations() {
return new String[] {"/org/acegisecurity/adapters/cas/applicationContext-valid.xml"};
}
try {
assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor("", "")));
assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor(null, null)));
} catch (final AuthenticationException e) {
fail("AuthenticationException not expected.");
}
}
private UsernamePasswordCredentials getCredentialsFor(final String username, final String password) {
final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials();
credentials.setUsername(username);
credentials.setPassword(password);
return credentials;
}
private UsernamePasswordCredentials getCredentialsFor(final String username, final String password) {
final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials();
credentials.setUsername(username);
credentials.setPassword(password);
return credentials;
}
protected void onSetUp() throws Exception {
this.casAuthenticationHandler = new CasAuthenticationHandler();
this.casAuthenticationHandler.setAuthenticationManager(authenticationManager);
this.casAuthenticationHandler.afterPropertiesSet();
}
public void setAuthenticationManager(final AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
public void testAfterPropertiesSet() throws Exception {
this.casAuthenticationHandler.setAuthenticationManager(null);
try {
this.casAuthenticationHandler.afterPropertiesSet();
fail("IllegalArgumenException expected when no AuthenticationManager is set.");
} catch (final IllegalArgumentException e) {
// this is okay
}
}
public void testGracefullyHandlesInvalidInput() {
try {
assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor("", "")));
assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor(null, null)));
} catch (final AuthenticationException e) {
fail("AuthenticationException not expected.");
}
}
public void testInvalidUsernamePasswordCombination() {
try {
assertFalse(this.casAuthenticationHandler.authenticate(getCredentialsFor("scott", "scott")));
} catch (final AuthenticationException e) {
fail("AuthenticationException not expected.");
}
}
public void testValidUsernamePasswordCombination() {
try {
assertTrue(this.casAuthenticationHandler.authenticate(getCredentialsFor("scott", "wombat")));
} catch (final AuthenticationException e) {
fail("AuthenticationException not expected.");
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -41,48 +41,27 @@ import java.util.Map;
/**
* Adapter to enable Catalina (Tomcat) to authenticate via the Acegi Security
* System for Spring.
*
* <p>
* Returns a {@link PrincipalAcegiUserToken} to Catalina's authentication
* system, which is subsequently available via
* <code>HttpServletRequest.getUserPrincipal()</code>.
* </p>
* Adapter to enable Catalina (Tomcat) to authenticate via the Acegi Security System for Spring.<p>Returns a {@link
* PrincipalAcegiUserToken} to Catalina's authentication system, which is subsequently available via
* <code>HttpServletRequest.getUserPrincipal()</code>.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class CatalinaAcegiUserRealm extends RealmBase {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(CatalinaAcegiUserRealm.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
protected final String name = "CatalinaSpringUserRealm / $Id$";
private AuthenticationManager authenticationManager;
private Container container;
private String appContextLocation;
private String key;
protected final String name = "CatalinaSpringUserRealm / $Id$";
//~ Methods ================================================================
public void setAppContextLocation(String appContextLocation) {
this.appContextLocation = appContextLocation;
}
public String getAppContextLocation() {
return appContextLocation;
}
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
//~ Methods ========================================================================================================
public Principal authenticate(String username, String credentials) {
if (username == null) {
@ -93,25 +72,21 @@ public class CatalinaAcegiUserRealm extends RealmBase {
credentials = "";
}
Authentication request = new UsernamePasswordAuthenticationToken(username,
credentials);
Authentication request = new UsernamePasswordAuthenticationToken(username, credentials);
Authentication response = null;
try {
response = authenticationManager.authenticate(request);
} catch (AuthenticationException failed) {
if (logger.isDebugEnabled()) {
logger.debug("Authentication request for user: " + username
+ " failed: " + failed.toString());
logger.debug("Authentication request for user: " + username + " failed: " + failed.toString());
}
return null;
}
return new PrincipalAcegiUserToken(this.key,
response.getPrincipal().toString(),
response.getCredentials().toString(), response.getAuthorities(),
response.getPrincipal());
return new PrincipalAcegiUserToken(this.key, response.getPrincipal().toString(),
response.getCredentials().toString(), response.getAuthorities(), response.getPrincipal());
}
public Principal authenticate(String username, byte[] credentials) {
@ -132,10 +107,9 @@ public class CatalinaAcegiUserRealm extends RealmBase {
*
* @return DOCUMENT ME!
*/
public java.security.Principal authenticate(java.lang.String username,
java.lang.String digest, java.lang.String nonce, java.lang.String nc,
java.lang.String cnonce, java.lang.String qop, java.lang.String realm,
java.lang.String md5a2) {
public java.security.Principal authenticate(java.lang.String username, java.lang.String digest,
java.lang.String nonce, java.lang.String nc, java.lang.String cnonce, java.lang.String qop,
java.lang.String realm, java.lang.String md5a2) {
return null;
}
@ -150,31 +124,12 @@ public class CatalinaAcegiUserRealm extends RealmBase {
return null;
}
public boolean hasRole(Principal principal, String role) {
if ((principal == null) || (role == null)) {
return false;
}
if (!(principal instanceof PrincipalAcegiUserToken)) {
logger.warn(
"Expected passed principal to be of type PrincipalAcegiUserToken but was "
+ principal.getClass().getName());
return false;
}
PrincipalAcegiUserToken test = (PrincipalAcegiUserToken) principal;
return test.isUserInRole(role);
public String getAppContextLocation() {
return appContextLocation;
}
/**
* Provides the method that Catalina will use to start the container.
*
* @throws LifecycleException if a problem is detected
*/
public void start() throws LifecycleException {
this.start(true);
public String getKey() {
return key;
}
protected String getName() {
@ -203,14 +158,38 @@ public class CatalinaAcegiUserRealm extends RealmBase {
return null;
}
public boolean hasRole(Principal principal, String role) {
if ((principal == null) || (role == null)) {
return false;
}
if (!(principal instanceof PrincipalAcegiUserToken)) {
logger.warn("Expected passed principal to be of type PrincipalAcegiUserToken but was "
+ principal.getClass().getName());
return false;
}
PrincipalAcegiUserToken test = (PrincipalAcegiUserToken) principal;
return test.isUserInRole(role);
}
public void setAppContextLocation(String appContextLocation) {
this.appContextLocation = appContextLocation;
}
public void setKey(String key) {
this.key = key;
}
/**
* Provides a method to load the container adapter without delegating to
* the superclass, which cannot operate outside the Catalina container.
* Provides the method that Catalina will use to start the container.
*
* @throws LifecycleException if a problem is detected
*/
protected void startForTest() throws LifecycleException {
this.start(false);
public void start() throws LifecycleException {
this.start(true);
}
private void start(boolean startParent) throws LifecycleException {
@ -226,17 +205,13 @@ public class CatalinaAcegiUserRealm extends RealmBase {
throw new LifecycleException("key must be defined");
}
File xml = new File(System.getProperty("catalina.base"),
appContextLocation);
File xml = new File(System.getProperty("catalina.base"), appContextLocation);
if (!xml.exists()) {
throw new LifecycleException(
"appContextLocation does not seem to exist in "
+ xml.toString());
throw new LifecycleException("appContextLocation does not seem to exist in " + xml.toString());
}
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext(
"file:" + xml.getAbsolutePath());
FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext("file:" + xml.getAbsolutePath());
Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true);
if (beans.size() == 0) {
@ -248,4 +223,14 @@ public class CatalinaAcegiUserRealm extends RealmBase {
authenticationManager = (AuthenticationManager) beans.get(beanName);
logger.info("CatalinaAcegiUserRealm Started");
}
/**
* Provides a method to load the container adapter without delegating to the superclass, which cannot
* operate outside the Catalina container.
*
* @throws LifecycleException if a problem is detected
*/
protected void startForTest() throws LifecycleException {
this.start(false);
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -38,11 +38,11 @@ import java.security.Principal;
* @version $Id$
*/
public class CatalinaAcegiUserRealmTests extends TestCase {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private final String ADAPTER_KEY = "my_key";
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public CatalinaAcegiUserRealmTests() {
super();
@ -52,21 +52,41 @@ public class CatalinaAcegiUserRealmTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(CatalinaAcegiUserRealmTests.class);
}
private CatalinaAcegiUserRealm makeAdapter(String fileName)
throws Exception {
CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
URL url = Thread.currentThread().getContextClassLoader().getResource("org/acegisecurity/adapters/" + fileName);
if (url == null) {
throw new Exception("Could not find " + fileName + " - cannot continue");
}
File file = new File(url.getFile());
System.setProperty("catalina.base", file.getParentFile().getAbsolutePath());
System.out.println("catalina.base set to: " + System.getProperty("catalina.base"));
adapter.setAppContextLocation(fileName);
adapter.setKey(ADAPTER_KEY);
adapter.startForTest();
return adapter;
}
public final void setUp() throws Exception {
super.setUp();
}
public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean()
throws Exception {
try {
CatalinaAcegiUserRealm adapter = makeAdapter(
"catalinaAdapterTest-invalid.xml");
CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-invalid.xml");
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(true);
@ -83,8 +103,7 @@ public class CatalinaAcegiUserRealmTests extends TestCase {
adapter.startForTest();
fail("Should have thrown LifecycleException");
} catch (LifecycleException expected) {
assertEquals("appContextLocation must be defined",
expected.getMessage());
assertEquals("appContextLocation must be defined", expected.getMessage());
}
adapter.setAppContextLocation("");
@ -93,8 +112,7 @@ public class CatalinaAcegiUserRealmTests extends TestCase {
adapter.startForTest();
fail("Should have thrown LifecycleException");
} catch (LifecycleException expected) {
assertEquals("appContextLocation must be defined",
expected.getMessage());
assertEquals("appContextLocation must be defined", expected.getMessage());
}
}
@ -140,15 +158,13 @@ public class CatalinaAcegiUserRealmTests extends TestCase {
}
public void testAdapterStartsUpSuccess() throws Exception {
CatalinaAcegiUserRealm adapter = makeAdapter(
"catalinaAdapterTest-valid.xml");
CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml");
assertTrue(true);
}
public void testAuthenticateManyParamsReturnsNull() {
CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
assertEquals(null,
adapter.authenticate(null, null, null, null, null, null, null, null));
assertEquals(null, adapter.authenticate(null, null, null, null, null, null, null, null));
}
public void testAuthenticateX509ReturnsNull() {
@ -158,22 +174,19 @@ public class CatalinaAcegiUserRealmTests extends TestCase {
public void testAuthenticationFailsForIncorrectPassword()
throws Exception {
CatalinaAcegiUserRealm adapter = makeAdapter(
"catalinaAdapterTest-valid.xml");
CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml");
assertEquals(null, adapter.authenticate("marissa", "kangaroo"));
}
public void testAuthenticationFailsForIncorrectUserName()
throws Exception {
CatalinaAcegiUserRealm adapter = makeAdapter(
"catalinaAdapterTest-valid.xml");
CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml");
assertEquals(null, adapter.authenticate("melissa", "koala"));
}
public void testAuthenticationUsingByteArrayForCredentials()
throws Exception {
CatalinaAcegiUserRealm adapter = makeAdapter(
"catalinaAdapterTest-valid.xml");
CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml");
byte[] credentials = {'k', 'o', 'a', 'l', 'a'};
Principal result = adapter.authenticate("marissa", credentials);
@ -184,17 +197,14 @@ public class CatalinaAcegiUserRealmTests extends TestCase {
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
assertEquals("marissa", castResult.getPrincipal());
assertEquals("koala", castResult.getCredentials());
assertEquals("ROLE_TELLER",
castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR",
castResult.getAuthorities()[1].getAuthority());
assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority());
assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
}
public void testAuthenticationUsingStringForCredentials()
throws Exception {
CatalinaAcegiUserRealm adapter = makeAdapter(
"catalinaAdapterTest-valid.xml");
CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml");
Principal result = adapter.authenticate("marissa", "koala");
if (!(result instanceof PrincipalAcegiUserToken)) {
@ -204,24 +214,20 @@ public class CatalinaAcegiUserRealmTests extends TestCase {
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
assertEquals("marissa", castResult.getPrincipal());
assertEquals("koala", castResult.getCredentials());
assertEquals("ROLE_TELLER",
castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR",
castResult.getAuthorities()[1].getAuthority());
assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority());
assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
}
public void testAuthenticationWithNullPasswordHandledGracefully()
throws Exception {
CatalinaAcegiUserRealm adapter = makeAdapter(
"catalinaAdapterTest-valid.xml");
CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml");
assertEquals(null, adapter.authenticate("marissa", (String) null));
}
public void testAuthenticationWithNullUserNameHandledGracefully()
throws Exception {
CatalinaAcegiUserRealm adapter = makeAdapter(
"catalinaAdapterTest-valid.xml");
CatalinaAcegiUserRealm adapter = makeAdapter("catalinaAdapterTest-valid.xml");
assertEquals(null, adapter.authenticate(null, "koala"));
}
@ -258,38 +264,12 @@ public class CatalinaAcegiUserRealmTests extends TestCase {
}
public void testHasRoleWithPrincipalAcegiUserToken() {
PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("KEY",
"Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
"ROLE_TWO")}, null);
PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("KEY", "Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")},
null);
CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
assertTrue(adapter.hasRole(token, "ROLE_ONE"));
assertTrue(adapter.hasRole(token, "ROLE_TWO"));
assertTrue(!adapter.hasRole(token, "ROLE_WE_DO_NOT_HAVE"));
}
private CatalinaAcegiUserRealm makeAdapter(String fileName)
throws Exception {
CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
URL url = Thread.currentThread().getContextClassLoader().getResource("org/acegisecurity/adapters/"
+ fileName);
if (url == null) {
throw new Exception("Could not find " + fileName
+ " - cannot continue");
}
File file = new File(url.getFile());
System.setProperty("catalina.base",
file.getParentFile().getAbsolutePath());
System.out.println("catalina.base set to: "
+ System.getProperty("catalina.base"));
adapter.setAppContextLocation(fileName);
adapter.setKey(ADAPTER_KEY);
adapter.startForTest();
return adapter;
}
}

View File

@ -52,28 +52,23 @@ import javax.security.auth.login.LoginException;
/**
* Adapter to enable JBoss to authenticate via the Acegi Security System for
* Spring.
*
* <p>
* Returns a {@link PrincipalAcegiUserToken} to JBoss' authentication system,
* which is subsequently available from
* <code>java:comp/env/security/subject</code>.
* </p>
* Adapter to enable JBoss to authenticate via the Acegi Security System for Spring.<p>Returns a {@link
* PrincipalAcegiUserToken} to JBoss' authentication system, which is subsequently available from
* <code>java:comp/env/security/subject</code>.</p>
*
* @author Ben Alex
* @author Sergio Bern<EFBFBD>
* @version $Id$
*/
public class JbossAcegiLoginModule extends AbstractServerLoginModule {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private AuthenticationManager authenticationManager;
private Principal identity;
private String key;
private char[] credential;
//~ Methods ================================================================
//~ Methods ========================================================================================================
protected Principal getIdentity() {
return this.identity;
@ -87,8 +82,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
Authentication user = (Authentication) this.identity;
for (int i = 0; i < user.getAuthorities().length; i++) {
roles.addMember(new SimplePrincipal(
user.getAuthorities()[i].getAuthority()));
roles.addMember(new SimplePrincipal(user.getAuthorities()[i].getAuthority()));
}
}
@ -100,8 +94,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
// prompt for a username and password
if (callbackHandler == null) {
throw new LoginException("Error: no CallbackHandler available "
+ "to collect authentication information");
throw new LoginException("Error: no CallbackHandler available " + "to collect authentication information");
}
NameCallback nc = new NameCallback("User name: ", "guest");
@ -118,16 +111,14 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
if (tmpPassword != null) {
credential = new char[tmpPassword.length];
System.arraycopy(tmpPassword, 0, credential, 0,
tmpPassword.length);
System.arraycopy(tmpPassword, 0, credential, 0, tmpPassword.length);
pc.clearPassword();
password = new String(credential);
}
} catch (java.io.IOException ioe) {
throw new LoginException(ioe.toString());
} catch (UnsupportedCallbackException uce) {
throw new LoginException("CallbackHandler does not support: "
+ uce.getCallback());
throw new LoginException("CallbackHandler does not support: " + uce.getCallback());
}
info[0] = username;
@ -136,8 +127,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
return info;
}
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
super.initialize(subject, callbackHandler, sharedState, options);
if (super.log.isInfoEnabled()) {
@ -154,24 +144,21 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
String appContextLocation = (String) options.get("appContextLocation");
if ((((singletonId == null) || "".equals(singletonId))
&& (appContextLocation == null)) || "".equals(appContextLocation)) {
throw new IllegalArgumentException(
"appContextLocation must be defined");
if ((((singletonId == null) || "".equals(singletonId)) && (appContextLocation == null))
|| "".equals(appContextLocation)) {
throw new IllegalArgumentException("appContextLocation must be defined");
}
String beanName = (String) options.get("authenticationManager");
// Attempt to find the appContextLocation only if no singletonId was defined
if ((singletonId == null) || "".equals(singletonId)) {
if (Thread.currentThread().getContextClassLoader()
.getResource(appContextLocation) == null) {
if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
if (super.log.isInfoEnabled()) {
super.log.info("cannot locate " + appContextLocation);
}
throw new IllegalArgumentException("Cannot locate "
+ appContextLocation);
throw new IllegalArgumentException("Cannot locate " + appContextLocation);
}
}
@ -182,13 +169,10 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
ctx = new ClassPathXmlApplicationContext(appContextLocation);
} catch (Exception e) {
if (super.log.isInfoEnabled()) {
super.log.info("error loading spring context "
+ appContextLocation + " " + e);
super.log.info("error loading spring context " + appContextLocation + " " + e);
}
throw new IllegalArgumentException(
"error loading spring context " + appContextLocation + " "
+ e);
throw new IllegalArgumentException("error loading spring context " + appContextLocation + " " + e);
}
} else {
if (super.log.isInfoEnabled()) {
@ -204,8 +188,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
super.log.info("singleton " + beanName + " does not exists");
}
throw new IllegalArgumentException("singleton " + singletonId
+ " does not exists");
throw new IllegalArgumentException("singleton " + singletonId + " does not exists");
}
}
@ -213,15 +196,13 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
Map beans = null;
try {
beans = ctx.getBeansOfType(AuthenticationManager.class, true,
true);
beans = ctx.getBeansOfType(AuthenticationManager.class, true, true);
} catch (Exception e) {
if (super.log.isInfoEnabled()) {
super.log.info("exception in getBeansOfType " + e);
}
throw new IllegalStateException(
"spring error in get beans by class");
throw new IllegalStateException("spring error in get beans by class");
}
if (beans.size() == 0) {
@ -248,8 +229,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
if ((username == null) && (password == null)) {
identity = null;
super.log.trace("Authenticating as unauthenticatedIdentity="
+ identity);
super.log.trace("Authenticating as unauthenticatedIdentity=" + identity);
}
if (username == null) {
@ -267,8 +247,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
if (identity == null) {
super.log.debug("creating usernamepassword token");
Authentication request = new UsernamePasswordAuthenticationToken(username,
password);
Authentication request = new UsernamePasswordAuthenticationToken(username, password);
Authentication response = null;
try {
@ -290,8 +269,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
"The credential used to identify the user has expired");
} catch (AccountExpiredException cee) {
if (super.log.isDebugEnabled()) {
super.log.debug(
"Account has expired, throwing jaas exception");
super.log.debug("Account has expired, throwing jaas exception");
}
throw new javax.security.auth.login.AccountExpiredException(
@ -301,14 +279,12 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
super.log.debug("Bad password for username=" + username);
}
throw new FailedLoginException(
"Password Incorrect/Password Required");
throw new FailedLoginException("Password Incorrect/Password Required");
}
super.log.debug("user is logged. redirecting to jaas classes");
identity = new PrincipalAcegiUserToken(this.key,
response.getName(), response.getCredentials().toString(),
identity = new PrincipalAcegiUserToken(this.key, response.getName(), response.getCredentials().toString(),
response.getAuthorities(), response.getPrincipal());
}
@ -319,8 +295,7 @@ public class JbossAcegiLoginModule extends AbstractServerLoginModule {
}
super.loginOk = true;
super.log.trace("User '" + identity + "' authenticated, loginOk="
+ loginOk);
super.log.trace("User '" + identity + "' authenticated, loginOk=" + loginOk);
return true;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,6 +16,7 @@
package org.acegisecurity.adapters.jboss;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.logging.Log;
@ -42,76 +43,45 @@ import javax.servlet.ServletResponse;
/**
* Populates a {@link org.acegisecurity.context.security.SecureContext} from
* JBoss' <code>java:comp/env/security/subject</code>.
*
* <p>
* This filter <b>never</b> preserves the <code>Authentication</code> on the
* <code>ContextHolder</code> - it is replaced every request.
* </p>
*
* <p>
* See {@link HttpSessionContextIntegrationFilter} for further information.
* </p>
* Populates a {@link org.acegisecurity.context.security.SecureContext} from JBoss'
* <code>java:comp/env/security/subject</code>.<p>This filter <b>never</b> preserves the
* <code>Authentication</code> on the <code>ContextHolder</code> - it is replaced every request.</p>
* <p>See {@link HttpSessionContextIntegrationFilter} for further information.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class JbossIntegrationFilter implements Filter {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(JbossIntegrationFilter.class);
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Does nothing. We use IoC container lifecycle services instead.
*/
public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Object principal = extractFromContainer(request);
if ((principal != null) && principal instanceof Authentication) {
SecurityContextHolder.getContext().setAuthentication((Authentication) principal);
if (logger.isDebugEnabled()) {
logger.debug(
"ContextHolder updated with Authentication from container: '"
+ principal + "'");
logger.debug("ContextHolder updated with Authentication from container: '" + principal + "'");
}
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"ContextHolder not set with new Authentication as Principal was: '"
+ principal + "'");
logger.debug("ContextHolder not set with new Authentication as Principal was: '" + principal + "'");
}
}
chain.doFilter(request, response);
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*
* @param arg0 ignored
*
* @throws ServletException ignored
*/
public void init(FilterConfig arg0) throws ServletException {}
/**
* Provided so that unit tests can override.
*
* @return a <code>Context</code> that can be used for lookup
*
* @throws NamingException DOCUMENT ME!
*/
protected Context getLookupContext() throws NamingException {
return new InitialContext();
}
private Object extractFromContainer(ServletRequest request) {
Subject subject = null;
@ -133,8 +103,7 @@ public class JbossIntegrationFilter implements Filter {
}
} catch (NamingException ne) {
if (logger.isWarnEnabled()) {
logger.warn("Lookup on Subject failed "
+ ne.getLocalizedMessage());
logger.warn("Lookup on Subject failed " + ne.getLocalizedMessage());
}
}
@ -152,4 +121,24 @@ public class JbossIntegrationFilter implements Filter {
return null;
}
/**
* Provided so that unit tests can override.
*
* @return a <code>Context</code> that can be used for lookup
*
* @throws NamingException DOCUMENT ME!
*/
protected Context getLookupContext() throws NamingException {
return new InitialContext();
}
/**
* Does nothing. We use IoC container lifecycle services instead.
*
* @param arg0 ignored
*
* @throws ServletException ignored
*/
public void init(FilterConfig arg0) throws ServletException {}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -45,11 +45,11 @@ import javax.security.auth.login.LoginException;
* @version $Id$
*/
public class JbossAcegiLoginModuleTests extends TestCase {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private final String ADAPTER_KEY = "my_key";
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public JbossAcegiLoginModuleTests() {
super();
@ -59,23 +59,22 @@ public class JbossAcegiLoginModuleTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(JbossAcegiLoginModuleTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean()
throws Exception {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-invalid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-invalid.xml");
try {
adapter.initialize(null, null, null, props);
@ -96,8 +95,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
adapter.initialize(null, null, null, props);
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("appContextLocation must be defined",
expected.getMessage());
assertEquals("appContextLocation must be defined", expected.getMessage());
}
props = new Properties();
@ -108,8 +106,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
adapter.initialize(null, null, null, props);
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("appContextLocation must be defined",
expected.getMessage());
assertEquals("appContextLocation must be defined", expected.getMessage());
}
}
@ -117,8 +114,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
try {
adapter.initialize(null, null, null, props);
@ -129,8 +125,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
props = new Properties();
props.put("key", "");
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
try {
adapter.initialize(null, null, null, props);
@ -152,8 +147,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
adapter.initialize(null, null, null, props);
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue("Cannot locate INVALID_PATH".equals(
expected.getMessage()));
assertTrue("Cannot locate INVALID_PATH".equals(expected.getMessage()));
}
}
@ -162,8 +156,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
Subject subject = new Subject();
@ -181,8 +174,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.initialize(null, null, null, props);
assertTrue(true);
}
@ -192,8 +184,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
Subject subject = new Subject();
CallbackHandler callback = new MockCallbackHandler("marissa", "kangaroo");
@ -213,8 +204,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
Subject subject = new Subject();
CallbackHandler callback = new MockCallbackHandler("melissa", "koala");
@ -233,8 +223,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
Subject subject = new Subject();
CallbackHandler callback = new MockCallbackHandler("marissa", "koala");
@ -251,10 +240,8 @@ public class JbossAcegiLoginModuleTests extends TestCase {
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
assertEquals("marissa", castResult.getPrincipal());
assertEquals("koala", castResult.getCredentials());
assertEquals("ROLE_TELLER",
castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR",
castResult.getAuthorities()[1].getAuthority());
assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority());
assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
}
@ -263,8 +250,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
Subject subject = new Subject();
CallbackHandler callback = new MockCallbackHandler("marissa", null);
@ -284,8 +270,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
Subject subject = new Subject();
CallbackHandler callback = new MockCallbackHandler(null, null);
@ -305,8 +290,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
Subject subject = new Subject();
CallbackHandler callback = new MockCallbackHandler(null, "kangaroo");
@ -325,8 +309,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
Properties props = new Properties();
props.put("key", ADAPTER_KEY);
props.put("appContextLocation",
"org/acegisecurity/adapters/adaptertest-valid.xml");
props.put("appContextLocation", "org/acegisecurity/adapters/adaptertest-valid.xml");
Subject subject = new Subject();
CallbackHandler callback = new MockCallbackHandler("marissa", "koala");
@ -342,7 +325,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
assertTrue(roles.isMember(new SimplePrincipal("ROLE_SUPERVISOR")));
}
//~ Inner Classes ==========================================================
//~ Inner Classes ==================================================================================================
private class MockCallbackHandler implements CallbackHandler {
private String password;
@ -357,8 +340,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
super();
}
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
((NameCallback) callbacks[i]).setName(username);
@ -366,8 +348,7 @@ public class JbossAcegiLoginModuleTests extends TestCase {
if (this.password == null) {
((PasswordCallback) callbacks[i]).setPassword(null);
} else {
((PasswordCallback) callbacks[i]).setPassword(password
.toCharArray());
((PasswordCallback) callbacks[i]).setPassword(password.toCharArray());
}
} else {
throw new UnsupportedCallbackException(callbacks[i]);

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -53,7 +53,7 @@ import javax.servlet.ServletResponse;
* @version $Id$
*/
public class JbossIntegrationFilterTests extends TestCase {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public JbossIntegrationFilterTests() {
super();
@ -63,35 +63,55 @@ public class JbossIntegrationFilterTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
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();
}
public static void main(String[] args) {
junit.textui.TestRunner.run(JbossIntegrationFilterTests.class);
}
public void testCorrectOperation() throws Exception {
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key",
"someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")},
null);
private Subject makeIntoSubject(Principal principal) {
Set principals = new HashSet();
principals.add(principal);
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
makeIntoSubject(principal)));
return new Subject(false, principals, new HashSet(), new HashSet());
}
protected void setUp() throws Exception {
super.setUp();
SecurityContextHolder.setContext(new SecurityContextImpl());
}
protected void tearDown() throws Exception {
super.tearDown();
SecurityContextHolder.setContext(new SecurityContextImpl());
}
public void testCorrectOperation() throws Exception {
PrincipalAcegiUserToken principal = new PrincipalAcegiUserToken("key", "someone", "password",
new GrantedAuthority[] {new GrantedAuthorityImpl("SOME_ROLE")}, null);
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(makeIntoSubject(principal)));
MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
filter.doFilter(request, null, chain);
assertEquals(principal,
SecurityContextHolder.getContext().getAuthentication());
assertEquals(principal, SecurityContextHolder.getContext().getAuthentication());
SecurityContextHolder.setContext(new SecurityContextImpl());
}
public void testReturnsNullIfContextReturnsSomethingOtherThanASubject()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
"THIS_IS_NOT_A_SUBJECT"));
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext("THIS_IS_NOT_A_SUBJECT"));
MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
@ -102,8 +122,7 @@ public class JbossIntegrationFilterTests extends TestCase {
public void testReturnsNullIfInitialContextHasNullPrincipal()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
makeIntoSubject(null)));
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(makeIntoSubject(null)));
MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
@ -114,8 +133,7 @@ public class JbossIntegrationFilterTests extends TestCase {
public void testReturnsNullIfInitialContextHasNullSubject()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
null));
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(null));
MockHttpServletRequest request = new MockHttpServletRequest();
MockFilterChain chain = new MockFilterChain();
@ -137,8 +155,8 @@ public class JbossIntegrationFilterTests extends TestCase {
public void testReturnsNullIfPrincipalNotAnAuthenticationImplementation()
throws Exception {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(
makeIntoSubject(new Principal() {
JbossIntegrationFilter filter = new MockJbossIntegrationFilter(new MockInitialContext(makeIntoSubject(
new Principal() {
public String getName() {
return "MockPrincipal";
}
@ -157,32 +175,7 @@ public class JbossIntegrationFilterTests extends TestCase {
assertTrue(filter.getLookupContext() instanceof Context);
}
protected void setUp() throws Exception {
super.setUp();
SecurityContextHolder.setContext(new SecurityContextImpl());
}
protected void tearDown() throws Exception {
super.tearDown();
SecurityContextHolder.setContext(new SecurityContextImpl());
}
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();
}
private Subject makeIntoSubject(Principal principal) {
Set principals = new HashSet();
principals.add(principal);
return new Subject(false, principals, new HashSet(), new HashSet());
}
//~ Inner Classes ==========================================================
//~ Inner Classes ==================================================================================================
private class MockFilterChain implements FilterChain {
public void doFilter(ServletRequest arg0, ServletResponse arg1)

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -25,18 +25,18 @@ import javax.naming.NamingException;
/**
* Mocks a <code>javax.naming.Context</code> and returns an <code>Object</code>
* when queried for address <code>java:comp/env/security/subject</code>.
* Mocks a <code>javax.naming.Context</code> and returns an <code>Object</code> when queried for address
* <code>java:comp/env/security/subject</code>.
*
* @author Ben Alex
* @version $Id$
*/
public class MockInitialContext implements Context {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private Object object;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public MockInitialContext(Object object) {
this.object = object;
@ -46,23 +46,7 @@ public class MockInitialContext implements Context {
super();
}
//~ Methods ================================================================
public Hashtable getEnvironment() throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}
public String getNameInNamespace() throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}
public NameParser getNameParser(String name) throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}
public NameParser getNameParser(Name name) throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}
//~ Methods ========================================================================================================
public Object addToEnvironment(String propName, Object propVal)
throws NamingException {
@ -106,6 +90,22 @@ public class MockInitialContext implements Context {
throw new UnsupportedOperationException("mock method not implemented");
}
public Hashtable getEnvironment() throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}
public String getNameInNamespace() throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}
public NameParser getNameParser(String name) throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}
public NameParser getNameParser(Name name) throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}
public NamingEnumeration list(String name) throws NamingException {
throw new UnsupportedOperationException("mock method not implemented");
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -20,18 +20,18 @@ import javax.naming.NamingException;
/**
* Provides mock of <code>JbossIntegrationFilter</code>, using a lookup
* <code>Context</code> provided in the constructor.
* Provides mock of <code>JbossIntegrationFilter</code>, using a lookup <code>Context</code> provided in the
* constructor.
*
* @author Ben Alex
* @version $Id$
*/
public class MockJbossIntegrationFilter extends JbossIntegrationFilter {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private Context context;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public MockJbossIntegrationFilter(Context context) {
this.context = context;
@ -41,7 +41,7 @@ public class MockJbossIntegrationFilter extends JbossIntegrationFilter {
super();
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
protected Context getLookupContext() throws NamingException {
return this.context;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -18,6 +18,7 @@ package org.acegisecurity.adapters.jetty;
import org.acegisecurity.Authentication;
import org.acegisecurity.AuthenticationException;
import org.acegisecurity.AuthenticationManager;
import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
import org.apache.commons.logging.Log;
@ -33,32 +34,27 @@ import java.util.Map;
/**
* Adapter to enable Jetty to authenticate via the Acegi Security System for
* Spring.
*
* <p>
* Returns a {@link JettyAcegiUserToken} to Jetty's authentication system,
* which is subsequently available via
* <code>HttpServletRequest.getUserPrincipal()</code>.
* </p>
* Adapter to enable Jetty to authenticate via the Acegi Security System for Spring.<p>Returns a {@link
* JettyAcegiUserToken} to Jetty's authentication system, which is subsequently available via
* <code>HttpServletRequest.getUserPrincipal()</code>.</p>
*
* @author Ben Alex
* @version $Id$
*/
public final class JettyAcegiUserRealm implements UserRealm {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(JettyAcegiUserRealm.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private AuthenticationManager authenticationManager;
private String key;
private String realm;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Construct a <code>SpringUserRealm</code>.
*
* @param realm the name of the authentication realm (within Jetty)
@ -68,8 +64,7 @@ public final class JettyAcegiUserRealm implements UserRealm {
*
* @throws IllegalArgumentException DOCUMENT ME!
*/
public JettyAcegiUserRealm(String realm, String providerKey,
String appContextLocation) {
public JettyAcegiUserRealm(String realm, String providerKey, String appContextLocation) {
this.realm = realm;
this.key = providerKey;
@ -82,13 +77,11 @@ public final class JettyAcegiUserRealm implements UserRealm {
}
if ((appContextLocation == null) || "".equals(appContextLocation)) {
throw new IllegalArgumentException(
"appContextLocation must be specified");
throw new IllegalArgumentException("appContextLocation must be specified");
}
if (Thread.currentThread().getContextClassLoader().getResource(appContextLocation) == null) {
throw new IllegalArgumentException("Cannot locate "
+ appContextLocation);
throw new IllegalArgumentException("Cannot locate " + appContextLocation);
}
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(appContextLocation);
@ -107,24 +100,9 @@ public final class JettyAcegiUserRealm implements UserRealm {
throw new IllegalArgumentException("Cannot use default constructor");
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
/**
* Accesses the realm name.
*
* @return the name of the realm as defined when
* <code>SpringUserRealm</code> was created
*/
public String getName() {
return this.realm;
}
public UserPrincipal authenticate(String username, Object password,
HttpRequest httpRequest) {
public UserPrincipal authenticate(String username, Object password, HttpRequest httpRequest) {
if (username == null) {
return null;
}
@ -133,23 +111,20 @@ public final class JettyAcegiUserRealm implements UserRealm {
password = "";
}
Authentication request = new UsernamePasswordAuthenticationToken(username
.toString(), password.toString());
Authentication request = new UsernamePasswordAuthenticationToken(username.toString(), password.toString());
Authentication response = null;
try {
response = authenticationManager.authenticate(request);
} catch (AuthenticationException failed) {
if (logger.isDebugEnabled()) {
logger.debug("Authentication request for user: " + username
+ " failed: " + failed.toString());
logger.debug("Authentication request for user: " + username + " failed: " + failed.toString());
}
return null;
}
return new JettyAcegiUserToken(this.key,
response.getPrincipal().toString(),
return new JettyAcegiUserToken(this.key, response.getPrincipal().toString(),
response.getCredentials().toString(), response.getAuthorities());
}
@ -157,6 +132,19 @@ public final class JettyAcegiUserRealm implements UserRealm {
// No action required
}
public AuthenticationManager getAuthenticationManager() {
return authenticationManager;
}
/**
* Accesses the realm name.
*
* @return the name of the realm as defined when <code>SpringUserRealm</code> was created
*/
public String getName() {
return this.realm;
}
public void logout(UserPrincipal arg0) {
// Not supported
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,6 +16,7 @@
package org.acegisecurity.adapters.jetty;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.adapters.AbstractAdapterAuthenticationToken;
import org.mortbay.http.UserPrincipal;
@ -27,17 +28,15 @@ import org.mortbay.http.UserPrincipal;
* @author Ben Alex
* @version $Id$
*/
public class JettyAcegiUserToken extends AbstractAdapterAuthenticationToken
implements UserPrincipal {
//~ Instance fields ========================================================
public class JettyAcegiUserToken extends AbstractAdapterAuthenticationToken implements UserPrincipal {
//~ Instance fields ================================================================================================
private String password;
private String username;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public JettyAcegiUserToken(String key, String username, String password,
GrantedAuthority[] authorities) {
public JettyAcegiUserToken(String key, String username, String password, GrantedAuthority[] authorities) {
super(key, authorities);
this.username = username;
this.password = password;
@ -47,7 +46,7 @@ public class JettyAcegiUserToken extends AbstractAdapterAuthenticationToken
throw new IllegalArgumentException("Cannot use default constructor");
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public Object getCredentials() {
return this.password;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -27,12 +27,12 @@ import org.mortbay.http.UserPrincipal;
* @version $Id$
*/
public class JettyAcegiUserRealmTests extends TestCase {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private final String ADAPTER_KEY = "my_key";
private final String REALM_NAME = "Acegi Powered Realm";
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public JettyAcegiUserRealmTests() {
super();
@ -42,16 +42,23 @@ public class JettyAcegiUserRealmTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(JettyAcegiUserRealmTests.class);
}
private JettyAcegiUserRealm makeAdapter(String fileName)
throws Exception {
String useFile = "org/acegisecurity/adapters/" + fileName;
return new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, useFile);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean()
throws Exception {
try {
@ -69,16 +76,14 @@ public class JettyAcegiUserRealmTests extends TestCase {
new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, null);
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("appContextLocation must be specified",
expected.getMessage());
assertEquals("appContextLocation must be specified", expected.getMessage());
}
try {
new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, "");
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertEquals("appContextLocation must be specified",
expected.getMessage());
assertEquals("appContextLocation must be specified", expected.getMessage());
}
}
@ -118,8 +123,7 @@ public class JettyAcegiUserRealmTests extends TestCase {
public void testAdapterAbortsWithIncorrectApplicationContextLocation()
throws Exception {
try {
new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY,
"SOME_INVALID_LOCATION");
new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, "SOME_INVALID_LOCATION");
fail("Should have thrown IllegalArgumentException");
} catch (IllegalArgumentException expected) {
assertTrue(expected.getMessage().startsWith("Cannot locate"));
@ -160,10 +164,8 @@ public class JettyAcegiUserRealmTests extends TestCase {
JettyAcegiUserToken castResult = (JettyAcegiUserToken) result;
assertEquals("marissa", castResult.getPrincipal());
assertEquals("koala", castResult.getCredentials());
assertEquals("ROLE_TELLER",
castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR",
castResult.getAuthorities()[1].getAuthority());
assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority());
assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
}
@ -217,29 +219,19 @@ public class JettyAcegiUserRealmTests extends TestCase {
assertEquals(user, adapter.pushRole(user, "SOME_ROLE"));
}
private JettyAcegiUserRealm makeAdapter(String fileName)
throws Exception {
String useFile = "org/acegisecurity/adapters/" + fileName;
return new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, useFile);
}
//~ Inner Classes ==========================================================
//~ Inner Classes ==================================================================================================
private class MockUserPrincipal implements UserPrincipal {
public boolean isAuthenticated() {
throw new UnsupportedOperationException(
"mock method not implemented");
public String getName() {
throw new UnsupportedOperationException("mock method not implemented");
}
public String getName() {
throw new UnsupportedOperationException(
"mock method not implemented");
public boolean isAuthenticated() {
throw new UnsupportedOperationException("mock method not implemented");
}
public boolean isUserInRole(String arg0) {
throw new UnsupportedOperationException(
"mock method not implemented");
throw new UnsupportedOperationException("mock method not implemented");
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -28,7 +28,7 @@ import org.acegisecurity.GrantedAuthorityImpl;
* @version $Id$
*/
public class JettyAcegiUserTokenTests extends TestCase {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public JettyAcegiUserTokenTests() {
super();
@ -38,21 +38,19 @@ public class JettyAcegiUserTokenTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(JettyAcegiUserTokenTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testGetters() throws Exception {
JettyAcegiUserToken token = new JettyAcegiUserToken("my_password",
"Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
"ROLE_TWO")});
JettyAcegiUserToken token = new JettyAcegiUserToken("my_password", "Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")});
assertEquals("Test", token.getPrincipal());
assertEquals("Password", token.getCredentials());
assertEquals("my_password".hashCode(), token.getKeyHash());

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -41,64 +41,34 @@ import javax.servlet.http.HttpServletResponse;
/**
* Adapter to enable Resin to authenticate via the Acegi Security System for
* Spring.
*
* <p>
* Returns a {@link PrincipalAcegiUserToken} to Resin's authentication system,
* which is subsequently available via
* <code>HttpServletRequest.getUserPrincipal()</code>.
* </p>
* Adapter to enable Resin to authenticate via the Acegi Security System for Spring.<p>Returns a {@link
* PrincipalAcegiUserToken} to Resin's authentication system, which is subsequently available via
* <code>HttpServletRequest.getUserPrincipal()</code>.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class ResinAcegiAuthenticator extends AbstractAuthenticator {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(ResinAcegiAuthenticator.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private AuthenticationManager authenticationManager;
private String appContextLocation;
private String key;
//~ Methods ================================================================
public void setAppContextLocation(String appContextLocation) {
this.appContextLocation = appContextLocation;
}
//~ Methods ========================================================================================================
public String getAppContextLocation() {
return appContextLocation;
}
public void setKey(String key) {
this.key = key;
}
public String getKey() {
return key;
}
public boolean isUserInRole(HttpServletRequest request,
HttpServletResponse response, ServletContext application,
Principal principal, String role) {
if (!(principal instanceof PrincipalAcegiUserToken)) {
if (logger.isWarnEnabled()) {
logger.warn(
"Expected passed principal to be of type PrincipalAcegiUserToken");
}
return false;
}
PrincipalAcegiUserToken test = (PrincipalAcegiUserToken) principal;
return test.isUserInRole(role);
}
public void init() throws ServletException {
super.init();
@ -118,8 +88,7 @@ public class ResinAcegiAuthenticator extends AbstractAuthenticator {
Map beans = ctx.getBeansOfType(AuthenticationManager.class, true, true);
if (beans.size() == 0) {
throw new ServletException(
"Bean context must contain at least one bean of type AuthenticationManager");
throw new ServletException("Bean context must contain at least one bean of type AuthenticationManager");
}
String beanName = (String) beans.keySet().iterator().next();
@ -127,6 +96,21 @@ public class ResinAcegiAuthenticator extends AbstractAuthenticator {
logger.info("ResinAcegiAuthenticator Started");
}
public boolean isUserInRole(HttpServletRequest request, HttpServletResponse response, ServletContext application,
Principal principal, String role) {
if (!(principal instanceof PrincipalAcegiUserToken)) {
if (logger.isWarnEnabled()) {
logger.warn("Expected passed principal to be of type PrincipalAcegiUserToken");
}
return false;
}
PrincipalAcegiUserToken test = (PrincipalAcegiUserToken) principal;
return test.isUserInRole(role);
}
protected Principal loginImpl(String username, String credentials) {
if (username == null) {
return null;
@ -136,30 +120,33 @@ public class ResinAcegiAuthenticator extends AbstractAuthenticator {
credentials = "";
}
Authentication request = new UsernamePasswordAuthenticationToken(username,
credentials);
Authentication request = new UsernamePasswordAuthenticationToken(username, credentials);
Authentication response = null;
try {
response = authenticationManager.authenticate(request);
} catch (AuthenticationException failed) {
if (logger.isDebugEnabled()) {
logger.debug("Authentication request for user: " + username
+ " failed: " + failed.toString());
logger.debug("Authentication request for user: " + username + " failed: " + failed.toString());
}
return null;
}
return new PrincipalAcegiUserToken(this.key,
response.getPrincipal().toString(),
response.getCredentials().toString(), response.getAuthorities(),
response.getPrincipal());
return new PrincipalAcegiUserToken(this.key, response.getPrincipal().toString(),
response.getCredentials().toString(), response.getAuthorities(), response.getPrincipal());
}
protected Principal loginImpl(HttpServletRequest request,
HttpServletResponse response, ServletContext application,
protected Principal loginImpl(HttpServletRequest request, HttpServletResponse response, ServletContext application,
String userName, String password) throws ServletException {
return loginImpl(userName, password);
}
public void setAppContextLocation(String appContextLocation) {
this.appContextLocation = appContextLocation;
}
public void setKey(String key) {
this.key = key;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -34,11 +34,11 @@ import javax.servlet.ServletException;
* @version $Id$
*/
public class ResinAcegiAuthenticatorTests extends TestCase {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private final String ADAPTER_KEY = "my_key";
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public ResinAcegiAuthenticatorTests() {
super();
@ -48,21 +48,20 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(ResinAcegiAuthenticatorTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean()
throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-invalid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-invalid.xml");
adapter.setKey(ADAPTER_KEY);
try {
@ -83,8 +82,7 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
adapter.init();
fail("Should have thrown ServletException");
} catch (ServletException expected) {
assertEquals("appContextLocation must be defined",
expected.getMessage());
assertEquals("appContextLocation must be defined", expected.getMessage());
}
adapter.setAppContextLocation("");
@ -93,15 +91,13 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
adapter.init();
fail("Should have thrown ServletException");
} catch (ServletException expected) {
assertEquals("appContextLocation must be defined",
expected.getMessage());
assertEquals("appContextLocation must be defined", expected.getMessage());
}
}
public void testAdapterAbortsIfNoKeySpecified() throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
try {
adapter.init();
@ -136,8 +132,7 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
public void testAdapterStartsUpSuccess() throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
assertTrue(true);
@ -146,8 +141,7 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
public void testAuthenticationFailsForIncorrectPassword()
throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
assertEquals(null, adapter.loginImpl("marissa", "kangaroo"));
@ -156,8 +150,7 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
public void testAuthenticationFailsForIncorrectUserName()
throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
assertEquals(null, adapter.loginImpl("melissa", "koala"));
@ -165,8 +158,7 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
public void testAuthenticationSuccess() throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
@ -179,23 +171,19 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
assertEquals("marissa", castResult.getPrincipal());
assertEquals("koala", castResult.getCredentials());
assertEquals("ROLE_TELLER",
castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR",
castResult.getAuthorities()[1].getAuthority());
assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority());
assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
}
public void testAuthenticationSuccessUsingAlternateMethod()
throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
Principal result = adapter.loginImpl(null, null, null, "marissa",
"koala");
Principal result = adapter.loginImpl(null, null, null, "marissa", "koala");
if (!(result instanceof PrincipalAcegiUserToken)) {
fail("Should have returned PrincipalAcegiUserToken");
@ -204,18 +192,15 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
assertEquals("marissa", castResult.getPrincipal());
assertEquals("koala", castResult.getCredentials());
assertEquals("ROLE_TELLER",
castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR",
castResult.getAuthorities()[1].getAuthority());
assertEquals("ROLE_TELLER", castResult.getAuthorities()[0].getAuthority());
assertEquals("ROLE_SUPERVISOR", castResult.getAuthorities()[1].getAuthority());
assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
}
public void testAuthenticationWithNullPasswordHandledGracefully()
throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
assertEquals(null, adapter.loginImpl("marissa", null));
@ -224,8 +209,7 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
public void testAuthenticationWithNullUserNameHandledGracefully()
throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
assertEquals(null, adapter.loginImpl(null, "koala"));
@ -233,18 +217,15 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
public void testGetters() throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
assertEquals(ADAPTER_KEY, adapter.getKey());
assertEquals("org/acegisecurity/adapters/adaptertest-valid.xml",
adapter.getAppContextLocation());
assertEquals("org/acegisecurity/adapters/adaptertest-valid.xml", adapter.getAppContextLocation());
}
public void testHasRoleWithANullPrincipalFails() throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
assertTrue(!adapter.isUserInRole(null, null, null, null, "ROLE_ONE"));
@ -253,8 +234,7 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
public void testHasRoleWithAPrincipalTheAdapterDidNotCreateFails()
throws Exception {
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
assertTrue(!adapter.isUserInRole(null, null, null,
@ -267,18 +247,15 @@ public class ResinAcegiAuthenticatorTests extends TestCase {
public void testHasRoleWithPrincipalAcegiUserToken()
throws Exception {
PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("KEY",
"Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
"ROLE_TWO")}, null);
PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("KEY", "Test", "Password",
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl("ROLE_TWO")},
null);
ResinAcegiAuthenticator adapter = new ResinAcegiAuthenticator();
adapter.setAppContextLocation(
"org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setAppContextLocation("org/acegisecurity/adapters/adaptertest-valid.xml");
adapter.setKey(ADAPTER_KEY);
adapter.init();
assertTrue(adapter.isUserInRole(null, null, null, token, "ROLE_ONE"));
assertTrue(adapter.isUserInRole(null, null, null, token, "ROLE_ONE"));
assertTrue(!adapter.isUserInRole(null, null, null, token,
"ROLE_WE_DO_NOT_HAVE"));
assertTrue(!adapter.isUserInRole(null, null, null, token, "ROLE_WE_DO_NOT_HAVE"));
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -47,9 +47,7 @@ import java.lang.annotation.Target;
@Inherited
@Documented
public @interface Secured {
//~ Methods ================================================================
/**
/**
* Returns the list of security configuration attributes.
* (i.e. ROLE_USER, ROLE_ADMIN etc.)
* @return String[] The secure method attributes

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -12,54 +12,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.acegisecurity.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
package org.acegisecurity.annotation;
import org.acegisecurity.SecurityConfig;
import org.springframework.metadata.Attributes;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* Java 5 Annotation <code>Attributes</code> metadata implementation used for
* secure method interception.
*
* <p>This <code>Attributes</code> implementation will return security
* configuration for classes described using the <code>Secured</code> Java 5
* annotation.
*
* <p>The <code>SecurityAnnotationAttributes</code> implementation can be used
* to configure a <code>MethodDefinitionAttributes</code> and
* <code>MethodSecurityInterceptor</code> bean definition (see below).
*
* <p>For example:
* <pre>
* &lt;bean id="attributes"
* class="org.acegisecurity.annotation.SecurityAnnotationAttributes"/>
*
* &lt;bean id="objectDefinitionSource"
* class="org.acegisecurity.intercept.method.MethodDefinitionAttributes">
* &lt;property name="attributes">
* &lt;ref local="attributes"/>
* &lt;/property>
* &lt;/bean>
*
* &lt;bean id="securityInterceptor"
* class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
* . . .
* &lt;property name="objectDefinitionSource">
* &lt;ref local="objectDefinitionSource"/>
* &lt;/property>
* &lt;/bean>
* </pre>
*
* <p>These security annotations are similiar to the Commons Attributes
* approach, however they are using Java 5 language-level metadata support.
* Java 5 Annotation <code>Attributes</code> metadata implementation used for secure method interception.<p>This
* <code>Attributes</code> implementation will return security configuration for classes described using the
* <code>Secured</code> Java 5 annotation.</p>
* <p>The <code>SecurityAnnotationAttributes</code> implementation can be used to configure a
* <code>MethodDefinitionAttributes</code> and <code>MethodSecurityInterceptor</code> bean definition (see below).</p>
* <p>For example:<pre>&lt;bean id="attributes"
* class="org.acegisecurity.annotation.SecurityAnnotationAttributes"/>&lt;bean id="objectDefinitionSource"
* class="org.acegisecurity.intercept.method.MethodDefinitionAttributes"> &lt;property name="attributes">
* &lt;ref local="attributes"/> &lt;/property>&lt;/bean>&lt;bean id="securityInterceptor"
* class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"> . . .
* &lt;property name="objectDefinitionSource"> &lt;ref local="objectDefinitionSource"/> &lt;/property>
* &lt;/bean></pre></p>
* <p>These security annotations are similiar to the Commons Attributes approach, however they are using Java 5
* language-level metadata support.</p>
*
* @author Mark St.Godard
* @version $Id$
@ -67,66 +50,77 @@ import org.springframework.metadata.Attributes;
* @see org.acegisecurity.annotation.Secured
*/
public class SecurityAnnotationAttributes implements Attributes {
//~ Methods ========================================================================================================
/**
* Get the <code>Secured</code> attributes for a given target class.
* @param method The target method
* @return Collection of <code>SecurityConfig</code>
* @see Attributes#getAttributes
*/
public Collection getAttributes(Class target) {
/**
* Get the <code>Secured</code> attributes for a given target class.
*
* @param target The target method
*
* @return Collection of <code>SecurityConfig</code>
*
* @see Attributes#getAttributes
*/
public Collection getAttributes(Class target) {
Set<SecurityConfig> attributes = new HashSet<SecurityConfig>();
Set<SecurityConfig> attributes = new HashSet<SecurityConfig>();
for (Annotation annotation : target.getAnnotations()) {
// check for Secured annotations
if (annotation instanceof Secured) {
Secured attr = (Secured) annotation;
for (Annotation annotation : target.getAnnotations()) {
// check for Secured annotations
if (annotation instanceof Secured) {
Secured attr = (Secured) annotation;
for (String auth : attr.value()) {
attributes.add(new SecurityConfig(auth));
}
break;
}
}
return attributes;
}
for (String auth : attr.value()) {
attributes.add(new SecurityConfig(auth));
}
public Collection getAttributes(Class clazz, Class filter) {
throw new UnsupportedOperationException("Unsupported operation");
}
break;
}
}
/**
* Get the <code>Secured</code> attributes for a given target method.
* @param method The target method
* @return Collection of <code>SecurityConfig</code>
* @see Attributes#getAttributes
*/
public Collection getAttributes(Method method) {
Set<SecurityConfig> attributes = new HashSet<SecurityConfig>();
return attributes;
}
for (Annotation annotation : method.getAnnotations()) {
// check for Secured annotations
if (annotation instanceof Secured) {
Secured attr = (Secured) annotation;
for (String auth : attr.value()) {
attributes.add(new SecurityConfig(auth));
}
break;
}
}
return attributes;
}
public Collection getAttributes(Class clazz, Class filter) {
throw new UnsupportedOperationException("Unsupported operation");
}
public Collection getAttributes(Method method, Class clazz) {
throw new UnsupportedOperationException("Unsupported operation");
}
/**
* Get the <code>Secured</code> attributes for a given target method.
*
* @param method The target method
*
* @return Collection of <code>SecurityConfig</code>
*
* @see Attributes#getAttributes
*/
public Collection getAttributes(Method method) {
Set<SecurityConfig> attributes = new HashSet<SecurityConfig>();
public Collection getAttributes(Field field) {
throw new UnsupportedOperationException("Unsupported operation");
}
for (Annotation annotation : method.getAnnotations()) {
// check for Secured annotations
if (annotation instanceof Secured) {
Secured attr = (Secured) annotation;
public Collection getAttributes(Field field, Class clazz) {
throw new UnsupportedOperationException("Unsupported operation");
}
for (String auth : attr.value()) {
attributes.add(new SecurityConfig(auth));
}
break;
}
}
return attributes;
}
public Collection getAttributes(Method method, Class clazz) {
throw new UnsupportedOperationException("Unsupported operation");
}
public Collection getAttributes(Field field) {
throw new UnsupportedOperationException("Unsupported operation");
}
public Collection getAttributes(Field field, Class clazz) {
throw new UnsupportedOperationException("Unsupported operation");
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -25,18 +25,18 @@ import org.springframework.util.Assert;
* @version $Id$
*/
public class Entity {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
String info;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public Entity(String info) {
Assert.hasText(info, "Some information must be given!");
this.info = info;
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public String getInfo() {
return info;

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -22,23 +22,23 @@ package org.acegisecurity;
* @version $Id$
*/
public class Organisation extends Entity {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private boolean active = true;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public Organisation(String name) {
super(name);
}
//~ Methods ================================================================
public boolean isActive() {
return this.active;
}
//~ Methods ========================================================================================================
void deactive() {
this.active = true;
}
public boolean isActive() {
return this.active;
}
}

View File

@ -1,5 +1,28 @@
/* Copyright 2004, 2005, 2006 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 org.acegisecurity;
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision$
*/
public interface OrganisationService extends Service<Organisation> {
public void deactive(Organisation org);
//~ Methods ========================================================================================================
public void deactive(Organisation org);
}

View File

@ -1,9 +1,30 @@
/* Copyright 2004, 2005, 2006 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 org.acegisecurity;
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision$
*/
public class OrganisationServiceImpl extends ServiceImpl<Organisation> implements OrganisationService {
//~ Methods ========================================================================================================
public void deactive(Organisation org) {
org.deactive();
}
public void deactive(Organisation org) {
org.deactive();
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -22,23 +22,23 @@ package org.acegisecurity;
* @version $Id$
*/
public class Person extends Entity {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private boolean active = true;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public Person(String name) {
super(name);
}
//~ Methods ================================================================
public boolean isActive() {
return this.active;
}
//~ Methods ========================================================================================================
void deactive() {
this.active = true;
}
public boolean isActive() {
return this.active;
}
}

View File

@ -1,5 +1,28 @@
/* Copyright 2004, 2005, 2006 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 org.acegisecurity;
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision$
*/
public interface PersonService extends Service<Person> {
public void deactive(Person person);
//~ Methods ========================================================================================================
public void deactive(Person person);
}

View File

@ -1,9 +1,30 @@
/* Copyright 2004, 2005, 2006 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 org.acegisecurity;
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision$
*/
public class PersonServiceImpl extends ServiceImpl<Person> implements PersonService {
//~ Methods ========================================================================================================
public void deactive(Person person) {
person.deactive();
}
public void deactive(Person person) {
person.deactive();
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -25,7 +25,7 @@ import java.util.Collection;
* @version $Id$
*/
public interface Service<E extends Entity> {
//~ Methods ================================================================
//~ Methods ========================================================================================================
public int countElements(Collection<E> ids);

View File

@ -1,23 +1,47 @@
/* Copyright 2004, 2005, 2006 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 org.acegisecurity;
import java.util.Collection;
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision$
*
* @param <E> DOCUMENT ME!
*/
public class ServiceImpl<E extends Entity> implements Service<E> {
//~ Methods ========================================================================================================
public int countElements(Collection<E> ids) {
return 0;
}
public int countElements(Collection<E> ids) {
return 0;
}
public void makeLowerCase(E input) {
input.makeLowercase();
}
public void makeLowerCase(E input) {
input.makeLowercase();
}
public void makeUpperCase(E input) {
input.makeUppercase();
}
public void publicMakeLowerCase(E input) {
input.makeUppercase();
}
public void makeUpperCase(E input) {
input.makeUppercase();
}
public void publicMakeLowerCase(E input) {
input.makeUppercase();
}
}

View File

@ -1,18 +1,39 @@
/* Copyright 2004, 2005, 2006 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 org.acegisecurity.annotation;
@Secured ({"ROLE_USER"})
/**
* DOCUMENT ME!
*
* @author $author$
* @version $Revision$
*/
@Secured({"ROLE_USER"})
public interface BusinessService {
@Secured ({"ROLE_USER"})
public void someUserMethod1();
//~ Methods ========================================================================================================
@Secured ({"ROLE_USER"})
public void someUserMethod2();
@Secured ({"ROLE_USER","ROLE_ADMIN"})
public void someUserAndAdminMethod();
@Secured ({"ROLE_ADMIN"})
public void someAdminMethod();
@Secured({"ROLE_ADMIN"})
public void someAdminMethod();
@Secured({"ROLE_USER", "ROLE_ADMIN"})
public void someUserAndAdminMethod();
@Secured({"ROLE_USER"})
public void someUserMethod1();
@Secured({"ROLE_USER"})
public void someUserMethod2();
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -15,15 +15,17 @@
package org.acegisecurity.annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import junit.framework.TestCase;
import org.acegisecurity.SecurityConfig;
import org.springframework.metadata.Attributes;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
/**
* Tests for {@link org.acegisecurity.annotation.SecurityAnnotationAttributes}
@ -32,17 +34,22 @@ import org.springframework.metadata.Attributes;
* @version $Revision$
*/
public class SecurityAnnotationAttributesTests extends TestCase {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private Attributes attributes;
//~ Methods ================================================================
//~ Methods ========================================================================================================
protected void setUp() throws Exception {
// create the Annotations impl
this.attributes = new SecurityAnnotationAttributes();
}
public void testGetAttributesClass() {
Collection attrs = this.attributes.getAttributes(BusinessService.class);
assertNotNull(attrs);
// expect 1 annotation
assertTrue(attrs.size() == 1);
@ -53,90 +60,76 @@ public class SecurityAnnotationAttributesTests extends TestCase {
}
public void testGetAttributesClassClass() {
try{
this.attributes.getAttributes(BusinessService.class, null);
fail("Unsupported method should have thrown an exception!");
}catch(UnsupportedOperationException expected){
}
try {
this.attributes.getAttributes(BusinessService.class, null);
fail("Unsupported method should have thrown an exception!");
} catch (UnsupportedOperationException expected) {}
}
public void testGetAttributesField() {
try{
Field field = null;
this.attributes.getAttributes(field);
fail("Unsupported method should have thrown an exception!");
}catch(UnsupportedOperationException expected){
}
try {
Field field = null;
this.attributes.getAttributes(field);
fail("Unsupported method should have thrown an exception!");
} catch (UnsupportedOperationException expected) {}
}
public void testGetAttributesFieldClass() {
try{
Field field = null;
this.attributes.getAttributes(field, null);
fail("Unsupported method should have thrown an exception!");
}catch(UnsupportedOperationException expected){
}
try {
Field field = null;
this.attributes.getAttributes(field, null);
fail("Unsupported method should have thrown an exception!");
} catch (UnsupportedOperationException expected) {}
}
public void testGetAttributesMethod() {
Method method = null;
try{
method = BusinessService.class.getMethod("someUserAndAdminMethod",new Class[] {});
}catch(NoSuchMethodException unexpected){
fail("Should be a method called 'someUserAndAdminMethod' on class!");
}
Method method = null;
try {
method = BusinessService.class.getMethod("someUserAndAdminMethod", new Class[] {});
} catch (NoSuchMethodException unexpected) {
fail("Should be a method called 'someUserAndAdminMethod' on class!");
}
Collection attrs = this.attributes.getAttributes(method);
assertNotNull(attrs);
// expect 2 attributes
assertTrue(attrs.size() == 2);
boolean user = false;
boolean admin = false;
// should have 2 SecurityConfigs
for(Object obj: attrs){
assertTrue(obj instanceof SecurityConfig);
SecurityConfig sc = (SecurityConfig)obj;
if(sc.getAttribute().equals("ROLE_USER")){
user = true;
}else if(sc.getAttribute().equals("ROLE_ADMIN")){
admin = true;
}
for (Object obj : attrs) {
assertTrue(obj instanceof SecurityConfig);
SecurityConfig sc = (SecurityConfig) obj;
if (sc.getAttribute().equals("ROLE_USER")) {
user = true;
} else if (sc.getAttribute().equals("ROLE_ADMIN")) {
admin = true;
}
}
// expect to have ROLE_USER and ROLE_ADMIN
assertTrue(user && admin);
}
public void testGetAttributesMethodClass() {
Method method = null;
try{
method = BusinessService.class.getMethod("someUserAndAdminMethod",new Class[] {});
}catch(NoSuchMethodException unexpected){
fail("Should be a method called 'someUserAndAdminMethod' on class!");
}
try{
this.attributes.getAttributes(method,null);
fail("Unsupported method should have thrown an exception!");
}catch(UnsupportedOperationException expected){
}
}
Method method = null;
protected void setUp() throws Exception {
// create the Annotations impl
this.attributes = new SecurityAnnotationAttributes();
try {
method = BusinessService.class.getMethod("someUserAndAdminMethod", new Class[] {});
} catch (NoSuchMethodException unexpected) {
fail("Should be a method called 'someUserAndAdminMethod' on class!");
}
try {
this.attributes.getAttributes(method, null);
fail("Unsupported method should have thrown an exception!");
} catch (UnsupportedOperationException expected) {}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -15,9 +15,6 @@
package org.acegisecurity.intercept.method;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import junit.framework.TestCase;
import org.acegisecurity.ConfigAttributeDefinition;
@ -28,18 +25,21 @@ import org.acegisecurity.PersonServiceImpl;
import org.acegisecurity.SecurityConfig;
import org.acegisecurity.Service;
import org.acegisecurity.ServiceImpl;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
/**
* Extra tests to demonstrate generics behaviour with
* <code>MethodDefinitionMap</code>.
* Extra tests to demonstrate generics behaviour with <code>MethodDefinitionMap</code>.
*
* @author Ben Alex
* @version $Id$
*/
public class MethodDefinitionSourceEditorTigerTests extends TestCase {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public MethodDefinitionSourceEditorTigerTests() {
super();
@ -49,16 +49,16 @@ public class MethodDefinitionSourceEditorTigerTests extends TestCase {
super(arg0);
}
//~ Methods ================================================================
public final void setUp() throws Exception {
super.setUp();
}
//~ Methods ========================================================================================================
public static void main(String[] args) {
junit.textui.TestRunner.run(MethodDefinitionSourceEditorTigerTests.class);
}
public final void setUp() throws Exception {
super.setUp();
}
public void testConcreteClassInvocationsAlsoReturnDefinitionsAgainstInterface()
throws Exception {
MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
@ -68,21 +68,17 @@ public class MethodDefinitionSourceEditorTigerTests extends TestCase {
MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue();
assertEquals(3, map.getMethodMapSize());
ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(
Service.class, "makeLowerCase", new Class[] {Entity.class}));
ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(Service.class,
"makeLowerCase", new Class[] {Entity.class}));
ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition();
expectedMakeLower.addConfigAttribute(new SecurityConfig(
"ROLE_FROM_INTERFACE"));
expectedMakeLower.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE"));
assertEquals(expectedMakeLower, returnedMakeLower);
ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(
ServiceImpl.class, "makeUpperCase",
new Class[] {Entity.class}));
ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(ServiceImpl.class,
"makeUpperCase", new Class[] {Entity.class}));
ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition();
expectedMakeUpper.addConfigAttribute(new SecurityConfig(
"ROLE_FROM_IMPLEMENTATION"));
expectedMakeUpper.addConfigAttribute(new SecurityConfig(
"ROLE_FROM_INTERFACE"));
expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_IMPLEMENTATION"));
expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE"));
assertEquals(expectedMakeUpper, returnedMakeUpper);
}
@ -95,49 +91,41 @@ public class MethodDefinitionSourceEditorTigerTests extends TestCase {
MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue();
assertEquals(3, map.getMethodMapSize());
ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(
PersonService.class, "makeLowerCase",
new Class[] {Entity.class}));
ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(PersonService.class,
"makeLowerCase", new Class[] {Entity.class}));
ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition();
expectedMakeLower.addConfigAttribute(new SecurityConfig(
"ROLE_FROM_INTERFACE"));
expectedMakeLower.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE"));
assertEquals(expectedMakeLower, returnedMakeLower);
ConfigAttributeDefinition returnedMakeLower2 = map.getAttributes(new MockMethodInvocation(
OrganisationService.class, "makeLowerCase",
new Class[] {Entity.class}));
OrganisationService.class, "makeLowerCase", new Class[] {Entity.class}));
ConfigAttributeDefinition expectedMakeLower2 = new ConfigAttributeDefinition();
expectedMakeLower2.addConfigAttribute(new SecurityConfig(
"ROLE_FROM_INTERFACE"));
expectedMakeLower2.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE"));
assertEquals(expectedMakeLower2, returnedMakeLower2);
ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(
PersonServiceImpl.class, "makeUpperCase",
new Class[] {Entity.class}));
PersonServiceImpl.class, "makeUpperCase", new Class[] {Entity.class}));
ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition();
expectedMakeUpper.addConfigAttribute(new SecurityConfig(
"ROLE_FROM_IMPLEMENTATION"));
expectedMakeUpper.addConfigAttribute(new SecurityConfig(
"ROLE_FROM_INTERFACE"));
expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_IMPLEMENTATION"));
expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_FROM_INTERFACE"));
assertEquals(expectedMakeUpper, returnedMakeUpper);
}
//~ Inner Classes ==========================================================
//~ Inner Classes ==================================================================================================
private class MockMethodInvocation implements MethodInvocation {
Method method;
public MockMethodInvocation(Class clazz, String methodName,
Class[] parameterTypes) throws NoSuchMethodException {
System.out.println(clazz + " " + methodName + " "
+ parameterTypes[0]);
method = clazz.getMethod(methodName, parameterTypes);
}
private MockMethodInvocation() {
super();
}
public MockMethodInvocation(Class clazz, String methodName, Class[] parameterTypes)
throws NoSuchMethodException {
System.out.println(clazz + " " + methodName + " " + parameterTypes[0]);
method = clazz.getMethod(methodName, parameterTypes);
}
public Object[] getArguments() {
return null;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,27 +17,21 @@ package org.acegisecurity;
import org.acegisecurity.providers.AbstractAuthenticationToken;
/**
* An abstract implementation of the {@link AuthenticationManager}.
*
* @author Wesley Hall
* @version $Id$
*/
public abstract class AbstractAuthenticationManager
implements AuthenticationManager {
//~ Methods ================================================================
public abstract class AbstractAuthenticationManager implements AuthenticationManager {
//~ Methods ========================================================================================================
/**
* <p>
* An implementation of the <code>authenticate</code> method that calls the
* abstract method <code>doAuthenticatation</code> to do its work.
* </p>
*
* <p>
* If doAuthenticate throws an <code>AuthenticationException</code> then
* the exception is populated with the failed <code>Authentication</code>
* object that failed.
* </p>
* <p>An implementation of the <code>authenticate</code> method that calls the abstract method
* <code>doAuthenticatation</code> to do its work.</p>
* <p>If doAuthenticate throws an <code>AuthenticationException</code> then the exception is populated
* with the failed <code>Authentication</code> object that failed.</p>
*
* @param authRequest the authentication request object
*
@ -59,32 +53,24 @@ public abstract class AbstractAuthenticationManager
}
/**
* Copies the authentication details from a source Authentication object
* to a destination one, provided the latter does not already have one
* set.
* Copies the authentication details from a source Authentication object to a destination one, provided the
* latter does not already have one set.
*
* @param source source authentication
* @param dest the destination authentication object
*/
private void copyDetails(Authentication source, Authentication dest) {
if((dest instanceof AbstractAuthenticationToken)
&& dest.getDetails() == null) {
AbstractAuthenticationToken token = (AbstractAuthenticationToken)dest;
if ((dest instanceof AbstractAuthenticationToken) && (dest.getDetails() == null)) {
AbstractAuthenticationToken token = (AbstractAuthenticationToken) dest;
token.setDetails(source.getDetails());
token.setDetails(source.getDetails());
}
}
/**
* <p>
* Concrete implementations of this class override this method to provide
* the authentication service.
* </p>
*
* <p>
* The contract for this method is documented in the {@link
* AuthenticationManager#authenticate(org.acegisecurity.Authentication)}.
* </p>
* <p>Concrete implementations of this class override this method to provide the authentication service.</p>
* <p>The contract for this method is documented in the {@link
* AuthenticationManager#authenticate(org.acegisecurity.Authentication)}.</p>
*
* @param authentication the authentication request object
*
@ -92,6 +78,6 @@ public abstract class AbstractAuthenticationManager
*
* @throws AuthenticationException if authentication fails
*/
protected abstract Authentication doAuthentication(
Authentication authentication) throws AuthenticationException;
protected abstract Authentication doAuthentication(Authentication authentication)
throws AuthenticationException;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -22,54 +22,44 @@ package org.acegisecurity;
* @version $Id$
*/
public interface AccessDecisionManager {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Resolves an access control decision for the passed parameters.
*
* @param authentication the caller invoking the method
* @param object the secured object being called
* @param config the configuration attributes associated with the secured
* object being invoked
* @param config the configuration attributes associated with the secured object being invoked
*
* @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
* @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)
public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
throws AccessDeniedException, InsufficientAuthenticationException;
/**
* Indicates whether this <code>AccessDecisionManager</code> is able to
* process authorization requests presented with the passed
* <code>ConfigAttribute</code>.
*
* <p>
* This allows the <code>AbstractSecurityInterceptor</code> to check every
* configuration attribute can be consumed by the configured
* <code>AccessDecisionManager</code> and/or <code>RunAsManager</code>
* and/or <code>AfterInvocationManager</code>.
* </p>
* Indicates whether this <code>AccessDecisionManager</code> is able to process authorization requests
* presented with the passed <code>ConfigAttribute</code>.<p>This allows the
* <code>AbstractSecurityInterceptor</code> to check every configuration attribute can be consumed by the
* configured <code>AccessDecisionManager</code> and/or <code>RunAsManager</code> and/or
* <code>AfterInvocationManager</code>.</p>
*
* @param attribute a configuration attribute that has been configured
* against the <code>AbstractSecurityInterceptor</code>
* @param attribute a configuration attribute that has been configured against the
* <code>AbstractSecurityInterceptor</code>
*
* @return true if this <code>AccessDecisionManager</code> can support the
* passed configuration attribute
* @return true if this <code>AccessDecisionManager</code> can support the passed configuration attribute
*/
public boolean supports(ConfigAttribute attribute);
/**
* Indicates whether the <code>AccessDecisionManager</code> implementation
* is able to provide access control decisions for the indicated secured
* object type.
* Indicates whether the <code>AccessDecisionManager</code> implementation is able to provide access
* control decisions for the indicated secured object type.
*
* @param clazz the class that is being queried
*
* @return <code>true</code> if the implementation can process the
* indicated class
* @return <code>true</code> if the implementation can process the indicated class
*/
public boolean supports(Class clazz);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,16 +16,15 @@
package org.acegisecurity;
/**
* Thrown if an {@link Authentication} object does not hold a required
* authority.
* Thrown if an {@link Authentication} object does not hold a required authority.
*
* @author Ben Alex
* @version $Id$
*/
public class AccessDeniedException extends AcegiSecurityException {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs an <code>AccessDeniedException</code> with the specified
* message.
*
@ -35,7 +34,7 @@ public class AccessDeniedException extends AcegiSecurityException {
super(msg);
}
/**
/**
* Constructs an <code>AccessDeniedException</code> with the specified
* message and root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,17 +16,16 @@
package org.acegisecurity;
/**
* Thrown if an authentication request is rejected because the account has
* expired. Makes no assertion as to whether or not the credentials were
* valid.
* Thrown if an authentication request is rejected because the account has expired. Makes no assertion as to
* whether or not the credentials were valid.
*
* @author Ben Alex
* @version $Id$
*/
public class AccountExpiredException extends AuthenticationException {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs a <code>AccountExpiredException</code> with the specified
* message.
*
@ -36,7 +35,7 @@ public class AccountExpiredException extends AuthenticationException {
super(msg);
}
/**
/**
* Constructs a <code>AccountExpiredException</code> with the specified
* message and root cause.
*

View File

@ -20,27 +20,22 @@ import org.springframework.context.support.ResourceBundleMessageSource;
/**
* The default <code>MessageSource</code> used by Acegi Security.
*
* <p>
* All Acegi Security classes requiring messge localization will by default use
* this class. However, all such classes will also implement
* <code>MessageSourceAware</code> so that the application context can inject
* an alternative message source. Therefore this class is only used when the
* deployment environment has not specified an alternative message source.
* </p>
* The default <code>MessageSource</code> used by Acegi Security.<p>All Acegi Security classes requiring messge
* localization will by default use this class. However, all such classes will also implement
* <code>MessageSourceAware</code> so that the application context can inject an alternative message source. Therefore
* this class is only used when the deployment environment has not specified an alternative message source.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class AcegiMessageSource extends ResourceBundleMessageSource {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public AcegiMessageSource() {
setBasename("org.acegisecurity.messages");
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public static MessageSourceAccessor getAccessor() {
return new MessageSourceAccessor(new AcegiMessageSource());

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,21 +19,16 @@ import org.springframework.core.NestedRuntimeException;
/**
* Abstract superclass for all exceptions thrown in the security package and
* subpackages.
*
* <p>
* Note that this is a runtime (unchecked) exception. Security exceptions are
* usually fatal; there is no reason for them to be checked.
* </p>
* Abstract superclass for all exceptions thrown in the security package and subpackages.<p>Note that this is a
* runtime (unchecked) exception. Security exceptions are usually fatal; there is no reason for them to be checked.</p>
*
* @author Ben Alex
* @version $Id$
*/
public abstract class AcegiSecurityException extends NestedRuntimeException {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs an <code>AcegiSecurityException</code> with the specified
* message and root cause.
*
@ -44,7 +39,7 @@ public abstract class AcegiSecurityException extends NestedRuntimeException {
super(msg, t);
}
/**
/**
* Constructs an <code>AcegiSecurityException</code> with the specified
* message and no root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -43,61 +43,47 @@ package org.acegisecurity;
* @version $Id$
*/
public interface AfterInvocationManager {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Given the details of a secure object invocation including its returned
* <code>Object</code>, make an access control decision or optionally
* modify the returned <code>Object</code>.
* Given the details of a secure object invocation including its returned <code>Object</code>, make an
* access control decision or optionally modify the returned <code>Object</code>.
*
* @param authentication the caller that invoked the method
* @param object the secured object that was called
* @param config the configuration attributes associated with the secured
* object that was invoked
* @param returnedObject the <code>Object</code> that was returned from the
* secure object invocation
* @param config the configuration attributes associated with the secured object that was invoked
* @param returnedObject the <code>Object</code> that was returned from the secure object invocation
*
* @return the <code>Object</code> that will ultimately be returned to the
* caller (if an implementation does not wish to modify the object
* to be returned to the caller, the implementation should simply
* return the same object it was passed by the
* <code>returnedObject</code> method argument)
* @return the <code>Object</code> that will ultimately be returned to the caller (if an implementation does not
* wish to modify the object to be returned to the caller, the implementation should simply return the
* same object it was passed by the <code>returnedObject</code> method argument)
*
* @throws AccessDeniedException if access is denied
*/
public Object decide(Authentication authentication, Object object,
ConfigAttributeDefinition config, Object returnedObject)
throws AccessDeniedException;
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config,
Object returnedObject) throws AccessDeniedException;
/**
* Indicates whether this <code>AfterInvocationManager</code> is able to
* process "after invocation" requests presented with the passed
* <code>ConfigAttribute</code>.
*
* <p>
* This allows the <code>AbstractSecurityInterceptor</code> to check every
* configuration attribute can be consumed by the configured
* <code>AccessDecisionManager</code> and/or <code>RunAsManager</code>
* and/or <code>AfterInvocationManager</code>.
* </p>
* Indicates whether this <code>AfterInvocationManager</code> is able to process "after invocation"
* requests presented with the passed <code>ConfigAttribute</code>.<p>This allows the
* <code>AbstractSecurityInterceptor</code> to check every configuration attribute can be consumed by the
* configured <code>AccessDecisionManager</code> and/or <code>RunAsManager</code> and/or
* <code>AfterInvocationManager</code>.</p>
*
* @param attribute a configuration attribute that has been configured
* against the <code>AbstractSecurityInterceptor</code>
* @param attribute a configuration attribute that has been configured against the
* <code>AbstractSecurityInterceptor</code>
*
* @return true if this <code>AfterInvocationManager</code> can support the
* passed configuration attribute
* @return true if this <code>AfterInvocationManager</code> can support the passed configuration attribute
*/
public boolean supports(ConfigAttribute attribute);
/**
* Indicates whether the <code>AfterInvocationManager</code> implementation
* is able to provide access control decisions for the indicated secured
* object type.
* Indicates whether the <code>AfterInvocationManager</code> implementation is able to provide access
* control decisions for the indicated secured object type.
*
* @param clazz the class that is being queried
*
* @return <code>true</code> if the implementation can process the
* indicated class
* @return <code>true</code> if the implementation can process the indicated class
*/
public boolean supports(Class clazz);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -37,101 +37,71 @@ import java.security.Principal;
* @version $Id$
*/
public interface Authentication extends Principal, Serializable {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* See {@link #isAuthenticated()} for a full description.
*
* <p>
* Implementations should <b>always</b> allow this method to be called with
* a <code>false</code> parameter, as this is used by various classes to
* specify the authentication token should not be trusted. If an
* implementation wishes to reject an invocation with a <code>true</code>
* parameter (which would indicate the authentication token is trusted - a
* potential security risk) the implementation should throw an {@link
* IllegalArgumentException}.
* </p>
* Set by an <code>AuthenticationManager</code> to indicate the authorities that the principal has been
* granted. Note that classes should not rely on this value as being valid unless it has been set by a trusted
* <code>AuthenticationManager</code>.<p>Implementations should ensure that modifications to the returned
* array do not affect the state of the Authentication object (e.g. by returning an array copy).</p>
*
* @param isAuthenticated <code>true</code> if the token should be trusted
* (which may result in an exception) or <code>false</code> if the
* token should not be trusted
*
* @throws IllegalArgumentException if an attempt to make the
* authentication token trusted (by passing <code>true</code> as
* the argument) is rejected due to the implementation being
* immutable or implementing its own alternative approach to
* {@link #isAuthenticated()}
*/
public void setAuthenticated(boolean isAuthenticated)
throws IllegalArgumentException;
/**
* Used to indicate to <code>AbstractSecurityInterceptor</code> whether it
* should present the authentication token to the
* <code>AuthenticationManager</code>. Typically an
* <code>AuthenticationManager</code> (or, more often, one of its
* <code>AuthenticationProvider</code>s) will return an immutable
* authentication token after successful authentication, in which case
* that token can safely return <code>true</code> to this method.
* Returning <code>true</code> will improve performance, as calling the
* <code>AuthenticationManager</code> for every request will no longer be
* necessary.
*
* <p>
* For security reasons, implementations of this interface should be very
* careful about returning <code>true</code> to this method unless they
* are either immutable, or have some way of ensuring the properties have
* not been changed since original creation.
* </p>
*
* @return true if the token has been authenticated and the
* <code>AbstractSecurityInterceptor</code> does not need to
* represent the token for re-authentication to the
* <code>AuthenticationManager</code>
*/
public boolean isAuthenticated();
/**
* Set by an <code>AuthenticationManager</code> to indicate the authorities
* that the principal has been granted. Note that classes should not rely
* on this value as being valid unless it has been set by a trusted
* <code>AuthenticationManager</code>.
* <p>
* Implementations should ensure that modifications to the returned array
* do not affect the state of the Authentication object (e.g. by returning an
* array copy).
* </p>
*
* @return the authorities granted to the principal, or <code>null</code>
* if authentication has not been completed
* @return the authorities granted to the principal, or <code>null</code> if authentication has not been completed
*/
public GrantedAuthority[] getAuthorities();
/**
* The credentials that prove the principal is correct. This is usually a
* password, but could be anything relevant to the
* <code>AuthenticationManager</code>. Callers are expected to populate
* the credentials.
* The credentials that prove the principal is correct. This is usually a password, but could be anything
* relevant to the <code>AuthenticationManager</code>. Callers are expected to populate the credentials.
*
* @return the credentials that prove the identity of the
* <code>Principal</code>
* @return the credentials that prove the identity of the <code>Principal</code>
*/
public Object getCredentials();
/**
* Stores additional details about the authentication request. These might
* be an IP address, certificate serial number etc.
* Stores additional details about the authentication request. These might be an IP address, certificate
* serial number etc.
*
* @return additional details about the authentication request, or
* <code>null</code> if not used
* @return additional details about the authentication request, or <code>null</code> if not used
*/
public Object getDetails();
/**
* The identity of the principal being authenticated. This is usually a
* username. Callers are expected to populate the principal.
* The identity of the principal being authenticated. This is usually a username. Callers are expected to
* populate the principal.
*
* @return the <code>Principal</code> being authenticated
*/
public Object getPrincipal();
/**
* Used to indicate to <code>AbstractSecurityInterceptor</code> whether it should present the
* authentication token to the <code>AuthenticationManager</code>. Typically an <code>AuthenticationManager</code>
* (or, more often, one of its <code>AuthenticationProvider</code>s) will return an immutable authentication token
* after successful authentication, in which case that token can safely return <code>true</code> to this method.
* Returning <code>true</code> will improve performance, as calling the <code>AuthenticationManager</code> for
* every request will no longer be necessary.<p>For security reasons, implementations of this interface
* should be very careful about returning <code>true</code> to this method unless they are either immutable, or
* have some way of ensuring the properties have not been changed since original creation.</p>
*
* @return true if the token has been authenticated and the <code>AbstractSecurityInterceptor</code> does not need
* to represent the token for re-authentication to the <code>AuthenticationManager</code>
*/
public boolean isAuthenticated();
/**
* See {@link #isAuthenticated()} for a full description.<p>Implementations should <b>always</b> allow this
* method to be called with a <code>false</code> parameter, as this is used by various classes to specify the
* authentication token should not be trusted. If an implementation wishes to reject an invocation with a
* <code>true</code> parameter (which would indicate the authentication token is trusted - a potential security
* risk) the implementation should throw an {@link IllegalArgumentException}.</p>
*
* @param isAuthenticated <code>true</code> if the token should be trusted (which may result in an exception) or
* <code>false</code> if the token should not be trusted
*
* @throws IllegalArgumentException if an attempt to make the authentication token trusted (by passing
* <code>true</code> as the argument) is rejected due to the implementation being immutable or
* implementing its own alternative approach to {@link #isAuthenticated()}
*/
public void setAuthenticated(boolean isAuthenticated)
throws IllegalArgumentException;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,17 +16,16 @@
package org.acegisecurity;
/**
* Thrown if an authentication request is rejected because there is no {@link
* Authentication} object in the {@link org.acegisecurity.context.SecurityContext SecurityContext}.
* Thrown if an authentication request is rejected because there is no {@link Authentication} object in the {@link
* org.acegisecurity.context.SecurityContext SecurityContext}.
*
* @author Ben Alex
* @version $Id$
*/
public class AuthenticationCredentialsNotFoundException
extends AuthenticationException {
//~ Constructors ===========================================================
public class AuthenticationCredentialsNotFoundException extends AuthenticationException {
//~ Constructors ===================================================================================================
/**
/**
* Constructs an <code>AuthenticationCredentialsNotFoundException</code>
* with the specified message.
*
@ -36,7 +35,7 @@ public class AuthenticationCredentialsNotFoundException
super(msg);
}
/**
/**
* Constructs an <code>AuthenticationCredentialsNotFoundException</code>
* with the specified message and root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,24 +16,21 @@
package org.acegisecurity;
/**
* Abstract superclass for all exceptions related an {@link Authentication}
* object being invalid for whatever reason.
* Abstract superclass for all exceptions related an {@link Authentication} object being invalid for whatever
* reason.
*
* @author Ben Alex
* @version $Id$
*/
public abstract class AuthenticationException extends AcegiSecurityException {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
/**
* The authentication that related to this exception (may be
* <code>null</code>)
*/
/** The authentication that related to this exception (may be <code>null</code>) */
private Authentication authentication;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs an <code>AuthenticationException</code> with the specified
* message and root cause.
*
@ -44,7 +41,7 @@ public abstract class AuthenticationException extends AcegiSecurityException {
super(msg, t);
}
/**
/**
* Constructs an <code>AuthenticationException</code> with the specified
* message and no root cause.
*
@ -54,7 +51,7 @@ public abstract class AuthenticationException extends AcegiSecurityException {
super(msg);
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public Authentication getAuthentication() {
return authentication;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -22,41 +22,21 @@ package org.acegisecurity;
* @version $Id$
*/
public interface AuthenticationManager {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Attempts to authenticate the passed {@link Authentication} object,
* returning a fully populated <code>Authentication</code> object
* (including granted authorities) if successful.
*
* <p>
* An <code>AuthenticationManager</code> must honour the following contract
* concerning exceptions:
* </p>
*
* <p>
* A {@link DisabledException} must be thrown if an account is disabled and
* the <code>AuthenticationManager</code> can test for this state.
* </p>
*
* <p>
* A {@link LockedException} must be thrown if an account is locked and the
* <code>AuthenticationManager</code> can test for account locking.
* </p>
*
* <p>
* A {@link BadCredentialsException} must be thrown if incorrect
* credentials are presented. Whilst the above exceptions are optional, an
* <code>AuthenticationManager</code> must <B>always</B> test credentials.
* </p>
*
* <p>
* Exceptions should be tested for and if applicable thrown in the order
* expressed above (ie if an account is disabled or locked, the
* authentication request is immediately rejected and the credentials
* testing process is not performed). This prevents credentials being
* tested against disabled or locked accounts.
* </p>
* Attempts to authenticate the passed {@link Authentication} object, returning a fully populated
* <code>Authentication</code> object (including granted authorities) if successful.<p>An
* <code>AuthenticationManager</code> must honour the following contract concerning exceptions:</p>
* <p>A {@link DisabledException} must be thrown if an account is disabled and the
* <code>AuthenticationManager</code> can test for this state.</p>
* <p>A {@link LockedException} must be thrown if an account is locked and the
* <code>AuthenticationManager</code> can test for account locking.</p>
* <p>A {@link BadCredentialsException} must be thrown if incorrect credentials are presented. Whilst the
* above exceptions are optional, an <code>AuthenticationManager</code> must <B>always</B> test credentials.</p>
* <p>Exceptions should be tested for and if applicable thrown in the order expressed above (ie if an
* account is disabled or locked, the authentication request is immediately rejected and the credentials testing
* process is not performed). This prevents credentials being tested against disabled or locked accounts.</p>
*
* @param authentication the authentication request object
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,20 +16,16 @@
package org.acegisecurity;
/**
* Thrown if an authentication request could not be processed due to a system
* problem.
*
* <p>
* This might be thrown if a backend authentication repository is unavailable.
* </p>
* Thrown if an authentication request could not be processed due to a system problem.<p>This might be thrown if a
* backend authentication repository is unavailable.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class AuthenticationServiceException extends AuthenticationException {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs an <code>AuthenticationServiceException</code> with the
* specified message.
*
@ -39,7 +35,7 @@ public class AuthenticationServiceException extends AuthenticationException {
super(msg);
}
/**
/**
* Constructs an <code>AuthenticationServiceException</code> with the
* specified message and root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -22,45 +22,35 @@ package org.acegisecurity;
* @version $Id$
*/
public interface AuthenticationTrustResolver {
//~ Methods ================================================================
//~ 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).
* 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>)
* @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
* @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>
* 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>)
* @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
* @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);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -20,29 +20,29 @@ import org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken;
/**
* Basic implementation of {@link AuthenticationTrustResolver}.
*
* <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>
* Basic implementation of {@link AuthenticationTrustResolver}.<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 ========================================================
public class AuthenticationTrustResolverImpl implements AuthenticationTrustResolver {
//~ Instance fields ================================================================================================
private Class anonymousClass = AnonymousAuthenticationToken.class;
private Class rememberMeClass = RememberMeAuthenticationToken.class;
//~ Methods ================================================================
//~ Methods ========================================================================================================
public Class getAnonymousClass() {
return anonymousClass;
}
public Class getRememberMeClass() {
return rememberMeClass;
}
public boolean isAnonymous(Authentication authentication) {
if ((anonymousClass == null) || (authentication == null)) {
@ -52,14 +52,6 @@ public class AuthenticationTrustResolverImpl
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;
@ -68,11 +60,11 @@ public class AuthenticationTrustResolverImpl
return rememberMeClass.isAssignableFrom(authentication.getClass());
}
public void setAnonymousClass(Class anonymousClass) {
this.anonymousClass = anonymousClass;
}
public void setRememberMeClass(Class rememberMeClass) {
this.rememberMeClass = rememberMeClass;
}
public Class getRememberMeClass() {
return rememberMeClass;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,21 +16,16 @@
package org.acegisecurity;
/**
* Thrown if an authorization request could not be processed due to a system
* problem.
*
* <p>
* This might be thrown if an <code>AccessDecisionManager</code> implementation
* could not locate a required method argument, for example.
* </p>
* Thrown if an authorization request could not be processed due to a system problem.<p>This might be thrown if an
* <code>AccessDecisionManager</code> implementation could not locate a required method argument, for example.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class AuthorizationServiceException extends AccessDeniedException {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs an <code>AuthorizationServiceException</code> with the
* specified message.
*
@ -40,7 +35,7 @@ public class AuthorizationServiceException extends AccessDeniedException {
super(msg);
}
/**
/**
* Constructs an <code>AuthorizationServiceException</code> with the
* specified message and root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,21 +16,20 @@
package org.acegisecurity;
/**
* Thrown if an authentication request is rejected because the credentials are
* invalid. For this exception to be thrown, it means the account is neither
* locked nor disabled.
* Thrown if an authentication request is rejected because the credentials are invalid. For this exception to be
* thrown, it means the account is neither locked nor disabled.
*
* @author Ben Alex
* @version $Id$
*/
public class BadCredentialsException extends AuthenticationException {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private Object extraInformation;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs a <code>BadCredentialsException</code> with the specified
* message.
*
@ -45,7 +44,7 @@ public class BadCredentialsException extends AuthenticationException {
this.extraInformation = extraInformation;
}
/**
/**
* Constructs a <code>BadCredentialsException</code> with the specified
* message and root cause.
*
@ -56,11 +55,10 @@ public class BadCredentialsException extends AuthenticationException {
super(msg, t);
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Any additional information about the exception. Generally a
* <code>UserDetails</code> object.
* Any additional information about the exception. Generally a <code>UserDetails</code> object.
*
* @return extra information or <code>null</code>
*/

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -38,28 +38,19 @@ import java.io.Serializable;
* @version $Id$
*/
public interface ConfigAttribute extends Serializable {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* If the <code>ConfigAttribute</code> can be represented as a
* <code>String</code> and that <code>String</code> is sufficient in
* precision to be relied upon as a configuration parameter by a {@link
* RunAsManager}, {@link AccessDecisionManager} or
* <code>AccessDecisionManager</code> delegate, this method should return
* such a <code>String</code>.
*
* <p>
* If the <code>ConfigAttribute</code> cannot be expressed with sufficient
* precision as a <code>String</code>, <code>null</code> should be
* returned. Returning <code>null</code> will require any relying classes
* to specifically support the <code>ConfigAttribute</code>
* implementation, so returning <code>null</code> should be avoided
* unless actually required.
* </p>
* If the <code>ConfigAttribute</code> can be represented as a <code>String</code> and that
* <code>String</code> is sufficient in precision to be relied upon as a configuration parameter by a {@link
* RunAsManager}, {@link AccessDecisionManager} or <code>AccessDecisionManager</code> delegate, this method should
* return such a <code>String</code>.<p>If the <code>ConfigAttribute</code> cannot be expressed with
* sufficient precision as a <code>String</code>, <code>null</code> should be returned. Returning
* <code>null</code> will require any relying classes to specifically support the <code>ConfigAttribute</code>
* implementation, so returning <code>null</code> should be avoided unless actually required.</p>
*
* @return a representation of the configuration attribute (or
* <code>null</code> if the configuration attribute cannot be
* expressed as a <code>String</code> with sufficient precision).
* @return a representation of the configuration attribute (or <code>null</code> if the configuration attribute
* cannot be expressed as a <code>String</code> with sufficient precision).
*/
public String getAttribute();
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,52 +23,29 @@ import java.util.Vector;
/**
* Holds a group of {@link ConfigAttribute}s that are associated with a given
* secure object target.
*
* <p>
* All the <code>ConfigAttributeDefinition</code>s associated with a given
* {@link org.acegisecurity.intercept.AbstractSecurityInterceptor} are
* stored in an {@link org.acegisecurity.intercept.ObjectDefinitionSource}.
* </p>
* Holds a group of {@link ConfigAttribute}s that are associated with a given secure object target.<p>All the
* <code>ConfigAttributeDefinition</code>s associated with a given {@link
* org.acegisecurity.intercept.AbstractSecurityInterceptor} are stored in an {@link
* org.acegisecurity.intercept.ObjectDefinitionSource}.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class ConfigAttributeDefinition implements Serializable {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private List configAttributes = new Vector();
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public ConfigAttributeDefinition() {
super();
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Returns an <code>Iterator</code> over all the
* <code>ConfigAttribute</code>s defined by this
* <code>ConfigAttributeDefinition</code>.
*
* <P>
* Allows <code>AccessDecisionManager</code>s and other classes to loop
* through every configuration attribute associated with a target secure
* object.
* </p>
*
* @return all the configuration attributes stored by the instance, or
* <code>null</code> if an <code>Iterator</code> is unavailable
*/
public Iterator getConfigAttributes() {
return this.configAttributes.iterator();
}
/**
* Adds a <code>ConfigAttribute</code> that is related to the secure object
* method.
* Adds a <code>ConfigAttribute</code> that is related to the secure object method.
*
* @param newConfigAttribute the new configuration attribute to add
*/
@ -77,13 +54,13 @@ public class ConfigAttributeDefinition implements Serializable {
}
/**
* Indicates whether the specified <code>ConfigAttribute</code> is
* contained within this <code>ConfigAttributeDefinition</code>.
* Indicates whether the specified <code>ConfigAttribute</code> is contained within this
* <code>ConfigAttributeDefinition</code>.
*
* @param configAttribute the attribute to locate
*
* @return <code>true</code> if the specified <code>ConfigAttribute</code>
* is contained, <code>false</code> otherwise
* @return <code>true</code> if the specified <code>ConfigAttribute</code> is contained, <code>false</code>
* otherwise
*/
public boolean contains(ConfigAttribute configAttribute) {
return configAttributes.contains(configAttribute);
@ -117,6 +94,18 @@ public class ConfigAttributeDefinition implements Serializable {
return false;
}
/**
* Returns an <code>Iterator</code> over all the <code>ConfigAttribute</code>s defined by this
* <code>ConfigAttributeDefinition</code>.<P>Allows <code>AccessDecisionManager</code>s and other classes
* to loop through every configuration attribute associated with a target secure object.</p>
*
* @return all the configuration attributes stored by the instance, or <code>null</code> if an
* <code>Iterator</code> is unavailable
*/
public Iterator getConfigAttributes() {
return this.configAttributes.iterator();
}
/**
* Returns the number of <code>ConfigAttribute</code>s defined by this
* <code>ConfigAttributeDefinition</code>.

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -21,19 +21,15 @@ import java.beans.PropertyEditorSupport;
/**
* A property editor that can create a populated {@link
* ConfigAttributeDefinition} from a comma separated list of values.
*
* <P>
* Trims preceding and trailing spaces from presented command separated tokens,
* as this can be a source of hard-to-spot configuration issues for end users.
* </p>
* A property editor that can create a populated {@link ConfigAttributeDefinition} from a comma separated list of
* values.<P>Trims preceding and trailing spaces from presented command separated tokens, as this can be a source
* of hard-to-spot configuration issues for end users.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class ConfigAttributeEditor extends PropertyEditorSupport {
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void setAsText(String s) throws IllegalArgumentException {
if ((s == null) || "".equals(s)) {
@ -43,8 +39,7 @@ public class ConfigAttributeEditor extends PropertyEditorSupport {
ConfigAttributeDefinition configDefinition = new ConfigAttributeDefinition();
for (int i = 0; i < tokens.length; i++) {
configDefinition.addConfigAttribute(new SecurityConfig(
tokens[i].trim()));
configDefinition.addConfigAttribute(new SecurityConfig(tokens[i].trim()));
}
setValue(configDefinition);

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,17 +16,16 @@
package org.acegisecurity;
/**
* Thrown if an authentication request is rejected because the account's
* credentials have expired. Makes no assertion as to whether or not the
* credentials were valid.
* Thrown if an authentication request is rejected because the account's credentials have expired. Makes no
* assertion as to whether or not the credentials were valid.
*
* @author Ben Alex
* @version $Id$
*/
public class CredentialsExpiredException extends AuthenticationException {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs a <code>CredentialsExpiredException</code> with the specified
* message.
*
@ -36,7 +35,7 @@ public class CredentialsExpiredException extends AuthenticationException {
super(msg);
}
/**
/**
* Constructs a <code>CredentialsExpiredException</code> with the specified
* message and root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,17 +16,16 @@
package org.acegisecurity;
/**
* Thrown if an authentication request is rejected because the account is
* disabled. Makes no assertion as to whether or not the credentials were
* valid.
* Thrown if an authentication request is rejected because the account is disabled. Makes no assertion as to
* whether or not the credentials were valid.
*
* @author Ben Alex
* @version $Id$
*/
public class DisabledException extends AuthenticationException {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs a <code>DisabledException</code> with the specified message.
*
* @param msg the detail message
@ -35,7 +34,7 @@ public class DisabledException extends AuthenticationException {
super(msg);
}
/**
/**
* Constructs a <code>DisabledException</code> with the specified message
* and root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -28,27 +28,19 @@ package org.acegisecurity;
* @version $Id$
*/
public interface GrantedAuthority {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* If the <code>GrantedAuthority</code> can be represented as a
* <code>String</code> and that <code>String</code> is sufficient in
* precision to be relied upon for an access control decision by an {@link
* AccessDecisionManager} (or delegate), this method should return such a
* <code>String</code>.
*
* <p>
* If the <code>GrantedAuthority</code> cannot be expressed with sufficient
* precision as a <code>String</code>, <code>null</code> should be
* returned. Returning <code>null</code> will require an
* <code>AccessDecisionManager</code> (or delegate) to specifically
* support the <code>GrantedAuthority</code> implementation, so returning
* <code>null</code> should be avoided unless actually required.
* </p>
* If the <code>GrantedAuthority</code> can be represented as a <code>String</code> and that
* <code>String</code> is sufficient in precision to be relied upon for an access control decision by an {@link
* AccessDecisionManager} (or delegate), this method should return such a <code>String</code>.<p>If the
* <code>GrantedAuthority</code> cannot be expressed with sufficient precision as a <code>String</code>,
* <code>null</code> should be returned. Returning <code>null</code> will require an
* <code>AccessDecisionManager</code> (or delegate) to specifically support the <code>GrantedAuthority</code>
* implementation, so returning <code>null</code> should be avoided unless actually required.</p>
*
* @return a representation of the granted authority (or <code>null</code>
* if the granted authority cannot be expressed as a
* <code>String</code> with sufficient precision).
* @return a representation of the granted authority (or <code>null</code> if the granted authority cannot be
* expressed as a <code>String</code> with sufficient precision).
*/
public String getAuthority();
}

View File

@ -19,29 +19,25 @@ import java.io.Serializable;
/**
* Basic concrete implementation of a {@link GrantedAuthority}.
*
* <p>
* Stores a <code>String</code> representation of an authority granted to the
* {@link Authentication} object.
* </p>
* Basic concrete implementation of a {@link GrantedAuthority}.<p>Stores a <code>String</code> representation of an
* authority granted to the {@link Authentication} object.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class GrantedAuthorityImpl implements GrantedAuthority, Serializable {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private String role;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public GrantedAuthorityImpl(String role) {
super();
this.role = role;
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public boolean equals(Object obj) {
if (obj instanceof String) {

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,26 +16,19 @@
package org.acegisecurity;
/**
* Thrown if an authentication request is rejected because the credentials are
* not sufficiently trusted.
*
* <p>
* {@link org.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 mechanism or
* anonymously. The commonly used {@link
* org.acegisecurity.ui.ExceptionTranslationFilter} will thus
* cause the <code>AuthenticationEntryPoint</code> to be called, allowing the
* principal to authenticate with a stronger level of authentication.
* </p>
* Thrown if an authentication request is rejected because the credentials are not sufficiently trusted.<p>{{@link
* org.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 mechanism or anonymously. The commonly used
* {@link org.acegisecurity.ui.ExceptionTranslationFilter} 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 ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs an <code>InsufficientAuthenticationException</code> with the
* specified message.
*
@ -45,7 +38,7 @@ public class InsufficientAuthenticationException extends AuthenticationException
super(msg);
}
/**
/**
* Constructs an <code>InsufficientAuthenticationException</code> with the
* specified message and root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,16 +16,16 @@
package org.acegisecurity;
/**
* Thrown if an authentication request is rejected because the account is
* locked. Makes no assertion as to whether or not the credentials were valid.
* Thrown if an authentication request is rejected because the account is locked. Makes no assertion as to whether
* or not the credentials were valid.
*
* @author Ben Alex
* @version $Id$
*/
public class LockedException extends AuthenticationException {
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs a <code>LockedException</code> with the specified message.
*
* @param msg the detail message.
@ -34,7 +34,7 @@ public class LockedException extends AuthenticationException {
super(msg);
}
/**
/**
* Constructs a <code>LockedException</code> with the specified message and
* root cause.
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,19 +16,18 @@
package org.acegisecurity;
/**
* Simply accepts as valid whatever is passed to it, if
* <code>grantAccess</code> is set to <code>true</code>.
* Simply accepts as valid whatever is passed to it, if <code>grantAccess</code> is set to <code>true</code>.
*
* @author Ben Alex
* @author Wesley Hall
* @version $Id$
*/
public class MockAuthenticationManager extends AbstractAuthenticationManager {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private boolean grantAccess = true;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public MockAuthenticationManager(boolean grantAccess) {
this.grantAccess = grantAccess;
@ -38,15 +37,14 @@ public class MockAuthenticationManager extends AbstractAuthenticationManager {
super();
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public Authentication doAuthentication(Authentication authentication)
throws AuthenticationException {
if (grantAccess) {
return authentication;
} else {
throw new BadCredentialsException(
"MockAuthenticationManager instructed to deny access");
throw new BadCredentialsException("MockAuthenticationManager instructed to deny access");
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -58,47 +58,37 @@ package org.acegisecurity;
* @version $Id$
*/
public interface RunAsManager {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Returns a replacement <code>Authentication</code> object for the current
* secure object invocation, or <code>null</code> if replacement not
* required.
* Returns a replacement <code>Authentication</code> object for the current secure object invocation, or
* <code>null</code> if replacement not required.
*
* @param authentication the caller invoking the secure object
* @param object the secured object being called
* @param config the configuration attributes associated with the secure
* object being invoked
* @param config the configuration attributes associated with the secure object being invoked
*
* @return a replacement object to be used for duration of the secure
* object invocation, or <code>null</code> if the
* <code>Authentication</code> should be left as is
* @return a replacement object to be used for duration of the secure object invocation, or <code>null</code> if
* the <code>Authentication</code> should be left as is
*/
public Authentication buildRunAs(Authentication authentication,
Object object, ConfigAttributeDefinition config);
public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config);
/**
* Indicates whether this <code>RunAsManager</code> is able to process the
* passed <code>ConfigAttribute</code>.
*
* <p>
* This allows the <code>AbstractSecurityInterceptor</code> to check every
* configuration attribute can be consumed by the configured
* <code>AccessDecisionManager</code> and/or <code>RunAsManager</code>
* and/or <code>AfterInvocationManager</code>.
* </p>
* Indicates whether this <code>RunAsManager</code> is able to process the passed
* <code>ConfigAttribute</code>.<p>This allows the <code>AbstractSecurityInterceptor</code> to check every
* configuration attribute can be consumed by the configured <code>AccessDecisionManager</code> and/or
* <code>RunAsManager</code> and/or <code>AfterInvocationManager</code>.</p>
*
* @param attribute a configuration attribute that has been configured
* against the <code>AbstractSecurityInterceptor</code>
* @param attribute a configuration attribute that has been configured against the
* <code>AbstractSecurityInterceptor</code>
*
* @return <code>true</code> if this <code>RunAsManager</code> can support
* the passed configuration attribute
* @return <code>true</code> if this <code>RunAsManager</code> can support the passed configuration attribute
*/
public boolean supports(ConfigAttribute attribute);
/**
* Indicates whether the <code>RunAsManager</code> implementation is able
* to provide run-as replacement for the indicated secure object type.
* Indicates whether the <code>RunAsManager</code> implementation is able to provide run-as replacement for
* the indicated secure object type.
*
* @param clazz the class that is being queried
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -22,21 +22,17 @@ package org.acegisecurity;
* @version $Id$
*/
public class SecurityConfig implements ConfigAttribute {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private String attrib;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public SecurityConfig(String config) {
this.attrib = config;
}
//~ Methods ================================================================
public String getAttribute() {
return this.attrib;
}
//~ Methods ========================================================================================================
public boolean equals(Object obj) {
if (obj instanceof String) {
@ -52,6 +48,10 @@ public class SecurityConfig implements ConfigAttribute {
return false;
}
public String getAttribute() {
return this.attrib;
}
public int hashCode() {
return this.attrib.hashCode();
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,7 @@ package org.acegisecurity.acl;
import java.io.Serializable;
/**
* Marker interface representing an access control list entry associated with a
* specific domain object instance.

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -26,33 +26,26 @@ import org.acegisecurity.Authentication;
* @version $Id$
*/
public interface AclManager {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Obtains the ACLs that apply to the specified domain instance.
*
* @param domainInstance the instance for which ACL information is required
* (never <code>null</code>)
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
*
* @return the ACLs that apply, or <code>null</code> if no ACLs apply to
* the specified domain instance
* @return the ACLs that apply, or <code>null</code> if no ACLs apply to the specified domain instance
*/
public AclEntry[] getAcls(Object domainInstance);
/**
* Obtains the ACLs that apply to the specified domain instance, but only
* including those ACLs which have been granted to the presented
* <code>Authentication</code> object
* Obtains the ACLs that apply to the specified domain instance, but only including those ACLs which have
* been granted to the presented <code>Authentication</code> object
*
* @param domainInstance the instance for which ACL information is required
* (never <code>null</code>)
* @param authentication the prncipal for which ACL information should be
* filtered (never <code>null</code>)
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
* @param authentication the prncipal for which ACL information should be filtered (never <code>null</code>)
*
* @return only those ACLs applying to the domain instance that have been
* granted to the principal (or <code>null</code>) if no such ACLs
* are found
* @return only those ACLs applying to the domain instance that have been granted to the principal (or
* <code>null</code>) if no such ACLs are found
*/
public AclEntry[] getAcls(Object domainInstance,
Authentication authentication);
public AclEntry[] getAcls(Object domainInstance, Authentication authentication);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,7 @@ package org.acegisecurity.acl;
import org.acegisecurity.Authentication;
/**
* Indicates a class can process a given domain object instance and
* authoritatively return the ACLs that apply.
@ -29,54 +30,38 @@ import org.acegisecurity.Authentication;
* @version $Id$
*/
public interface AclProvider {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Obtains the ACLs that apply to the specified domain instance.
*
* <P>
* Will never be called unless the {@link #supports(Object)} method
* returned <code>true</code>.
* </p>
* Obtains the ACLs that apply to the specified domain instance.<P>Will never be called unless the {@link
* #supports(Object)} method returned <code>true</code>.</p>
*
* @param domainInstance the instance for which ACL information is required
* (never <code>null</code>)
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
*
* @return the ACLs that apply, or <code>null</code> if no ACLs apply to
* the specified domain instance
* @return the ACLs that apply, or <code>null</code> if no ACLs apply to the specified domain instance
*/
public AclEntry[] getAcls(Object domainInstance);
/**
* Obtains the ACLs that apply to the specified domain instance
* and presented <code>Authentication</code> object.
* Obtains the ACLs that apply to the specified domain instance and presented <code>Authentication</code>
* object.<P>Will never be called unless the {@link #supports(Object)} method returned <code>true</code>.</p>
*
* <P>
* Will never be called unless the {@link #supports(Object)} method
* returned <code>true</code>.
* </p>
*
* @param domainInstance the instance for which ACL information is required
* (never <code>null</code>)
* @param authentication the prncipal for which ACL information should be
* filtered (never <code>null</code>)
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
* @param authentication the prncipal for which ACL information should be filtered (never <code>null</code>)
*
* @return only those ACLs applying to the domain instance that have been
* granted to the principal (or <code>null</code>) if no such ACLs
* are found
* @return only those ACLs applying to the domain instance that have been granted to the principal (or
* <code>null</code>) if no such ACLs are found
*/
public AclEntry[] getAcls(Object domainInstance,
Authentication authentication);
public AclEntry[] getAcls(Object domainInstance, Authentication authentication);
/**
* Indicates whether this <code>AclProvider</code> can authoritatively
* return ACL information for the specified domain object instance.
* Indicates whether this <code>AclProvider</code> can authoritatively return ACL information for the
* specified domain object instance.
*
* @param domainInstance the instance for which ACL information is required
* (never <code>null</code>)
* @param domainInstance the instance for which ACL information is required (never <code>null</code>)
*
* @return <code>true</code> if this provider is authoritative for the
* specified domain object instance, <code>false</code> otherwise
* @return <code>true</code> if this provider is authoritative for the specified domain object instance,
* <code>false</code> otherwise
*/
public boolean supports(Object domainInstance);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -21,6 +21,7 @@ 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.util.Iterator;
@ -28,27 +29,31 @@ import java.util.List;
/**
* Iterates through a list of {@link AclProvider}s to locate the ACLs that
* apply to a given domain object instance.
*
* <P>
* If no compatible provider is found, it is assumed that no ACLs apply for the
* specified domain object instance and <code>null</code> is returned.
* </p>
* Iterates through a list of {@link AclProvider}s to locate the ACLs that apply to a given domain object instance.<P>If
* no compatible provider is found, it is assumed that no ACLs apply for the specified domain object instance and
* <code>null</code> is returned.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class AclProviderManager implements AclManager, InitializingBean {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(AclProviderManager.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private List providers;
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
checkIfValidList(this.providers);
}
private void checkIfValidList(List listToCheck) {
Assert.notEmpty(listToCheck, "A list of AclManagers is required");
}
public AclEntry[] getAcls(Object domainInstance) {
Assert.notNull(domainInstance, "domainInstance is null - violating interface contract");
@ -60,8 +65,7 @@ public class AclProviderManager implements AclManager, InitializingBean {
if (provider.supports(domainInstance)) {
if (logger.isDebugEnabled()) {
logger.debug("ACL lookup using "
+ provider.getClass().getName());
logger.debug("ACL lookup using " + provider.getClass().getName());
}
return provider.getAcls(domainInstance);
@ -69,15 +73,13 @@ public class AclProviderManager implements AclManager, InitializingBean {
}
if (logger.isDebugEnabled()) {
logger.debug("No AclProvider found for "
+ domainInstance.toString());
logger.debug("No AclProvider found for " + domainInstance.toString());
}
return null;
}
public AclEntry[] getAcls(Object domainInstance,
Authentication authentication) {
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
Assert.notNull(domainInstance, "domainInstance is null - violating interface contract");
Assert.notNull(authentication, "authentication is null - violating interface contract");
@ -88,34 +90,34 @@ public class AclProviderManager implements AclManager, InitializingBean {
if (provider.supports(domainInstance)) {
if (logger.isDebugEnabled()) {
logger.debug("ACL lookup using "
+ provider.getClass().getName());
logger.debug("ACL lookup using " + provider.getClass().getName());
}
return provider.getAcls(domainInstance, authentication);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Provider " + provider.toString()
+ " does not support " + domainInstance);
logger.debug("Provider " + provider.toString() + " does not support " + domainInstance);
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("No AclProvider found for "
+ domainInstance.toString());
logger.debug("No AclProvider found for " + domainInstance.toString());
}
return null;
}
public List getProviders() {
return this.providers;
}
/**
* Sets the {@link AclProvider} objects to be used for ACL determinations.
*
* @param newList that should be used for ACL determinations
*
* @throws IllegalArgumentException if an invalid provider was included in
* the list
* @throws IllegalArgumentException if an invalid provider was included in the list
*/
public void setProviders(List newList) {
checkIfValidList(newList);
@ -130,24 +132,11 @@ public class AclProviderManager implements AclManager, InitializingBean {
AclProvider attemptToCast = (AclProvider) currentObject;
} catch (ClassCastException cce) {
throw new IllegalArgumentException("AclProvider "
+ currentObject.getClass().getName()
throw new IllegalArgumentException("AclProvider " + currentObject.getClass().getName()
+ " must implement AclProvider");
}
}
this.providers = newList;
}
public List getProviders() {
return this.providers;
}
public void afterPropertiesSet() throws Exception {
checkIfValidList(this.providers);
}
private void checkIfValidList(List listToCheck) {
Assert.notEmpty(listToCheck, "A list of AclManagers is required");
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,27 +17,24 @@ package org.acegisecurity.acl.basic;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import java.util.Arrays;
/**
* Abstract implementation of {@link BasicAclEntry}.
*
* <P>
* Provides core bit mask handling methods.
* </p>
* Abstract implementation of {@link BasicAclEntry}.<P>Provides core bit mask handling methods.</p>
*
* @author Ben Alex
* @version $Id$
*/
public abstract class AbstractBasicAclEntry implements BasicAclEntry {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(AbstractBasicAclEntry.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private AclObjectIdentity aclObjectIdentity;
private AclObjectIdentity aclObjectParentIdentity;
@ -45,10 +42,9 @@ public abstract class AbstractBasicAclEntry implements BasicAclEntry {
private int[] validPermissions;
private int mask = 0; // default means no permissions
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public AbstractBasicAclEntry(Object recipient,
AclObjectIdentity aclObjectIdentity,
public AbstractBasicAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity,
AclObjectIdentity aclObjectParentIdentity, int mask) {
Assert.notNull(recipient, "recipient cannot be null");
@ -59,10 +55,8 @@ public abstract class AbstractBasicAclEntry implements BasicAclEntry {
for (int i = 0; i < validPermissions.length; i++) {
if (logger.isDebugEnabled()) {
logger.debug("Valid permission: "
+ printPermissionsBlock(validPermissions[i]) + " "
+ printBinary(validPermissions[i]) + " ("
+ validPermissions[i] + ")");
logger.debug("Valid permission: " + printPermissionsBlock(validPermissions[i]) + " "
+ printBinary(validPermissions[i]) + " (" + validPermissions[i] + ")");
}
}
@ -72,7 +66,7 @@ public abstract class AbstractBasicAclEntry implements BasicAclEntry {
this.mask = mask;
}
/**
/**
* A protected constructor for use by Hibernate.
*/
protected AbstractBasicAclEntry() {
@ -80,86 +74,7 @@ public abstract class AbstractBasicAclEntry implements BasicAclEntry {
Arrays.sort(validPermissions);
}
//~ Methods ================================================================
public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity) {
this.aclObjectIdentity = aclObjectIdentity;
}
public AclObjectIdentity getAclObjectIdentity() {
return this.aclObjectIdentity;
}
public void setAclObjectParentIdentity(
AclObjectIdentity aclObjectParentIdentity) {
this.aclObjectParentIdentity = aclObjectParentIdentity;
}
public AclObjectIdentity getAclObjectParentIdentity() {
return this.aclObjectParentIdentity;
}
/**
* Subclasses must indicate the permissions they support. Each base
* permission should be an integer with a base 2. ie: the first permission
* is 2^^0 (1), the second permission is 2^^1 (2), the third permission is
* 2^^2 (4) etc. Each base permission should be exposed by the subclass as
* a <code>public static final int</code>. It is further recommended that
* valid combinations of permissions are also exposed as <code>public
* static final int</code>s.
*
* <P>
* This method returns all permission integers that are allowed to be used
* together. <B>This must include any combinations of valid
* permissions</b>. So if the permissions indicated by 2^^2 (4) and 2^^1
* (2) can be used together, one of the integers returned by this method
* must be 6 (4 + 2). Otherwise attempts to set the permission will be
* rejected, as the final resulting mask will be rejected.
* </p>
*
* <P>
* Whilst it may seem unduly time onerous to return every valid permission
* <B>combination</B>, doing so delivers maximum flexibility in ensuring
* ACLs only reflect logical combinations. For example, it would be
* inappropriate to grant a "read" and "write" permission along with an
* "unrestricted" permission, as the latter implies the former
* permissions.
* </p>
*
* @return <b>every</b> valid combination of permissions
*/
public abstract int[] getValidPermissions();
/**
* Outputs the permissions in a human-friendly format. For example, this
* method may return "CR-D" to indicate the passed integer permits create,
* permits read, does not permit update, and permits delete.
*
* @param i the integer containing the mask which should be printed
*
* @return the human-friend formatted block
*/
public abstract String printPermissionsBlock(int i);
public void setMask(int mask) {
this.mask = mask;
}
public int getMask() {
return this.mask;
}
public boolean isPermitted(int permissionToCheck) {
return isPermitted(this.mask, permissionToCheck);
}
public void setRecipient(Object recipient) {
this.recipient = recipient;
}
public Object getRecipient() {
return this.recipient;
}
//~ Methods ========================================================================================================
public int addPermission(int permissionToAdd) {
return addPermissions(new int[] {permissionToAdd});
@ -167,29 +82,25 @@ public abstract class AbstractBasicAclEntry implements BasicAclEntry {
public int addPermissions(int[] permissionsToAdd) {
if (logger.isDebugEnabled()) {
logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask)
+ " " + printBinary(mask) + " (" + mask + ")");
logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask
+ ")");
}
for (int i = 0; i < permissionsToAdd.length; i++) {
if (logger.isDebugEnabled()) {
logger.debug("Add permission: "
+ printPermissionsBlock(permissionsToAdd[i]) + " "
+ printBinary(permissionsToAdd[i]) + " ("
+ permissionsToAdd[i] + ")");
logger.debug("Add permission: " + printPermissionsBlock(permissionsToAdd[i]) + " "
+ printBinary(permissionsToAdd[i]) + " (" + permissionsToAdd[i] + ")");
}
this.mask |= permissionsToAdd[i];
}
if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
throw new IllegalArgumentException(
"Resulting permission set will be invalid.");
throw new IllegalArgumentException("Resulting permission set will be invalid.");
} else {
if (logger.isDebugEnabled()) {
logger.debug("AFTER Permissions: "
+ printPermissionsBlock(mask) + " " + printBinary(mask)
+ " (" + mask + ")");
logger.debug("AFTER Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " ("
+ mask + ")");
}
return this.mask;
@ -202,65 +113,67 @@ public abstract class AbstractBasicAclEntry implements BasicAclEntry {
public int deletePermissions(int[] permissionsToDelete) {
if (logger.isDebugEnabled()) {
logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask)
+ " " + printBinary(mask) + " (" + mask + ")");
logger.debug("BEFORE Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " (" + mask
+ ")");
}
for (int i = 0; i < permissionsToDelete.length; i++) {
if (logger.isDebugEnabled()) {
logger.debug("Delete permission: "
+ printPermissionsBlock(permissionsToDelete[i]) + " "
+ printBinary(permissionsToDelete[i]) + " ("
+ permissionsToDelete[i] + ")");
logger.debug("Delete permission: " + printPermissionsBlock(permissionsToDelete[i]) + " "
+ printBinary(permissionsToDelete[i]) + " (" + permissionsToDelete[i] + ")");
}
this.mask &= ~permissionsToDelete[i];
}
if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
throw new IllegalArgumentException(
"Resulting permission set will be invalid.");
throw new IllegalArgumentException("Resulting permission set will be invalid.");
} else {
if (logger.isDebugEnabled()) {
logger.debug("AFTER Permissions: "
+ printPermissionsBlock(mask) + " " + printBinary(mask)
+ " (" + mask + ")");
logger.debug("AFTER Permissions: " + printPermissionsBlock(mask) + " " + printBinary(mask) + " ("
+ mask + ")");
}
return this.mask;
}
}
public AclObjectIdentity getAclObjectIdentity() {
return this.aclObjectIdentity;
}
public AclObjectIdentity getAclObjectParentIdentity() {
return this.aclObjectParentIdentity;
}
public int getMask() {
return this.mask;
}
public Object getRecipient() {
return this.recipient;
}
/**
* Outputs the permissions in human-friendly format for the current
* <code>AbstractBasicAclEntry</code>'s mask.
* Subclasses must indicate the permissions they support. Each base permission should be an integer with a
* base 2. ie: the first permission is 2^^0 (1), the second permission is 2^^1 (2), the third permission is 2^^2
* (4) etc. Each base permission should be exposed by the subclass as a <code>public static final int</code>. It
* is further recommended that valid combinations of permissions are also exposed as <code>public static final
* int</code>s.<P>This method returns all permission integers that are allowed to be used together. <B>This
* must include any combinations of valid permissions</b>. So if the permissions indicated by 2^^2 (4) and 2^^1
* (2) can be used together, one of the integers returned by this method must be 6 (4 + 2). Otherwise attempts to
* set the permission will be rejected, as the final resulting mask will be rejected.</p>
* <P>Whilst it may seem unduly time onerous to return every valid permission <B>combination</B>, doing so
* delivers maximum flexibility in ensuring ACLs only reflect logical combinations. For example, it would be
* inappropriate to grant a "read" and "write" permission along with an "unrestricted" permission, as the latter
* implies the former permissions.</p>
*
* @return the human-friendly formatted block for this instance
* @return <b>every</b> valid combination of permissions
*/
public String printPermissionsBlock() {
return printPermissionsBlock(this.mask);
}
public abstract int[] getValidPermissions();
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName());
sb.append("[").append(aclObjectIdentity).append(",").append(recipient);
sb.append("=").append(printPermissionsBlock(mask)).append(" ");
sb.append(printBinary(mask)).append(" (");
sb.append(mask).append(")").append("]");
return sb.toString();
}
public int togglePermission(int permissionToToggle) {
this.mask ^= permissionToToggle;
if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
throw new IllegalArgumentException(
"Resulting permission set will be invalid.");
} else {
return this.mask;
}
public boolean isPermitted(int permissionToCheck) {
return isPermitted(this.mask, permissionToCheck);
}
protected boolean isPermitted(int maskToCheck, int permissionToCheck) {
@ -278,4 +191,61 @@ public abstract class AbstractBasicAclEntry implements BasicAclEntry {
return temp2.replace('0', '.');
}
/**
* Outputs the permissions in a human-friendly format. For example, this method may return "CR-D" to
* indicate the passed integer permits create, permits read, does not permit update, and permits delete.
*
* @param i the integer containing the mask which should be printed
*
* @return the human-friend formatted block
*/
public abstract String printPermissionsBlock(int i);
/**
* Outputs the permissions in human-friendly format for the current <code>AbstractBasicAclEntry</code>'s
* mask.
*
* @return the human-friendly formatted block for this instance
*/
public String printPermissionsBlock() {
return printPermissionsBlock(this.mask);
}
public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity) {
this.aclObjectIdentity = aclObjectIdentity;
}
public void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity) {
this.aclObjectParentIdentity = aclObjectParentIdentity;
}
public void setMask(int mask) {
this.mask = mask;
}
public void setRecipient(Object recipient) {
this.recipient = recipient;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName());
sb.append("[").append(aclObjectIdentity).append(",").append(recipient);
sb.append("=").append(printPermissionsBlock(mask)).append(" ");
sb.append(printBinary(mask)).append(" (");
sb.append(mask).append(")").append("]");
return sb.toString();
}
public int togglePermission(int permissionToToggle) {
this.mask ^= permissionToToggle;
if (Arrays.binarySearch(validPermissions, this.mask) < 0) {
throw new IllegalArgumentException("Resulting permission set will be invalid.");
} else {
return this.mask;
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -44,22 +44,19 @@ import java.io.Serializable;
* @version $Id$
*/
public interface AclObjectIdentity extends Serializable {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Refer to the <code>java.lang.Object</code> documentation for the
* interface contract.
* Refer to the <code>java.lang.Object</code> documentation for the interface contract.
*
* @param obj to be compared
*
* @return <code>true</code> if the objects are equal, <code>false</code>
* otherwise
* @return <code>true</code> if the objects are equal, <code>false</code> otherwise
*/
public boolean equals(Object obj);
/**
* Refer to the <code>java.lang.Object</code> documentation for the
* interface contract.
* Refer to the <code>java.lang.Object</code> documentation for the interface contract.
*
* @return a hash code representation of this object
*/

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -30,13 +30,12 @@ package org.acegisecurity.acl.basic;
* @version $Id$
*/
public interface AclObjectIdentityAware {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Retrieves the <code>AclObjectIdentity</code> for this instance.
*
* @return the ACL object identity for this instance (can never be
* <code>null</code>)
* @return the ACL object identity for this instance (can never be <code>null</code>)
*/
public AclObjectIdentity getAclObjectIdentity();
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -35,24 +35,18 @@ package org.acegisecurity.acl.basic;
* @version $Id$
*/
public interface BasicAclDao {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Obtains the ACLs that apply to the specified domain instance.
*
* <P>
* Does <b>not</b> perform caching, include ACLs from any inheritance
* hierarchy or filter returned objects based on effective permissions.
* Implementations are solely responsible for returning ACLs found in the
* ACL repository for the specified object identity.
* </p>
* Obtains the ACLs that apply to the specified domain instance.<P>Does <b>not</b> perform caching, include
* ACLs from any inheritance hierarchy or filter returned objects based on effective permissions. Implementations
* are solely responsible for returning ACLs found in the ACL repository for the specified object identity.</p>
*
* @param aclObjectIdentity the domain object instance that ACL information
* is being requested for (never <code>null</code>)
* @param aclObjectIdentity the domain object instance that ACL information is being requested for (never
* <code>null</code>)
*
* @return the ACLs that apply (no <code>null</code>s are permitted in the
* array), or <code>null</code> if no ACLs could be found for the
* specified ACL object identity
* @return the ACLs that apply (no <code>null</code>s are permitted in the array), or <code>null</code> if no ACLs
* could be found for the specified ACL object identity
*/
public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -25,50 +25,79 @@ import org.acegisecurity.acl.AclEntry;
* @version $Id$
*/
public interface BasicAclEntry extends AclEntry {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* This setter should <B>only</B> be used by DAO implementations.
* Indicates the domain object instance that is subject of this <code>BasicAclEntry</code>. This
* information may be of interest to relying classes (voters and business methods) that wish to know the actual
* origination of the ACL entry (so as to distinguish individual ACL entries from others contributed by the
* inheritance hierarchy).
*
* @param aclObjectIdentity an object which can be used to uniquely
* identify the domain object instance subject of this ACL entry
*/
public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity);
/**
* Indicates the domain object instance that is subject of this
* <code>BasicAclEntry</code>. This information may be of interest to
* relying classes (voters and business methods) that wish to know the
* actual origination of the ACL entry (so as to distinguish individual
* ACL entries from others contributed by the inheritance hierarchy).
*
* @return the ACL object identity that is subject of this ACL entry (never
* <code>null</code>)
* @return the ACL object identity that is subject of this ACL entry (never <code>null</code>)
*/
public AclObjectIdentity getAclObjectIdentity();
/**
* This setter should <B>only</B> be used by DAO implementations.
* Indicates any ACL parent of the domain object instance. This is used by <code>BasicAclProvider</code> to
* walk the inheritance hierarchy. An domain object instance need <b>not</b> have a parent.
*
* @param aclObjectParentIdentity an object which represents the parent of
* the domain object instance subject of this ACL entry, or
* <code>null</code> if either the domain object instance has no
* parent or its parent should be not used to compute an
* inheritance hierarchy
*/
public void setAclObjectParentIdentity(
AclObjectIdentity aclObjectParentIdentity);
/**
* Indicates any ACL parent of the domain object instance. This is used by
* <code>BasicAclProvider</code> to walk the inheritance hierarchy. An
* domain object instance need <b>not</b> have a parent.
*
* @return the ACL object identity that is the parent of this ACL entry
* (may be <code>null</code> if no parent should be consulted)
* @return the ACL object identity that is the parent of this ACL entry (may be <code>null</code> if no parent
* should be consulted)
*/
public AclObjectIdentity getAclObjectParentIdentity();
/**
* Access control lists in this package are based on bit masking. The integer value of the bit mask can be
* obtained from this method.
*
* @return the bit mask applicable to this ACL entry (zero indicates a bit mask where no permissions have been
* granted)
*/
public int getMask();
/**
* A domain object instance will usually have multiple <code>BasicAclEntry</code>s. Each separate
* <code>BasicAclEntry</code> applies to a particular "recipient". Typical examples of recipients include (but do
* not necessarily have to include) usernames, role names, complex granted authorities etc.<P><B>It is
* essential that only one <code>BasicAclEntry</code> exists for a given recipient</B>. Otherwise conflicts as to
* the mask that should apply to a given recipient will occur.</p>
* <P>This method indicates which recipient this <code>BasicAclEntry</code> applies to. The returned
* object type will vary depending on the type of recipient. For instance, it might be a <code>String</code>
* containing a username, or a <code>GrantedAuthorityImpl</code> containing a complex granted authority that is
* being granted the permissions contained in this access control entry. The {@link EffectiveAclsResolver} and
* {@link BasicAclProvider#getAcls(Object, Authentication)} can process the different recipient types and return
* only those that apply to a specified <code>Authentication</code> object.</p>
*
* @return the recipient of this access control list entry (never <code>null</code>)
*/
public Object getRecipient();
/**
* Determine if the mask of this entry includes this permission or not
*
* @param permissionToCheck
*
* @return if the entry's mask includes this permission
*/
public boolean isPermitted(int permissionToCheck);
/**
* This setter should <B>only</B> be used by DAO implementations.
*
* @param aclObjectIdentity an object which can be used to uniquely identify the domain object instance subject of
* this ACL entry
*/
public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity);
/**
* This setter should <B>only</B> be used by DAO implementations.
*
* @param aclObjectParentIdentity an object which represents the parent of the domain object instance subject of
* this ACL entry, or <code>null</code> if either the domain object instance has no parent or its parent
* should be not used to compute an inheritance hierarchy
*/
public void setAclObjectParentIdentity(AclObjectIdentity aclObjectParentIdentity);
/**
* This setter should <B>only</B> be used by DAO implementations.
*
@ -76,59 +105,11 @@ public interface BasicAclEntry extends AclEntry {
*/
public void setMask(int mask);
/**
* Access control lists in this package are based on bit masking. The
* integer value of the bit mask can be obtained from this method.
*
* @return the bit mask applicable to this ACL entry (zero indicates a bit
* mask where no permissions have been granted)
*/
public int getMask();
/**
* This setter should <B>only</B> be used by DAO implementations.
*
* @param recipient a representation of the recipient of this ACL entry
* that makes sense to an <code>EffectiveAclsResolver</code>
* implementation
* @param recipient a representation of the recipient of this ACL entry that makes sense to an
* <code>EffectiveAclsResolver</code> implementation
*/
public void setRecipient(Object recipient);
/**
* A domain object instance will usually have multiple
* <code>BasicAclEntry</code>s. Each separate <code>BasicAclEntry</code>
* applies to a particular "recipient". Typical examples of recipients
* include (but do not necessarily have to include) usernames, role names,
* complex granted authorities etc.
*
* <P>
* <B>It is essential that only one <code>BasicAclEntry</code> exists for a
* given recipient</B>. Otherwise conflicts as to the mask that should
* apply to a given recipient will occur.
* </p>
*
* <P>
* This method indicates which recipient this <code>BasicAclEntry</code>
* applies to. The returned object type will vary depending on the type of
* recipient. For instance, it might be a <code>String</code> containing a
* username, or a <code>GrantedAuthorityImpl</code> containing a complex
* granted authority that is being granted the permissions contained in
* this access control entry. The {@link EffectiveAclsResolver} and {@link
* BasicAclProvider#getAcls(Object, Authentication)} can process the
* different recipient types and return only those that apply to a
* specified <code>Authentication</code> object.
* </p>
*
* @return the recipient of this access control list entry (never
* <code>null</code>)
*/
public Object getRecipient();
/**
* Determine if the mask of this entry includes this permission or not
*
* @param permissionToCheck
* @return if the entry's mask includes this permission
*/
public boolean isPermitted(int permissionToCheck);
}

View File

@ -31,37 +31,29 @@ package org.acegisecurity.acl.basic;
* @version $Id$
*/
public interface BasicAclEntryCache {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Obtains an array of {@link BasicAclEntry}s from the cache.
*
* @param aclObjectIdentity which should be obtained from the cache
*
* @return any applicable <code>BasicAclEntry</code>s (no
* <code>null</code>s are permitted in the returned array) or
* <code>null</code> if the object identity could not be found or
* if the cache entry has expired
* @return any applicable <code>BasicAclEntry</code>s (no <code>null</code>s are permitted in the returned array)
* or <code>null</code> if the object identity could not be found or if the cache entry has expired
*/
public BasicAclEntry[] getEntriesFromCache(
AclObjectIdentity aclObjectIdentity);
public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity);
/**
* Places an array of {@link BasicAclEntry}s in the cache.
*
* <P>
* No <code>null</code>s are allowed in the passed array. If any
* <code>null</code> is passed, the implementation may throw an exception.
* </p>
* Places an array of {@link BasicAclEntry}s in the cache.<P>No <code>null</code>s are allowed in the
* passed array. If any <code>null</code> is passed, the implementation may throw an exception.</p>
*
* @param basicAclEntry the ACL entries to cache (the key will be extracted
* from the {@link BasicAclEntry#getAclObjectIdentity()} method
* @param basicAclEntry the ACL entries to cache (the key will be extracted from the {@link
* BasicAclEntry#getAclObjectIdentity()} method
*/
public void putEntriesInCache(BasicAclEntry[] basicAclEntry);
/**
* Removes all ACL entries related to an {@link AclObjectIdentity} from the
* cache.
* Removes all ACL entries related to an {@link AclObjectIdentity} from the cache.
*
* @param aclObjectIdentity which should be removed from the cache
*/

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,7 @@ package org.acegisecurity.acl.basic;
import org.springframework.dao.DataAccessException;
/**
* Represents a more extensive data access object
* for {@link BasicAclEntry}s.
@ -30,35 +31,42 @@ import org.springframework.dao.DataAccessException;
* @version $Id$
*/
public interface BasicAclExtendedDao extends BasicAclDao {
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void create(BasicAclEntry basicAclEntry) throws DataAccessException;
/**
* Deletes <b>all</b> entries associated with the
* specified <code>AclObjectIdentity</code>.
*
* @param aclObjectIdentity to delete, including any <code>BasicAclEntry</code>s
*/
public void delete(AclObjectIdentity aclObjectIdentity) throws DataAccessException;
/**
* Deletes the <code>BasicAclEntry</code> associated with the specified
* <code>AclObjectIdentity</code> and recipient <code>Object</code>.
*
* @param aclObjectIdentity to delete
* @param recipient to delete
*/
public void delete(AclObjectIdentity aclObjectIdentity, Object recipient) throws DataAccessException;
/**
* Changes the permission mask assigned to the <code>BasicAclEntry</code>
* associated with the specified
* <code>AclObjectIdentity</code> and recipient <code>Object</code>.
*
* @param aclObjectIdentity to locate the relevant <code>BasicAclEntry</code>
* @param recipient to locate the relevant <code>BasicAclEntry</code>
* @param newMask indicating the new permission
*/
public void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask) throws DataAccessException;
/**
* Changes the permission mask assigned to the <code>BasicAclEntry</code> associated with the specified
* <code>AclObjectIdentity</code> and recipient <code>Object</code>.
*
* @param aclObjectIdentity to locate the relevant <code>BasicAclEntry</code>
* @param recipient to locate the relevant <code>BasicAclEntry</code>
* @param newMask indicating the new permission
*
* @throws DataAccessException DOCUMENT ME!
*/
public void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask)
throws DataAccessException;
public void create(BasicAclEntry basicAclEntry) throws DataAccessException;
/**
* Deletes <b>all</b> entries associated with the specified <code>AclObjectIdentity</code>.
*
* @param aclObjectIdentity to delete, including any <code>BasicAclEntry</code>s
*
* @throws DataAccessException DOCUMENT ME!
*/
public void delete(AclObjectIdentity aclObjectIdentity)
throws DataAccessException;
/**
* Deletes the <code>BasicAclEntry</code> associated with the specified <code>AclObjectIdentity</code> and
* recipient <code>Object</code>.
*
* @param aclObjectIdentity to delete
* @param recipient to delete
*
* @throws DataAccessException DOCUMENT ME!
*/
public void delete(AclObjectIdentity aclObjectIdentity, Object recipient)
throws DataAccessException;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,6 +16,7 @@
package org.acegisecurity.acl.basic;
import org.acegisecurity.Authentication;
import org.acegisecurity.acl.AclEntry;
import org.acegisecurity.acl.AclProvider;
import org.acegisecurity.acl.basic.cache.NullAclEntryCache;
@ -24,6 +25,7 @@ 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.lang.reflect.Constructor;
@ -34,70 +36,59 @@ import java.util.Map;
/**
* <P>
* Retrieves access control lists (ACL) entries for domain object instances
* from a data access object (DAO).
* </p>
*
* <P>
* This implementation will provide ACL lookup services for any object that it
* can determine the {@link AclObjectIdentity} for by calling the {@link
* #obtainIdentity(Object)} method. Subclasses can override this method if
* they only want the <code>BasicAclProvider</code> responding to particular
* domain object instances.
* </p>
*
* <P>
* <code>BasicAclProvider</code> will walk an inheritance hierarchy if a
* <code>BasicAclEntry</code> returned by the DAO indicates it has a parent.
* NB: inheritance occurs at a <I>domain instance object</I> level. It does
* not occur at an ACL recipient level. This means
* <B>all</B><code>BasicAclEntry</code>s for a given domain instance object
* <B>must</B> have the <B>same</B> parent identity, or
* <B>all</B><code>BasicAclEntry</code>s must have <code>null</code> as their
* parent identity.
* </p>
*
* <P>
* A cache should be used. This is provided by the {@link BasicAclEntryCache}.
* <code>BasicAclProvider</code> by default is setup to use the {@link
* NullAclEntryCache}, which performs no caching.
* </p>
*
* <P>
* To implement the {@link #getAcls(Object, Authentication)} method,
* <code>BasicAclProvider</code> requires a {@link EffectiveAclsResolver} to
* be configured against it. By default the {@link
* GrantedAuthorityEffectiveAclsResolver} is used.
* </p>
* <P>Retrieves access control lists (ACL) entries for domain object instances from a data access object (DAO).</p>
* <P>This implementation will provide ACL lookup services for any object that it can determine the {@link
* AclObjectIdentity} for by calling the {@link #obtainIdentity(Object)} method. Subclasses can override this method
* if they only want the <code>BasicAclProvider</code> responding to particular domain object instances.</p>
* <P><code>BasicAclProvider</code> will walk an inheritance hierarchy if a <code>BasicAclEntry</code> returned by
* the DAO indicates it has a parent. NB: inheritance occurs at a <I>domain instance object</I> level. It does not
* occur at an ACL recipient level. This means <B>all</B><code>BasicAclEntry</code>s for a given domain instance
* object <B>must</B> have the <B>same</B> parent identity, or <B>all</B><code>BasicAclEntry</code>s must have
* <code>null</code> as their parent identity.</p>
* <P>A cache should be used. This is provided by the {@link BasicAclEntryCache}. <code>BasicAclProvider</code> by
* default is setup to use the {@link NullAclEntryCache}, which performs no caching.</p>
* <P>To implement the {@link #getAcls(Object, Authentication)} method, <code>BasicAclProvider</code> requires a
* {@link EffectiveAclsResolver} to be configured against it. By default the {@link
* GrantedAuthorityEffectiveAclsResolver} is used.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class BasicAclProvider implements AclProvider, InitializingBean {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(BasicAclProvider.class);
/**
* Marker added to the cache to indicate an AclObjectIdentity has no
* corresponding BasicAclEntry[]s
*/
/** Marker added to the cache to indicate an AclObjectIdentity has no corresponding BasicAclEntry[]s */
private static String RECIPIENT_FOR_CACHE_EMPTY = "RESERVED_RECIPIENT_NOBODY";
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
/**
* Must be set to an appropriate data access object. Defaults to
* <code>null</code>.
*/
/** Must be set to an appropriate data access object. Defaults to <code>null</code>. */
private BasicAclDao basicAclDao;
private BasicAclEntryCache basicAclEntryCache = new NullAclEntryCache();
private Class defaultAclObjectIdentityClass = NamedEntityObjectIdentity.class;
private Class restrictSupportToClass = null;
private EffectiveAclsResolver effectiveAclsResolver = new GrantedAuthorityEffectiveAclsResolver();
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void afterPropertiesSet() {
Assert.notNull(basicAclDao, "basicAclDao required");
Assert.notNull(basicAclEntryCache, "basicAclEntryCache required");
Assert.notNull(basicAclEntryCache, "basicAclEntryCache required");
Assert.notNull(effectiveAclsResolver, "effectiveAclsResolver required");
Assert.notNull(defaultAclObjectIdentityClass, "defaultAclObjectIdentityClass required");
Assert.isTrue(AclObjectIdentity.class.isAssignableFrom(this.defaultAclObjectIdentityClass),
"defaultAclObjectIdentityClass must implement AclObjectIdentity");
try {
Constructor constructor = defaultAclObjectIdentityClass.getConstructor(new Class[] {Object.class});
} catch (NoSuchMethodException nsme) {
throw new IllegalArgumentException(
"defaultAclObjectIdentityClass must provide a constructor that accepts the domain object instance!");
}
}
public AclEntry[] getAcls(Object domainInstance) {
Map map = new HashMap();
@ -120,15 +111,13 @@ public class BasicAclProvider implements AclProvider, InitializingBean {
// Add the leaf objects to the Map, keyed on recipient
for (int i = 0; i < instanceAclEntries.length; i++) {
if (logger.isDebugEnabled()) {
logger.debug("Explicit add: "
+ instanceAclEntries[i].toString());
logger.debug("Explicit add: " + instanceAclEntries[i].toString());
}
map.put(instanceAclEntries[i].getRecipient(), instanceAclEntries[i]);
}
AclObjectIdentity parent = instanceAclEntries[0]
.getAclObjectParentIdentity();
AclObjectIdentity parent = instanceAclEntries[0].getAclObjectParentIdentity();
while (parent != null) {
BasicAclEntry[] parentAclEntries = lookup(parent);
@ -150,16 +139,13 @@ public class BasicAclProvider implements AclProvider, InitializingBean {
for (int i = 0; i < parentAclEntries.length; i++) {
if (!map.containsKey(parentAclEntries[i].getRecipient())) {
if (logger.isDebugEnabled()) {
logger.debug("Added parent to map: "
+ parentAclEntries[i].toString());
logger.debug("Added parent to map: " + parentAclEntries[i].toString());
}
map.put(parentAclEntries[i].getRecipient(),
parentAclEntries[i]);
map.put(parentAclEntries[i].getRecipient(), parentAclEntries[i]);
} else {
if (logger.isDebugEnabled()) {
logger.debug("Did NOT add parent to map: "
+ parentAclEntries[i].toString());
logger.debug("Did NOT add parent to map: " + parentAclEntries[i].toString());
}
}
}
@ -170,211 +156,35 @@ public class BasicAclProvider implements AclProvider, InitializingBean {
Collection collection = map.values();
return (AclEntry[]) collection.toArray(new AclEntry[]{});
return (AclEntry[]) collection.toArray(new AclEntry[] {});
}
public AclEntry[] getAcls(Object domainInstance,
Authentication authentication) {
public AclEntry[] getAcls(Object domainInstance, Authentication authentication) {
AclEntry[] allAcls = (AclEntry[]) this.getAcls(domainInstance);
return this.effectiveAclsResolver.resolveEffectiveAcls(allAcls,
authentication);
}
public void setBasicAclDao(BasicAclDao basicAclDao) {
this.basicAclDao = basicAclDao;
return this.effectiveAclsResolver.resolveEffectiveAcls(allAcls, authentication);
}
public BasicAclDao getBasicAclDao() {
return basicAclDao;
}
public void setBasicAclEntryCache(BasicAclEntryCache basicAclEntryCache) {
this.basicAclEntryCache = basicAclEntryCache;
}
public BasicAclEntryCache getBasicAclEntryCache() {
return basicAclEntryCache;
}
/**
* Allows selection of the <code>AclObjectIdentity</code> class that an
* attempt should be made to construct if the passed object does not
* implement <code>AclObjectIdentityAware</code>.
*
* <P>
* NB: Any <code>defaultAclObjectIdentityClass</code><b>must</b> provide a
* public constructor that accepts an <code>Object</code>. Otherwise it is
* not possible for the <code>BasicAclProvider</code> to try to create the
* <code>AclObjectIdentity</code> instance at runtime.
* </p>
*
* @param defaultAclObjectIdentityClass
*/
public void setDefaultAclObjectIdentityClass(
Class defaultAclObjectIdentityClass) {
this.defaultAclObjectIdentityClass = defaultAclObjectIdentityClass;
}
public Class getDefaultAclObjectIdentityClass() {
return defaultAclObjectIdentityClass;
}
public void setEffectiveAclsResolver(
EffectiveAclsResolver effectiveAclsResolver) {
this.effectiveAclsResolver = effectiveAclsResolver;
}
public EffectiveAclsResolver getEffectiveAclsResolver() {
return effectiveAclsResolver;
}
/**
* If set to a value other than <code>null</code>, the {@link
* #supports(Object)} method will <b>only</b> support the indicates class.
* This is useful if you wish to wire multiple
* <code>BasicAclProvider</code>s in a list of
* <code>AclProviderManager.providers</code> but only have particular
* instances respond to particular domain object types.
*
* @param restrictSupportToClass the class to restrict this
* <code>BasicAclProvider</code> to service request for, or
* <code>null</code> (the default) if the
* <code>BasicAclProvider</code> should respond to every class
* presented
*/
public void setRestrictSupportToClass(Class restrictSupportToClass) {
this.restrictSupportToClass = restrictSupportToClass;
}
public Class getRestrictSupportToClass() {
return restrictSupportToClass;
}
public void afterPropertiesSet() {
Assert.notNull(basicAclDao, "basicAclDao required");
Assert.notNull(basicAclEntryCache, "basicAclEntryCache required");
Assert.notNull(basicAclEntryCache, "basicAclEntryCache required");
Assert.notNull(effectiveAclsResolver, "effectiveAclsResolver required");
Assert.notNull(defaultAclObjectIdentityClass, "defaultAclObjectIdentityClass required");
Assert.isTrue(AclObjectIdentity.class.isAssignableFrom(this.defaultAclObjectIdentityClass),
"defaultAclObjectIdentityClass must implement AclObjectIdentity");
try {
Constructor constructor = defaultAclObjectIdentityClass
.getConstructor(new Class[]{Object.class});
} catch (NoSuchMethodException nsme) {
throw new IllegalArgumentException("defaultAclObjectIdentityClass must provide a constructor that accepts the domain object instance!");
}
}
/**
* Indicates support for the passed object.
*
* <p>
* An object will only be supported if it (i) is allowed to be supported as
* defined by the {@link #setRestrictSupportToClass(Class)} method,
* <b>and</b> (ii) if an <code>AclObjectIdentity</code> is returned by
* {@link #obtainIdentity(Object)} for that object.
* </p>
*
* @param domainInstance the instance to check
*
* @return <code>true</code> if this provider supports the passed object,
* <code>false</code> otherwise
*/
public boolean supports(Object domainInstance) {
if (domainInstance == null) {
if (logger.isDebugEnabled()) {
logger.debug("domainInstance is null");
}
return false;
}
if ((restrictSupportToClass != null)
&& !restrictSupportToClass.isAssignableFrom(
domainInstance.getClass())) {
if (logger.isDebugEnabled()) {
logger.debug("domainInstance not instance of "
+ restrictSupportToClass);
}
return false;
}
if (obtainIdentity(domainInstance) == null) {
if (logger.isDebugEnabled()) {
logger.debug("obtainIdentity returned null");
}
return false;
} else {
if (logger.isDebugEnabled()) {
logger.debug("obtainIdentity returned "
+ obtainIdentity(domainInstance));
}
return true;
}
}
/**
* This method looks up the <code>AclObjectIdentity</code> of a passed
* domain object instance.
*
* <P>
* This implementation attempts to obtain the
* <code>AclObjectIdentity</code> via reflection inspection of the class
* for the {@link AclObjectIdentityAware} interface. If this fails, an
* attempt is made to construct a {@link
* #getDefaultAclObjectIdentityClass()} object by passing the domain
* instance object into its constructor.
* </p>
*
* @param domainInstance the domain object instance (never
* <code>null</code>)
*
* @return an ACL object identity, or <code>null</code> if one could not be
* obtained
*/
protected AclObjectIdentity obtainIdentity(Object domainInstance) {
if (domainInstance instanceof AclObjectIdentityAware) {
AclObjectIdentityAware aclObjectIdentityAware = (AclObjectIdentityAware) domainInstance;
if (logger.isDebugEnabled()) {
logger.debug("domainInstance: " + domainInstance
+ " cast to AclObjectIdentityAware");
}
return aclObjectIdentityAware.getAclObjectIdentity();
}
try {
Constructor constructor = defaultAclObjectIdentityClass
.getConstructor(new Class[] {Object.class});
if (logger.isDebugEnabled()) {
logger.debug("domainInstance: " + domainInstance
+ " attempting to pass to constructor: " + constructor);
}
return (AclObjectIdentity) constructor.newInstance(new Object[] {domainInstance});
} catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error attempting construction of "
+ defaultAclObjectIdentityClass + ": " + ex.getMessage(), ex);
if (ex.getCause() != null) {
logger.debug("Cause: " + ex.getCause().getMessage(),
ex.getCause());
}
}
return null;
}
}
private BasicAclEntry[] lookup(AclObjectIdentity aclObjectIdentity) {
BasicAclEntry[] result = basicAclEntryCache.getEntriesFromCache(aclObjectIdentity);
@ -389,8 +199,9 @@ public class BasicAclProvider implements AclProvider, InitializingBean {
result = basicAclDao.getAcls(aclObjectIdentity);
if (result == null) {
SimpleAclEntry[] emptyAclEntries = {new SimpleAclEntry(RECIPIENT_FOR_CACHE_EMPTY,
aclObjectIdentity, null, 0)};
SimpleAclEntry[] emptyAclEntries = {
new SimpleAclEntry(RECIPIENT_FOR_CACHE_EMPTY, aclObjectIdentity, null, 0)
};
basicAclEntryCache.putEntriesInCache(emptyAclEntries);
return null;
@ -400,4 +211,127 @@ public class BasicAclProvider implements AclProvider, InitializingBean {
return result;
}
/**
* This method looks up the <code>AclObjectIdentity</code> of a passed domain object instance.<P>This
* implementation attempts to obtain the <code>AclObjectIdentity</code> via reflection inspection of the class for
* the {@link AclObjectIdentityAware} interface. If this fails, an attempt is made to construct a {@link
* #getDefaultAclObjectIdentityClass()} object by passing the domain instance object into its constructor.</p>
*
* @param domainInstance the domain object instance (never <code>null</code>)
*
* @return an ACL object identity, or <code>null</code> if one could not be obtained
*/
protected AclObjectIdentity obtainIdentity(Object domainInstance) {
if (domainInstance instanceof AclObjectIdentityAware) {
AclObjectIdentityAware aclObjectIdentityAware = (AclObjectIdentityAware) domainInstance;
if (logger.isDebugEnabled()) {
logger.debug("domainInstance: " + domainInstance + " cast to AclObjectIdentityAware");
}
return aclObjectIdentityAware.getAclObjectIdentity();
}
try {
Constructor constructor = defaultAclObjectIdentityClass.getConstructor(new Class[] {Object.class});
if (logger.isDebugEnabled()) {
logger.debug("domainInstance: " + domainInstance + " attempting to pass to constructor: " + constructor);
}
return (AclObjectIdentity) constructor.newInstance(new Object[] {domainInstance});
} catch (Exception ex) {
if (logger.isDebugEnabled()) {
logger.debug("Error attempting construction of " + defaultAclObjectIdentityClass + ": "
+ ex.getMessage(), ex);
if (ex.getCause() != null) {
logger.debug("Cause: " + ex.getCause().getMessage(), ex.getCause());
}
}
return null;
}
}
public void setBasicAclDao(BasicAclDao basicAclDao) {
this.basicAclDao = basicAclDao;
}
public void setBasicAclEntryCache(BasicAclEntryCache basicAclEntryCache) {
this.basicAclEntryCache = basicAclEntryCache;
}
/**
* Allows selection of the <code>AclObjectIdentity</code> class that an attempt should be made to construct
* if the passed object does not implement <code>AclObjectIdentityAware</code>.<P>NB: Any
* <code>defaultAclObjectIdentityClass</code><b>must</b> provide a public constructor that accepts an
* <code>Object</code>. Otherwise it is not possible for the <code>BasicAclProvider</code> to try to create the
* <code>AclObjectIdentity</code> instance at runtime.</p>
*
* @param defaultAclObjectIdentityClass
*/
public void setDefaultAclObjectIdentityClass(Class defaultAclObjectIdentityClass) {
this.defaultAclObjectIdentityClass = defaultAclObjectIdentityClass;
}
public void setEffectiveAclsResolver(EffectiveAclsResolver effectiveAclsResolver) {
this.effectiveAclsResolver = effectiveAclsResolver;
}
/**
* If set to a value other than <code>null</code>, the {@link #supports(Object)} method will <b>only</b>
* support the indicates class. This is useful if you wish to wire multiple <code>BasicAclProvider</code>s in a
* list of <code>AclProviderManager.providers</code> but only have particular instances respond to particular
* domain object types.
*
* @param restrictSupportToClass the class to restrict this <code>BasicAclProvider</code> to service request for,
* or <code>null</code> (the default) if the <code>BasicAclProvider</code> should respond to every class
* presented
*/
public void setRestrictSupportToClass(Class restrictSupportToClass) {
this.restrictSupportToClass = restrictSupportToClass;
}
/**
* Indicates support for the passed object.<p>An object will only be supported if it (i) is allowed to be
* supported as defined by the {@link #setRestrictSupportToClass(Class)} method, <b>and</b> (ii) if an
* <code>AclObjectIdentity</code> is returned by {@link #obtainIdentity(Object)} for that object.</p>
*
* @param domainInstance the instance to check
*
* @return <code>true</code> if this provider supports the passed object, <code>false</code> otherwise
*/
public boolean supports(Object domainInstance) {
if (domainInstance == null) {
if (logger.isDebugEnabled()) {
logger.debug("domainInstance is null");
}
return false;
}
if ((restrictSupportToClass != null) && !restrictSupportToClass.isAssignableFrom(domainInstance.getClass())) {
if (logger.isDebugEnabled()) {
logger.debug("domainInstance not instance of " + restrictSupportToClass);
}
return false;
}
if (obtainIdentity(domainInstance) == null) {
if (logger.isDebugEnabled()) {
logger.debug("obtainIdentity returned null");
}
return false;
} else {
if (logger.isDebugEnabled()) {
logger.debug("obtainIdentity returned " + obtainIdentity(domainInstance));
}
return true;
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,6 +16,7 @@
package org.acegisecurity.acl.basic;
import org.acegisecurity.Authentication;
import org.acegisecurity.acl.AclEntry;
@ -45,21 +46,16 @@ import org.acegisecurity.acl.AclEntry;
* @version $Id$
*/
public interface EffectiveAclsResolver {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Determines the ACLs that apply to the presented
* <code>Authentication</code> object.
* Determines the ACLs that apply to the presented <code>Authentication</code> object.
*
* @param allAcls every ACL assigned to a domain object instance
* @param filteredBy the principal (populated with
* <code>GrantedAuthority</code>s along with any other members that
* relate to role or group membership) that effective ACLs should
* be returned for
* @param filteredBy the principal (populated with <code>GrantedAuthority</code>s along with any other members that
* relate to role or group membership) that effective ACLs should be returned for
*
* @return the ACLs that apply to the presented principal, or
* <code>null</code> if there are none after filtering
* @return the ACLs that apply to the presented principal, or <code>null</code> if there are none after filtering
*/
public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls,
Authentication filteredBy);
public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls, Authentication filteredBy);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,7 +17,9 @@ package org.acegisecurity.acl.basic;
import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.acl.AclEntry;
import org.acegisecurity.userdetails.UserDetails;
import org.apache.commons.logging.Log;
@ -28,45 +30,29 @@ import java.util.Vector;
/**
* Simple implementation of {@link EffectiveAclsResolver}.
*
* <P>
* This implementation does not need to understand the "recipient" types
* presented in a <code>BasicAclEntry</code> because it merely delegates to
* the detected {@link Authentication#getPrincipal()} or {@link
* Authentication#getAuthorities()}. The principal object or granted
* authorities object has its <code>Object.equals(recipient)</code> method
* called to make the decision as to whether the recipient in the
* <code>BasicAclEntry</code> is the same as the principal or granted
* authority.
* </p>
*
* <P>
* This class should prove an adequate ACLs resolver if you're using standard
* Acegi Security classes. This is because the typical
* <code>Authentication</code> token is
* <code>UsernamePasswordAuthenticationToken</code>, which for its
* <code>principal</code> is usually a <code>String</code>. The
* <code>GrantedAuthorityImpl</code> is typically used for granted
* authorities, which tests for equality based on a <code>String</code>. This
* means <code>BasicAclDao</code>s simply need to return a <code>String</code>
* to represent the recipient. If you use non-<code>String</code> objects, you
* will probably require an alternative <code>EffectiveAclsResolver</code>.
* </p>
* Simple implementation of {@link EffectiveAclsResolver}.<P>This implementation does not need to understand the
* "recipient" types presented in a <code>BasicAclEntry</code> because it merely delegates to the detected {@link
* Authentication#getPrincipal()} or {@link Authentication#getAuthorities()}. The principal object or granted
* authorities object has its <code>Object.equals(recipient)</code> method called to make the decision as to whether
* the recipient in the <code>BasicAclEntry</code> is the same as the principal or granted authority.</p>
* <P>This class should prove an adequate ACLs resolver if you're using standard Acegi Security classes. This is
* because the typical <code>Authentication</code> token is <code>UsernamePasswordAuthenticationToken</code>, which
* for its <code>principal</code> is usually a <code>String</code>. The <code>GrantedAuthorityImpl</code> is typically
* used for granted authorities, which tests for equality based on a <code>String</code>. This means
* <code>BasicAclDao</code>s simply need to return a <code>String</code> to represent the recipient. If you use
* non-<code>String</code> objects, you will probably require an alternative <code>EffectiveAclsResolver</code>.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class GrantedAuthorityEffectiveAclsResolver
implements EffectiveAclsResolver {
//~ Static fields/initializers =============================================
public class GrantedAuthorityEffectiveAclsResolver implements EffectiveAclsResolver {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(GrantedAuthorityEffectiveAclsResolver.class);
//~ Methods ================================================================
//~ Methods ========================================================================================================
public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls,
Authentication filteredBy) {
public AclEntry[] resolveEffectiveAcls(AclEntry[] allAcls, Authentication filteredBy) {
if ((allAcls == null) || (allAcls.length == 0)) {
return null;
}
@ -74,8 +60,7 @@ public class GrantedAuthorityEffectiveAclsResolver
List list = new Vector();
if (logger.isDebugEnabled()) {
logger.debug("Locating AclEntry[]s (from set of "
+ ((allAcls == null) ? 0 : allAcls.length)
logger.debug("Locating AclEntry[]s (from set of " + ((allAcls == null) ? 0 : allAcls.length)
+ ") that apply to Authentication: " + filteredBy);
}
@ -84,26 +69,21 @@ public class GrantedAuthorityEffectiveAclsResolver
continue;
}
Object recipient = ((BasicAclEntry) allAcls[i])
.getRecipient();
Object recipient = ((BasicAclEntry) allAcls[i]).getRecipient();
// Allow the Authentication's getPrincipal to decide whether
// the presented recipient is "equal" (allows BasicAclDaos to
// return Strings rather than proper objects in simple cases)
if (filteredBy.getPrincipal().equals(recipient)) {
if (logger.isDebugEnabled()) {
logger.debug("Principal matches AclEntry recipient: "
+ recipient);
logger.debug("Principal matches AclEntry recipient: " + recipient);
}
list.add(allAcls[i]);
} else if (filteredBy.getPrincipal() instanceof UserDetails
&& ((UserDetails) filteredBy.getPrincipal()).getUsername()
.equals(recipient)) {
&& ((UserDetails) filteredBy.getPrincipal()).getUsername().equals(recipient)) {
if (logger.isDebugEnabled()) {
logger.debug(
"Principal (from UserDetails) matches AclEntry recipient: "
+ recipient);
logger.debug("Principal (from UserDetails) matches AclEntry recipient: " + recipient);
}
list.add(allAcls[i]);
@ -127,8 +107,7 @@ public class GrantedAuthorityEffectiveAclsResolver
for (int k = 0; k < authorities.length; k++) {
if (authorities[k].equals(recipient)) {
if (logger.isDebugEnabled()) {
logger.debug("GrantedAuthority: " + authorities[k]
+ " matches recipient: " + recipient);
logger.debug("GrantedAuthority: " + authorities[k] + " matches recipient: " + recipient);
}
list.add(allAcls[i]);
@ -140,15 +119,13 @@ public class GrantedAuthorityEffectiveAclsResolver
// return null if appropriate (as per interface contract)
if (list.size() > 0) {
if (logger.isDebugEnabled()) {
logger.debug("Returning effective AclEntry array with "
+ list.size() + " elements");
logger.debug("Returning effective AclEntry array with " + list.size() + " elements");
}
return (BasicAclEntry[]) list.toArray(new BasicAclEntry[] {});
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"Returning null AclEntry array as zero effective AclEntrys found");
logger.debug("Returning null AclEntry array as zero effective AclEntrys found");
}
return null;

View File

@ -23,21 +23,16 @@ import java.lang.reflect.Method;
/**
* Simple implementation of {@link AclObjectIdentity}.
*
* <P>
* Uses <code>String</code>s to store the identity of the domain object
* instance. Also offers a constructor that uses reflection to build the
* identity information.
* </p>
* Simple implementation of {@link AclObjectIdentity}.<P>Uses <code>String</code>s to store the identity of the
* domain object instance. Also offers a constructor that uses reflection to build the identity information.</p>
*/
public class NamedEntityObjectIdentity implements AclObjectIdentity {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private String classname;
private String id;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public NamedEntityObjectIdentity(String classname, String id) {
Assert.hasText(classname, "classname required");
@ -46,7 +41,7 @@ public class NamedEntityObjectIdentity implements AclObjectIdentity {
this.id = id;
}
/**
/**
* Creates the <code>NamedEntityObjectIdentity</code> based on the passed
* object instance. The passed object must provide a <code>getId()</code>
* method, otherwise an exception will be thrown.
@ -57,15 +52,13 @@ public class NamedEntityObjectIdentity implements AclObjectIdentity {
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public NamedEntityObjectIdentity(Object object)
throws IllegalAccessException, InvocationTargetException {
public NamedEntityObjectIdentity(Object object) throws IllegalAccessException, InvocationTargetException {
Assert.notNull(object, "object cannot be null");
this.classname = (getPackageName(object.getClass().getName()) == null)
? ClassUtils.getShortName(object.getClass())
: getPackageName(object.getClass().getName()) + "."
+ ClassUtils.getShortName(object.getClass());
? ClassUtils.getShortName(object.getClass())
: (getPackageName(object.getClass().getName()) + "." + ClassUtils.getShortName(object.getClass()));
Class clazz = object.getClass();
try {
@ -78,15 +71,11 @@ public class NamedEntityObjectIdentity implements AclObjectIdentity {
}
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Important so caching operates properly.
*
* <P>
* Considers an object of the same class equal if it has the same
* <code>classname</code> and <code>id</code> properties.
* </p>
* Important so caching operates properly.<P>Considers an object of the same class equal if it has the same
* <code>classname</code> and <code>id</code> properties.</p>
*
* @param arg0 object to compare
*
@ -103,8 +92,7 @@ public class NamedEntityObjectIdentity implements AclObjectIdentity {
NamedEntityObjectIdentity other = (NamedEntityObjectIdentity) arg0;
if (this.getId().equals(other.getId())
&& this.getClassname().equals(other.getClassname())) {
if (this.getId().equals(other.getId()) && this.getClassname().equals(other.getClassname())) {
return true;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -26,7 +26,7 @@ import org.apache.commons.logging.LogFactory;
* @version $Id$
*/
public class SimpleAclEntry extends AbstractBasicAclEntry {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(SimpleAclEntry.class);
@ -39,18 +39,20 @@ public class SimpleAclEntry extends AbstractBasicAclEntry {
public static final int DELETE = (int) Math.pow(2, 4);
// Combinations of base permissions we permit
public static final int READ_WRITE_CREATE_DELETE = READ | WRITE | CREATE
| DELETE;
public static final int READ_WRITE_CREATE_DELETE = READ | WRITE | CREATE | DELETE;
public static final int READ_WRITE_CREATE = READ | WRITE | CREATE;
public static final int READ_WRITE = READ | WRITE;
public static final int READ_WRITE_DELETE = READ | WRITE | DELETE;
// Array required by the abstract superclass via getValidPermissions()
private static final int[] validPermissions = {NOTHING, ADMINISTRATION, READ, WRITE, CREATE, DELETE, READ_WRITE_CREATE_DELETE, READ_WRITE_CREATE, READ_WRITE, READ_WRITE_DELETE};
private static final int[] validPermissions = {
NOTHING, ADMINISTRATION, READ, WRITE, CREATE, DELETE, READ_WRITE_CREATE_DELETE, READ_WRITE_CREATE,
READ_WRITE, READ_WRITE_DELETE
};
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Allows {@link BasicAclDao} implementations to construct this object
* using <code>newInstance()</code>.
*
@ -62,13 +64,12 @@ public class SimpleAclEntry extends AbstractBasicAclEntry {
super();
}
public SimpleAclEntry(Object recipient,
AclObjectIdentity aclObjectIdentity,
public SimpleAclEntry(Object recipient, AclObjectIdentity aclObjectIdentity,
AclObjectIdentity aclObjectParentIdentity, int mask) {
super(recipient, aclObjectIdentity, aclObjectParentIdentity, mask);
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public int[] getValidPermissions() {
return validPermissions;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,36 +17,28 @@ package org.acegisecurity.acl.basic.cache;
import org.acegisecurity.acl.basic.BasicAclEntry;
import java.io.Serializable;
import org.springframework.util.Assert;
import java.io.Serializable;
/**
* Used by {@link EhCacheBasedAclEntryCache} to store the array of
* <code>BasicAclEntry</code>s in the cache.
*
* <P>
* This is necessary because caches store a single object per key, not an
* array.
* </p>
*
* <P>
* This class uses value object semantics. ie: construction-based
* initialisation without any setters for the properties.
* </p>
* Used by {@link EhCacheBasedAclEntryCache} to store the array of <code>BasicAclEntry</code>s in the cache.<P>This
* is necessary because caches store a single object per key, not an array.</p>
* <P>This class uses value object semantics. ie: construction-based initialisation without any setters for the
* properties.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class BasicAclEntryHolder implements Serializable {
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private BasicAclEntry[] basicAclEntries;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructs the <code>BasicAclEntryHolder</code>.
*
* @param aclEntries to cache (any <code>null</code>s will cause an
@ -68,7 +60,7 @@ public class BasicAclEntryHolder implements Serializable {
this.basicAclEntries = aclEntries;
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public BasicAclEntry[] getBasicAclEntries() {
return basicAclEntries;

View File

@ -40,17 +40,16 @@ import org.springframework.util.Assert;
* @author Ben Alex
* @version $Id$
*/
public class EhCacheBasedAclEntryCache implements BasicAclEntryCache,
InitializingBean {
//~ Static fields/initializers =============================================
public class EhCacheBasedAclEntryCache implements BasicAclEntryCache, InitializingBean {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(EhCacheBasedAclEntryCache.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private Cache cache;
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.notNull(cache, "cache mandatory");
@ -60,15 +59,13 @@ public class EhCacheBasedAclEntryCache implements BasicAclEntryCache,
return cache;
}
public BasicAclEntry[] getEntriesFromCache(
AclObjectIdentity aclObjectIdentity) {
public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) {
Element element = null;
try {
element = cache.get(aclObjectIdentity);
} catch (CacheException cacheException) {
throw new DataRetrievalFailureException("Cache failure: "
+ cacheException.getMessage());
throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage());
}
// Return null if cache element has expired or not found
@ -81,8 +78,7 @@ public class EhCacheBasedAclEntryCache implements BasicAclEntryCache,
}
if (logger.isDebugEnabled()) {
logger.debug("Cache hit: " + (element != null) + "; object: "
+ aclObjectIdentity);
logger.debug("Cache hit: " + (element != null) + "; object: " + aclObjectIdentity);
}
BasicAclEntryHolder holder = (BasicAclEntryHolder) element.getValue();
@ -92,8 +88,7 @@ public class EhCacheBasedAclEntryCache implements BasicAclEntryCache,
public void putEntriesInCache(BasicAclEntry[] basicAclEntry) {
BasicAclEntryHolder holder = new BasicAclEntryHolder(basicAclEntry);
Element element = new Element(basicAclEntry[0].getAclObjectIdentity(),
holder);
Element element = new Element(basicAclEntry[0].getAclObjectIdentity(), holder);
if (logger.isDebugEnabled()) {
logger.debug("Cache put: " + element.getKey());

View File

@ -21,29 +21,23 @@ import org.acegisecurity.acl.basic.BasicAclEntryCache;
/**
* Does not perform any caching.
*
* <P>
* <B>Do not use in production settings</B>, as ACL queries are likely to be
* extensive.
* </p>
* Does not perform any caching.<P><B>Do not use in production settings</B>, as ACL queries are likely to be
* extensive.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class NullAclEntryCache implements BasicAclEntryCache {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* As nothing ever stored in the cache, will always return
* <code>null</code>.
* As nothing ever stored in the cache, will always return <code>null</code>.
*
* @param aclObjectIdentity ignored
*
* @return always <code>null</code>
*/
public BasicAclEntry[] getEntriesFromCache(
AclObjectIdentity aclObjectIdentity) {
public BasicAclEntry[] getEntriesFromCache(AclObjectIdentity aclObjectIdentity) {
return null;
}

View File

@ -42,56 +42,48 @@ import javax.sql.DataSource;
/**
* <p>
* Retrieves ACL details from a JDBC location.
* </p>
*
* <p>
* A default database structure is assumed. This may be overridden by setting
* the default query strings to use. If this does not provide enough
* flexibility, another strategy would be to subclass this class and override
* the {@link MappingSqlQuery} instance used, via the {@link
* #initMappingSqlQueries()} extension point.
* </p>
* <p>Retrieves ACL details from a JDBC location.</p>
* <p>A default database structure is assumed. This may be overridden by setting the default query strings to use.
* If this does not provide enough flexibility, another strategy would be to subclass this class and override the
* {@link MappingSqlQuery} instance used, via the {@link #initMappingSqlQueries()} extension point.</p>
*/
public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
public static final String RECIPIENT_USED_FOR_INHERITENCE_MARKER = "___INHERITENCE_MARKER_ONLY___";
public static final String DEF_ACLS_BY_OBJECT_IDENTITY_QUERY = "SELECT RECIPIENT, MASK FROM acl_permission WHERE acl_object_identity = ?";
public static final String DEF_OBJECT_PROPERTIES_QUERY = "SELECT CHILD.ID, CHILD.OBJECT_IDENTITY, CHILD.ACL_CLASS, PARENT.OBJECT_IDENTITY as PARENT_OBJECT_IDENTITY FROM acl_object_identity as CHILD LEFT OUTER JOIN acl_object_identity as PARENT ON CHILD.parent_object=PARENT.id WHERE CHILD.object_identity = ?";
private static final Log logger = LogFactory.getLog(JdbcDaoImpl.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
protected MappingSqlQuery aclsByObjectIdentity;
protected MappingSqlQuery objectProperties;
private String aclsByObjectIdentityQuery;
private String objectPropertiesQuery;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public JdbcDaoImpl() {
aclsByObjectIdentityQuery = DEF_ACLS_BY_OBJECT_IDENTITY_QUERY;
objectPropertiesQuery = DEF_OBJECT_PROPERTIES_QUERY;
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Responsible for covering a <code>AclObjectIdentity</code> to a
* <code>String</code> that can be located in the RDBMS.
* Responsible for covering a <code>AclObjectIdentity</code> to a <code>String</code> that can be located
* in the RDBMS.
*
* @param aclObjectIdentity to locate
*
* @return the object identity as a <code>String</code>
*/
protected String convertAclObjectIdentityToString(
AclObjectIdentity aclObjectIdentity) {
protected String convertAclObjectIdentityToString(AclObjectIdentity aclObjectIdentity) {
// Ensure we can process this type of AclObjectIdentity
Assert.isInstanceOf(NamedEntityObjectIdentity.class, aclObjectIdentity,
"Only aclObjectIdentity of type NamedEntityObjectIdentity supported (was passed: "
+ aclObjectIdentity + ")");
"Only aclObjectIdentity of type NamedEntityObjectIdentity supported (was passed: " + aclObjectIdentity
+ ")");
NamedEntityObjectIdentity neoi = (NamedEntityObjectIdentity) aclObjectIdentity;
@ -100,37 +92,26 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
}
/**
* Constructs an individual <code>BasicAclEntry</code> from the passed
* <code>AclDetailsHolder</code>s.
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are thrown in
* the event of any issues).
* </p>
* Constructs an individual <code>BasicAclEntry</code> from the passed <code>AclDetailsHolder</code>s.<P>Guarantees
* to never return <code>null</code> (exceptions are thrown in the event of any issues).</p>
*
* @param propertiesInformation mandatory information about which instance
* to create, the object identity, and the parent object identity
* (<code>null</code> or empty <code>String</code>s prohibited for
* @param propertiesInformation mandatory information about which instance to create, the object identity, and the
* parent object identity (<code>null</code> or empty <code>String</code>s prohibited for
* <code>aclClass</code> and <code>aclObjectIdentity</code>
* @param aclInformation optional information about the individual ACL
* record (if <code>null</code> only an "inheritence marker"
* instance is returned which will include a recipient of {@link
* #RECIPIENT_USED_FOR_INHERITENCE_MARKER} ; if not
* <code>null</code>, it is prohibited to present <code>null</code>
* or an empty <code>String</code> for <code>recipient</code>)
* @param aclInformation optional information about the individual ACL record (if <code>null</code> only an
* "inheritence marker" instance is returned which will include a recipient of {@link
* #RECIPIENT_USED_FOR_INHERITENCE_MARKER} ; if not <code>null</code>, it is prohibited to present
* <code>null</code> or an empty <code>String</code> for <code>recipient</code>)
*
* @return a fully populated instance suitable for use by external objects
*
* @throws IllegalArgumentException if the indicated ACL class could not be
* created
* @throws IllegalArgumentException if the indicated ACL class could not be created
*/
private BasicAclEntry createBasicAclEntry(
AclDetailsHolder propertiesInformation, AclDetailsHolder aclInformation) {
private BasicAclEntry createBasicAclEntry(AclDetailsHolder propertiesInformation, AclDetailsHolder aclInformation) {
BasicAclEntry entry;
try {
entry = (BasicAclEntry) propertiesInformation.getAclClass()
.newInstance();
entry = (BasicAclEntry) propertiesInformation.getAclClass().newInstance();
} catch (InstantiationException ie) {
throw new IllegalArgumentException(ie.getMessage());
} catch (IllegalAccessException iae) {
@ -138,8 +119,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
}
entry.setAclObjectIdentity(propertiesInformation.getAclObjectIdentity());
entry.setAclObjectParentIdentity(propertiesInformation
.getAclObjectParentIdentity());
entry.setAclObjectParentIdentity(propertiesInformation.getAclObjectParentIdentity());
if (aclInformation == null) {
// this is an inheritence marker instance only
@ -155,30 +135,19 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
}
/**
* Returns the ACLs associated with the requested
* <code>AclObjectIdentity</code>.
*
* <P>
* The {@link BasicAclEntry}s returned by this method will have
* <code>String</code>-based recipients. This will not be a problem if you
* are using the <code>GrantedAuthorityEffectiveAclsResolver</code>, which
* is the default configured against <code>BasicAclProvider</code>.
* </p>
*
* <P>
* This method will only return ACLs for requests where the
* <code>AclObjectIdentity</code> is of type {@link
* NamedEntityObjectIdentity}. Of course, you can subclass or replace this
* class and support your own custom <code>AclObjectIdentity</code> types.
* </p>
* Returns the ACLs associated with the requested <code>AclObjectIdentity</code>.<P>The {@link
* BasicAclEntry}s returned by this method will have <code>String</code>-based recipients. This will not be a
* problem if you are using the <code>GrantedAuthorityEffectiveAclsResolver</code>, which is the default
* configured against <code>BasicAclProvider</code>.</p>
* <P>This method will only return ACLs for requests where the <code>AclObjectIdentity</code> is of type
* {@link NamedEntityObjectIdentity}. Of course, you can subclass or replace this class and support your own
* custom <code>AclObjectIdentity</code> types.</p>
*
* @param aclObjectIdentity for which ACL information is required (cannot
* be <code>null</code> and must be an instance of
* <code>NamedEntityObjectIdentity</code>)
* @param aclObjectIdentity for which ACL information is required (cannot be <code>null</code> and must be an
* instance of <code>NamedEntityObjectIdentity</code>)
*
* @return the ACLs that apply (without any <code>null</code>s inside the
* array), or <code>null</code> if not found or if an incompatible
* <code>AclObjectIdentity</code> was requested
* @return the ACLs that apply (without any <code>null</code>s inside the array), or <code>null</code> if not found
* or if an incompatible <code>AclObjectIdentity</code> was requested
*/
public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity) {
String aclObjectIdentityString;
@ -201,21 +170,18 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
AclDetailsHolder propertiesInformation = (AclDetailsHolder) objects.get(0);
// Lookup the object's ACLs from RDBMS (guaranteed no nulls)
List acls = aclsByObjectIdentity.execute(propertiesInformation
.getForeignKeyId());
List acls = aclsByObjectIdentity.execute(propertiesInformation.getForeignKeyId());
if (acls.size() == 0) {
// return merely an inheritence marker (as we know about the object but it has no related ACLs)
return new BasicAclEntry[] {createBasicAclEntry(propertiesInformation,
null)};
return new BasicAclEntry[] {createBasicAclEntry(propertiesInformation, null)};
} else {
// return the individual ACL instances
AclDetailsHolder[] aclHolders = (AclDetailsHolder[]) acls.toArray(new AclDetailsHolder[] {});
List toReturnAcls = new Vector();
for (int i = 0; i < aclHolders.length; i++) {
toReturnAcls.add(createBasicAclEntry(propertiesInformation,
aclHolders[i]));
toReturnAcls.add(createBasicAclEntry(propertiesInformation, aclHolders[i]));
}
return (BasicAclEntry[]) toReturnAcls.toArray(new BasicAclEntry[] {});
@ -239,26 +205,22 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
}
/**
* Extension point to allow other MappingSqlQuery objects to be substituted
* in a subclass
* Extension point to allow other MappingSqlQuery objects to be substituted in a subclass
*/
protected void initMappingSqlQueries() {
setAclsByObjectIdentity(new AclsByObjectIdentityMapping(getDataSource()));
setObjectProperties(new ObjectPropertiesMapping(getDataSource()));
}
public void setAclsByObjectIdentity(
MappingSqlQuery aclsByObjectIdentityQuery) {
public void setAclsByObjectIdentity(MappingSqlQuery aclsByObjectIdentityQuery) {
this.aclsByObjectIdentity = aclsByObjectIdentityQuery;
}
/**
* Allows the default query string used to retrieve ACLs based on object
* identity to be overriden, if default table or column names need to be
* changed. The default query is {@link
* #DEF_ACLS_BY_OBJECT_IDENTITY_QUERY}; when modifying this query, ensure
* that all returned columns are mapped back to the same column names as
* in the default query.
* Allows the default query string used to retrieve ACLs based on object identity to be overriden, if
* default table or column names need to be changed. The default query is {@link
* #DEF_ACLS_BY_OBJECT_IDENTITY_QUERY}; when modifying this query, ensure that all returned columns are mapped
* back to the same column names as in the default query.
*
* @param queryString The query string to set
*/
@ -274,22 +236,14 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
objectPropertiesQuery = queryString;
}
//~ Inner Classes ==========================================================
//~ Inner Classes ==================================================================================================
/**
* Used to hold details of a domain object instance's properties, or an
* individual ACL entry.
*
* <P>
* Not all properties will be set. The actual properties set will depend on
* which <code>MappingSqlQuery</code> creates the object.
* </p>
*
* <P>
* Does not enforce <code>null</code>s or empty <code>String</code>s as
* this is performed by the <code>MappingSqlQuery</code> objects (or
* preferably the backend RDBMS via schema constraints).
* </p>
* Used to hold details of a domain object instance's properties, or an individual ACL entry.<P>Not all
* properties will be set. The actual properties set will depend on which <code>MappingSqlQuery</code> creates the
* object.</p>
* <P>Does not enforce <code>null</code>s or empty <code>String</code>s as this is performed by the
* <code>MappingSqlQuery</code> objects (or preferably the backend RDBMS via schema constraints).</p>
*/
protected final class AclDetailsHolder {
private AclObjectIdentity aclObjectIdentity;
@ -299,7 +253,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
private int mask;
private long foreignKeyId;
/**
/**
* Record details of an individual ACL entry (usually from the
* ACL_PERMISSION table)
*
@ -311,7 +265,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
this.mask = mask;
}
/**
/**
* Record details of a domain object instance's properties (usually
* from the ACL_OBJECT_IDENTITY table)
*
@ -326,8 +280,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
* created for each individual ACL entry (or an inheritence
* "holder" class if there are no ACL entries)
*/
public AclDetailsHolder(long foreignKeyId,
AclObjectIdentity aclObjectIdentity,
public AclDetailsHolder(long foreignKeyId, AclObjectIdentity aclObjectIdentity,
AclObjectIdentity aclObjectParentIdentity, Class aclClass) {
this.foreignKeyId = foreignKeyId;
this.aclObjectIdentity = aclObjectIdentity;
@ -361,21 +314,11 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
}
/**
* Query object to look up individual ACL entries.
*
* <P>
* Returns the generic <code>AclDetailsHolder</code> object.
* </p>
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are thrown in
* the event of any issues).
* </p>
*
* <P>
* The executed SQL requires the following information be made available
* from the indicated placeholders: 1. RECIPIENT, 2. MASK.
* </p>
* Query object to look up individual ACL entries.<P>Returns the generic <code>AclDetailsHolder</code>
* object.</p>
* <P>Guarantees to never return <code>null</code> (exceptions are thrown in the event of any issues).</p>
* <P>The executed SQL requires the following information be made available from the indicated
* placeholders: 1. RECIPIENT, 2. MASK.</p>
*/
protected class AclsByObjectIdentityMapping extends MappingSqlQuery {
protected AclsByObjectIdentityMapping(DataSource ds) {
@ -395,22 +338,11 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
}
/**
* Query object to look up properties for an object identity.
*
* <P>
* Returns the generic <code>AclDetailsHolder</code> object.
* </p>
*
* <P>
* Guarantees to never return <code>null</code> (exceptions are thrown in
* the event of any issues).
* </p>
*
* <P>
* The executed SQL requires the following information be made available
* from the indicated placeholders: 1. ID, 2. OBJECT_IDENTITY, 3.
* ACL_CLASS and 4. PARENT_OBJECT_IDENTITY.
* </p>
* Query object to look up properties for an object identity.<P>Returns the generic
* <code>AclDetailsHolder</code> object.</p>
* <P>Guarantees to never return <code>null</code> (exceptions are thrown in the event of any issues).</p>
* <P>The executed SQL requires the following information be made available from the indicated
* placeholders: 1. ID, 2. OBJECT_IDENTITY, 3. ACL_CLASS and 4. PARENT_OBJECT_IDENTITY.</p>
*/
protected class ObjectPropertiesMapping extends MappingSqlQuery {
protected ObjectPropertiesMapping(DataSource ds) {
@ -440,8 +372,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
String parentObjectIdentity = rs.getString(4); // optional
Assert.hasText(objectIdentity,
"required DEF_OBJECT_PROPERTIES_QUERY value (objectIdentity) returned null or empty");
Assert.hasText(aclClass,
"required DEF_OBJECT_PROPERTIES_QUERY value (aclClass) returned null or empty");
Assert.hasText(aclClass, "required DEF_OBJECT_PROPERTIES_QUERY value (aclClass) returned null or empty");
Class aclClazz;
@ -451,8 +382,7 @@ public class JdbcDaoImpl extends JdbcDaoSupport implements BasicAclDao {
throw new IllegalArgumentException(cnf.getMessage());
}
return new AclDetailsHolder(id, buildIdentity(objectIdentity),
buildIdentity(parentObjectIdentity), aclClazz);
return new AclDetailsHolder(id, buildIdentity(objectIdentity), buildIdentity(parentObjectIdentity), aclClazz);
}
}
}

View File

@ -47,36 +47,20 @@ import javax.sql.DataSource;
/**
* <p>
* Extension of the base {@link JdbcDaoImpl}, which implements {@link
* BasicAclExtendedDao}.
* </p>
*
* <p>
* A default database structure is assumed. This may be overridden by setting
* the default query strings to use.
* </p>
*
* <p>
* If you are using a cache with <code>BasicAclProvider</code>, you should
* specify that cache via {@link #setBasicAclEntryCache(BasicAclEntryCache)}.
* This will cause cache evictions (removals) to take place whenever a DAO
* mutator method is called.
* </p>
*
* <p>
* This implementation works with <code>String</code> based recipients and
* {@link org.acegisecurity.acl.basic.NamedEntityObjectIdentity} only. The
* latter can be changed by overriding {@link
* #convertAclObjectIdentityToString(AclObjectIdentity)}.
* </p>
* <p>Extension of the base {@link JdbcDaoImpl}, which implements {@link BasicAclExtendedDao}.</p>
* <p>A default database structure is assumed. This may be overridden by setting the default query strings to use.</p>
* <p>If you are using a cache with <code>BasicAclProvider</code>, you should specify that cache via {@link
* #setBasicAclEntryCache(BasicAclEntryCache)}. This will cause cache evictions (removals) to take place whenever a
* DAO mutator method is called.</p>
* <p>This implementation works with <code>String</code> based recipients and {@link
* org.acegisecurity.acl.basic.NamedEntityObjectIdentity} only. The latter can be changed by overriding {@link
* #convertAclObjectIdentityToString(AclObjectIdentity)}.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class JdbcExtendedDaoImpl extends JdbcDaoImpl
implements BasicAclExtendedDao {
//~ Static fields/initializers =============================================
public class JdbcExtendedDaoImpl extends JdbcDaoImpl implements BasicAclExtendedDao {
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(JdbcExtendedDaoImpl.class);
public static final String DEF_ACL_OBJECT_IDENTITY_DELETE_STATEMENT = "DELETE FROM acl_object_identity WHERE id = ?";
@ -86,7 +70,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
public static final String DEF_ACL_PERMISSION_UPDATE_STATEMENT = "UPDATE acl_permission SET mask = ? WHERE id = ?";
public static final String DEF_LOOKUP_PERMISSION_ID_QUERY = "SELECT id FROM acl_permission WHERE acl_object_identity = ? AND recipient = ?";
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private AclObjectIdentityDelete aclObjectIdentityDelete;
private AclObjectIdentityInsert aclObjectIdentityInsert;
@ -102,7 +86,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
private String aclPermissionUpdateStatement;
private String lookupPermissionIdQuery;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public JdbcExtendedDaoImpl() {
aclObjectIdentityDeleteStatement = DEF_ACL_OBJECT_IDENTITY_DELETE_STATEMENT;
@ -113,22 +97,20 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
lookupPermissionIdQuery = DEF_LOOKUP_PERMISSION_ID_QUERY;
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void changeMask(AclObjectIdentity aclObjectIdentity,
Object recipient, Integer newMask) throws DataAccessException {
public void changeMask(AclObjectIdentity aclObjectIdentity, Object recipient, Integer newMask)
throws DataAccessException {
basicAclEntryCache.removeEntriesFromCache(aclObjectIdentity);
// Retrieve acl_object_identity record details
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity);
// Retrieve applicable acl_permission.id
long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(),
recipient.toString());
long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(), recipient.toString());
if (permissionId == -1) {
throw new DataRetrievalFailureException(
"Could not locate existing acl_permission for aclObjectIdentity: "
throw new DataRetrievalFailureException("Could not locate existing acl_permission for aclObjectIdentity: "
+ aclObjectIdentity + ", recipient: " + recipient.toString());
}
@ -147,59 +129,48 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
}
// Retrieve acl_object_identity record details
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(basicAclEntry
.getAclObjectIdentity());
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(basicAclEntry.getAclObjectIdentity());
// Ensure there isn't an existing record for this recipient
long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(),
basicAclEntry.getRecipient());
long permissionId = lookupPermissionId(aclDetailsHolder.getForeignKeyId(), basicAclEntry.getRecipient());
if (permissionId != -1) {
throw new DataIntegrityViolationException("Recipient '"
+ basicAclEntry.getRecipient()
+ "' already exists for aclObjectIdentity ID "
+ aclDetailsHolder.getForeignKeyId() + " (permission ID " + ")");
throw new DataIntegrityViolationException("Recipient '" + basicAclEntry.getRecipient()
+ "' already exists for aclObjectIdentity ID " + aclDetailsHolder.getForeignKeyId()
+ " (permission ID " + ")");
}
// Create acl_permission
aclPermissionInsert.insert(new Long(aclDetailsHolder.getForeignKeyId()),
basicAclEntry.getRecipient().toString(),
new Integer(basicAclEntry.getMask()));
basicAclEntry.getRecipient().toString(), new Integer(basicAclEntry.getMask()));
}
/**
* Convenience method that creates an acl_object_identity record if
* required.
* Convenience method that creates an acl_object_identity record if required.
*
* @param basicAclEntry containing the <code>AclObjectIdentity</code> to
* create
* @param basicAclEntry containing the <code>AclObjectIdentity</code> to create
*
* @throws DataAccessException
*/
private void createAclObjectIdentityIfRequired(BasicAclEntry basicAclEntry)
throws DataAccessException {
basicAclEntryCache.removeEntriesFromCache(basicAclEntry
.getAclObjectIdentity());
basicAclEntryCache.removeEntriesFromCache(basicAclEntry.getAclObjectIdentity());
String aclObjectIdentityString = convertAclObjectIdentityToString(basicAclEntry
.getAclObjectIdentity());
String aclObjectIdentityString = convertAclObjectIdentityToString(basicAclEntry.getAclObjectIdentity());
// Lookup the object's main properties from the RDBMS (guaranteed no nulls)
List objects = objectProperties.execute(aclObjectIdentityString);
if (objects.size() == 0) {
if (basicAclEntry.getAclObjectParentIdentity() != null) {
AclDetailsHolder parentDetails = lookupAclDetailsHolder(basicAclEntry
.getAclObjectParentIdentity());
AclDetailsHolder parentDetails = lookupAclDetailsHolder(basicAclEntry.getAclObjectParentIdentity());
// Must create the acl_object_identity record
aclObjectIdentityInsert.insert(aclObjectIdentityString,
new Long(parentDetails.getForeignKeyId()),
aclObjectIdentityInsert.insert(aclObjectIdentityString, new Long(parentDetails.getForeignKeyId()),
basicAclEntry.getClass().getName());
} else {
// Must create the acl_object_identity record
aclObjectIdentityInsert.insert(aclObjectIdentityString, null,
basicAclEntry.getClass().getName());
aclObjectIdentityInsert.insert(aclObjectIdentityString, null, basicAclEntry.getClass().getName());
}
}
}
@ -212,8 +183,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity);
// Retrieve all acl_permissions applying to this acl_object_identity
Iterator acls = aclsByObjectIdentity.execute(aclDetailsHolder
.getForeignKeyId()).iterator();
Iterator acls = aclsByObjectIdentity.execute(aclDetailsHolder.getForeignKeyId()).iterator();
// Delete all existing acl_permissions applying to this acl_object_identity
while (acls.hasNext()) {
@ -222,8 +192,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
}
// Delete acl_object_identity
aclObjectIdentityDelete.delete(new Long(
aclDetailsHolder.getForeignKeyId()));
aclObjectIdentityDelete.delete(new Long(aclDetailsHolder.getForeignKeyId()));
}
public void delete(AclObjectIdentity aclObjectIdentity, Object recipient)
@ -234,8 +203,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
AclDetailsHolder aclDetailsHolder = lookupAclDetailsHolder(aclObjectIdentity);
// Delete acl_permission
aclPermissionDelete.delete(new Long(aclDetailsHolder.getForeignKeyId()),
recipient.toString());
aclPermissionDelete.delete(new Long(aclDetailsHolder.getForeignKeyId()), recipient.toString());
}
public AclObjectIdentityDelete getAclObjectIdentityDelete() {
@ -309,8 +277,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
*
* @throws DataRetrievalFailureException if record could not be found
*/
private AclDetailsHolder lookupAclDetailsHolder(
AclObjectIdentity aclObjectIdentity)
private AclDetailsHolder lookupAclDetailsHolder(AclObjectIdentity aclObjectIdentity)
throws DataRetrievalFailureException {
String aclObjectIdentityString = convertAclObjectIdentityToString(aclObjectIdentity);
@ -318,8 +285,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
List objects = objectProperties.execute(aclObjectIdentityString);
if (objects.size() == 0) {
throw new DataRetrievalFailureException(
"aclObjectIdentity not found: " + aclObjectIdentityString);
throw new DataRetrievalFailureException("aclObjectIdentity not found: " + aclObjectIdentityString);
}
// Should only be one record
@ -327,8 +293,8 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
}
/**
* Convenience method to lookup the acl_permission applying to a given
* acl_object_identity.id and acl_permission.recipient.
* Convenience method to lookup the acl_permission applying to a given acl_object_identity.id and
* acl_permission.recipient.
*
* @param aclObjectIdentityId to locate
* @param recipient to locate
@ -339,8 +305,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
*/
private long lookupPermissionId(long aclObjectIdentityId, Object recipient)
throws DataAccessException {
List list = lookupPermissionIdMapping.execute(new Object[] {new Long(
aclObjectIdentityId), recipient});
List list = lookupPermissionIdMapping.execute(new Object[] {new Long(aclObjectIdentityId), recipient});
if (list.size() == 0) {
return -1;
@ -349,23 +314,19 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
return ((Long) list.get(0)).longValue();
}
public void setAclObjectIdentityDelete(
AclObjectIdentityDelete aclObjectIdentityDelete) {
public void setAclObjectIdentityDelete(AclObjectIdentityDelete aclObjectIdentityDelete) {
this.aclObjectIdentityDelete = aclObjectIdentityDelete;
}
public void setAclObjectIdentityDeleteStatement(
String aclObjectIdentityDeleteStatement) {
public void setAclObjectIdentityDeleteStatement(String aclObjectIdentityDeleteStatement) {
this.aclObjectIdentityDeleteStatement = aclObjectIdentityDeleteStatement;
}
public void setAclObjectIdentityInsert(
AclObjectIdentityInsert aclObjectIdentityInsert) {
public void setAclObjectIdentityInsert(AclObjectIdentityInsert aclObjectIdentityInsert) {
this.aclObjectIdentityInsert = aclObjectIdentityInsert;
}
public void setAclObjectIdentityInsertStatement(
String aclObjectIdentityInsertStatement) {
public void setAclObjectIdentityInsertStatement(String aclObjectIdentityInsertStatement) {
this.aclObjectIdentityInsertStatement = aclObjectIdentityInsertStatement;
}
@ -373,8 +334,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
this.aclPermissionDelete = aclPermissionDelete;
}
public void setAclPermissionDeleteStatement(
String aclPermissionDeleteStatement) {
public void setAclPermissionDeleteStatement(String aclPermissionDeleteStatement) {
this.aclPermissionDeleteStatement = aclPermissionDeleteStatement;
}
@ -382,8 +342,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
this.aclPermissionInsert = aclPermissionInsert;
}
public void setAclPermissionInsertStatement(
String aclPermissionInsertStatement) {
public void setAclPermissionInsertStatement(String aclPermissionInsertStatement) {
this.aclPermissionInsertStatement = aclPermissionInsertStatement;
}
@ -391,8 +350,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
this.aclPermissionUpdate = aclPermissionUpdate;
}
public void setAclPermissionUpdateStatement(
String aclPermissionUpdateStatement) {
public void setAclPermissionUpdateStatement(String aclPermissionUpdateStatement) {
this.aclPermissionUpdateStatement = aclPermissionUpdateStatement;
}
@ -401,8 +359,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
this.basicAclEntryCache = basicAclEntryCache;
}
public void setLookupPermissionIdMapping(
MappingSqlQuery lookupPermissionIdMapping) {
public void setLookupPermissionIdMapping(MappingSqlQuery lookupPermissionIdMapping) {
this.lookupPermissionIdMapping = lookupPermissionIdMapping;
}
@ -410,7 +367,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
this.lookupPermissionIdQuery = lookupPermissionIdQuery;
}
//~ Inner Classes ==========================================================
//~ Inner Classes ==================================================================================================
protected class AclObjectIdentityDelete extends SqlUpdate {
protected AclObjectIdentityDelete(DataSource ds) {
@ -419,8 +376,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
compile();
}
protected void delete(Long aclObjectIdentity)
throws DataAccessException {
protected void delete(Long aclObjectIdentity) throws DataAccessException {
super.update(aclObjectIdentity.intValue());
}
}
@ -434,8 +390,7 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
compile();
}
protected void insert(String objectIdentity,
Long parentAclObjectIdentity, String aclClass)
protected void insert(String objectIdentity, Long parentAclObjectIdentity, String aclClass)
throws DataAccessException {
Object[] objs = new Object[] {objectIdentity, parentAclObjectIdentity, aclClass};
super.update(objs);
@ -465,8 +420,8 @@ public class JdbcExtendedDaoImpl extends JdbcDaoImpl
compile();
}
protected void insert(Long aclObjectIdentity, String recipient,
Integer mask) throws DataAccessException {
protected void insert(Long aclObjectIdentity, String recipient, Integer mask)
throws DataAccessException {
Object[] objs = new Object[] {aclObjectIdentity, recipient, mask};
super.update(objs);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,6 +16,7 @@
package org.acegisecurity.adapters;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.providers.AbstractAuthenticationToken;
@ -25,19 +26,18 @@ import org.acegisecurity.providers.AbstractAuthenticationToken;
* @author Ben Alex
* @version $Id$
*/
public abstract class AbstractAdapterAuthenticationToken
extends AbstractAuthenticationToken implements AuthByAdapter {
//~ Instance fields ========================================================
public abstract class AbstractAdapterAuthenticationToken extends AbstractAuthenticationToken implements AuthByAdapter {
//~ Instance fields ================================================================================================
private int keyHash;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
protected AbstractAdapterAuthenticationToken() {
super(null);
}
/**
/**
* The only way an <code>AbstractAdapterAuthentication</code> should be
* constructed.
*
@ -45,62 +45,12 @@ public abstract class AbstractAdapterAuthenticationToken
* #getKeyHash()}
* @param authorities the authorities granted to this principal
*/
protected AbstractAdapterAuthenticationToken(String key,
GrantedAuthority[] authorities) {
protected AbstractAdapterAuthenticationToken(String key, GrantedAuthority[] authorities) {
super(authorities);
this.keyHash = key.hashCode();
}
//~ Methods ================================================================
/**
* Setting is ignored. Always considered authenticated.
*
* @param ignored DOCUMENT ME!
*/
public void setAuthenticated(boolean ignored) {
// ignored
}
/**
* Always returns <code>true</code>.
*
* @return DOCUMENT ME!
*/
public boolean isAuthenticated() {
return true;
}
public int getKeyHash() {
return this.keyHash;
}
/**
* Iterates the granted authorities and indicates whether or not the
* specified role is held.
*
* <p>
* Comparison is based on the <code>String</code> returned by {@link
* GrantedAuthority#getAuthority}.
* </p>
*
* @param role the role being searched for in this object's granted
* authorities list
*
* @return <code>true</code> if the granted authority is held, or
* <code>false</code> otherwise
*/
public boolean isUserInRole(String role) {
GrantedAuthority[] authorities = super.getAuthorities();
for (int i = 0; i < authorities.length; i++) {
if (role.equals(authorities[i].getAuthority())) {
return true;
}
}
return false;
}
//~ Methods ========================================================================================================
public boolean equals(Object obj) {
if (obj instanceof AbstractAdapterAuthenticationToken) {
@ -115,4 +65,46 @@ public abstract class AbstractAdapterAuthenticationToken
return false;
}
public int getKeyHash() {
return this.keyHash;
}
/**
* Always returns <code>true</code>.
*
* @return DOCUMENT ME!
*/
public boolean isAuthenticated() {
return true;
}
/**
* Iterates the granted authorities and indicates whether or not the specified role is held.<p>Comparison
* is based on the <code>String</code> returned by {@link GrantedAuthority#getAuthority}.</p>
*
* @param role the role being searched for in this object's granted authorities list
*
* @return <code>true</code> if the granted authority is held, or <code>false</code> otherwise
*/
public boolean isUserInRole(String role) {
GrantedAuthority[] authorities = super.getAuthorities();
for (int i = 0; i < authorities.length; i++) {
if (role.equals(authorities[i].getAuthority())) {
return true;
}
}
return false;
}
/**
* Setting is ignored. Always considered authenticated.
*
* @param ignored DOCUMENT ME!
*/
public void setAuthenticated(boolean ignored) {
// ignored
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,13 +32,12 @@ import org.acegisecurity.Authentication;
* @version $Id$
*/
public interface AuthByAdapter extends Authentication {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Returns the hash code of the key that was passed to the constructor of
* the <code>AuthByAdapter</code> implementation. The implementation
* should convert the value to a hash code at construction time, rather
* than storing the key itself.
* Returns the hash code of the key that was passed to the constructor of the <code>AuthByAdapter</code>
* implementation. The implementation should convert the value to a hash code at construction time, rather than
* storing the key itself.
*
* @return the hash code of the key used when the object was created.
*/

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,32 +32,22 @@ import org.springframework.util.Assert;
/**
* An {@link AuthenticationProvider} implementation that can authenticate an
* {@link AuthByAdapter}.
*
* <P>
* Configured in the bean context with a key that should match the key used by
* adapters to generate <code>AuthByAdapter</code> instances. It treats as
* valid any such instance presenting a hash code that matches the
* <code>AuthByAdapterProvider</code>-configured key.
* </p>
*
* <P>
* If the key does not match, a <code>BadCredentialsException</code> is thrown.
* </p>
* An {@link AuthenticationProvider} implementation that can authenticate an {@link AuthByAdapter}.<P>Configured in
* the bean context with a key that should match the key used by adapters to generate <code>AuthByAdapter</code>
* instances. It treats as valid any such instance presenting a hash code that matches the
* <code>AuthByAdapterProvider</code>-configured key.</p>
* <P>If the key does not match, a <code>BadCredentialsException</code> is thrown.</p>
*/
public class AuthByAdapterProvider implements InitializingBean,
AuthenticationProvider, MessageSourceAware {
//~ Instance fields ========================================================
public class AuthByAdapterProvider implements InitializingBean, AuthenticationProvider, MessageSourceAware {
//~ Instance fields ================================================================================================
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private String key;
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.notNull(key,
"A Key is required and should match that configured for the adapters");
Assert.notNull(key, "A Key is required and should match that configured for the adapters");
Assert.notNull(messages, "A message source must be set");
}
@ -68,8 +58,7 @@ public class AuthByAdapterProvider implements InitializingBean,
if (token.getKeyHash() == key.hashCode()) {
return authentication;
} else {
throw new BadCredentialsException(messages.getMessage(
"AuthByAdapterProvider.incorrectKey",
throw new BadCredentialsException(messages.getMessage("AuthByAdapterProvider.incorrectKey",
"The presented AuthByAdapter implementation does not contain the expected key"));
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,6 +16,7 @@
package org.acegisecurity.adapters;
import org.acegisecurity.Authentication;
import org.acegisecurity.context.SecurityContextHolder;
import org.apache.commons.logging.Log;
@ -35,63 +36,47 @@ import javax.servlet.http.HttpServletRequest;
/**
* Populates <code>SecurityContext</code> with the <code>Authentication</code>
* obtained from the container's
* <code>HttpServletRequest.getUserPrincipal()</code>.
*
* <p>
* Use this filter with container adapters only.
* </p>
*
* <p>
* This filter <b>never</b> preserves the <code>Authentication</code> on the
* <code>SecurityContext</code> - it is replaced every request.
* </p>
*
* <p>
* See {@link org.acegisecurity.context.HttpSessionContextIntegrationFilter}
* for further information.
* </p>
* Populates <code>SecurityContext</code> with the <code>Authentication</code> obtained from the container's
* <code>HttpServletRequest.getUserPrincipal()</code>.<p>Use this filter with container adapters only.</p>
* <p>This filter <b>never</b> preserves the <code>Authentication</code> on the <code>SecurityContext</code> - it
* is replaced every request.</p>
* <p>See {@link org.acegisecurity.context.HttpSessionContextIntegrationFilter} for further information.</p>
*
* @author Ben Alex
* @version $Id$
*/
public class HttpRequestIntegrationFilter implements Filter {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
private static final Log logger = LogFactory.getLog(HttpRequestIntegrationFilter.class);
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Does nothing. We use IoC container lifecycle services instead.
*/
public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
Principal principal = ((HttpServletRequest) request)
.getUserPrincipal();
Principal principal = ((HttpServletRequest) request).getUserPrincipal();
if ((principal != null) && principal instanceof Authentication) {
SecurityContextHolder.getContext().setAuthentication((Authentication) principal);
if (logger.isDebugEnabled()) {
logger.debug(
"SecurityContextHolder updated with Authentication from container: '"
+ principal + "'");
logger.debug("SecurityContextHolder updated with Authentication from container: '" + principal
+ "'");
}
} else {
if (logger.isDebugEnabled()) {
logger.debug(
"SecurityContextHolder not set with new Authentication as Principal was: '"
logger.debug("SecurityContextHolder not set with new Authentication as Principal was: '"
+ principal + "'");
}
}
} else {
throw new IllegalArgumentException(
"Only HttpServletRequest is acceptable");
throw new IllegalArgumentException("Only HttpServletRequest is acceptable");
}
chain.doFilter(request, response);

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -21,31 +21,29 @@ import java.security.Principal;
/**
* A {@link Principal} compatible {@link org.acegisecurity.Authentication}
* object.
* A {@link Principal} compatible {@link org.acegisecurity.Authentication} object.
*
* @author Ben Alex
* @version $Id$
*/
public class PrincipalAcegiUserToken extends AbstractAdapterAuthenticationToken
implements Principal {
//~ Instance fields ========================================================
public class PrincipalAcegiUserToken extends AbstractAdapterAuthenticationToken implements Principal {
//~ Instance fields ================================================================================================
private Object principal;
private String password;
private String username;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public PrincipalAcegiUserToken(String key, String username,
String password, GrantedAuthority[] authorities, Object principal) {
public PrincipalAcegiUserToken(String key, String username, String password, GrantedAuthority[] authorities,
Object principal) {
super(key, authorities);
this.username = username;
this.password = password;
this.principal = principal;
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
public Object getCredentials() {
return this.password;

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,36 +29,28 @@ import org.acegisecurity.ConfigAttributeDefinition;
* @version $Id$
*/
public interface AfterInvocationProvider {
//~ Methods ================================================================
//~ Methods ========================================================================================================
public Object decide(Authentication authentication, Object object,
ConfigAttributeDefinition config, Object returnedObject)
throws AccessDeniedException;
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config,
Object returnedObject) throws AccessDeniedException;
/**
* Indicates whether this <code>AfterInvocationProvider</code> is able to
* participate in a decision involving the passed
* <code>ConfigAttribute</code>.
*
* <p>
* This allows the <code>AbstractSecurityInterceptor</code> to check every
* configuration attribute can be consumed by the configured
* <code>AccessDecisionManager</code> and/or <code>RunAsManager</code>
* and/or <code>AccessDecisionManager</code>.
* </p>
* Indicates whether this <code>AfterInvocationProvider</code> is able to participate in a decision
* involving the passed <code>ConfigAttribute</code>.<p>This allows the
* <code>AbstractSecurityInterceptor</code> to check every configuration attribute can be consumed by the
* configured <code>AccessDecisionManager</code> and/or <code>RunAsManager</code> and/or
* <code>AccessDecisionManager</code>.</p>
*
* @param attribute a configuration attribute that has been configured
* against the <code>AbstractSecurityInterceptor</code>
* @param attribute a configuration attribute that has been configured against the
* <code>AbstractSecurityInterceptor</code>
*
* @return true if this <code>AfterInvocationProvider</code> can support
* the passed configuration attribute
* @return true if this <code>AfterInvocationProvider</code> can support the passed configuration attribute
*/
public boolean supports(ConfigAttribute attribute);
/**
* Indicates whether the <code>AfterInvocationProvider</code> is able to
* provide "after invocation" processing for the indicated secured object
* type.
* Indicates whether the <code>AfterInvocationProvider</code> is able to provide "after invocation"
* processing for the indicated secured object type.
*
* @param clazz the class of secure object that is being queried
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -31,38 +31,55 @@ import java.util.List;
/**
* Provider-based implementation of {@link AfterInvocationManager}.
*
* <p>
* Handles configuration of a bean context defined list of {@link
* AfterInvocationProvider}s.
* </p>
*
* <p>
* Every <code>AfterInvocationProvider</code> will be polled when the {@link
* #decide(Authentication, Object, ConfigAttributeDefinition, Object)} method
* is called. The <code>Object</code> returned from each provider will be
* presented to the successive provider for processing. This means each
* provider <b>must</b> ensure they return the <code>Object</code>, even if
* they are not interested in the "after invocation" decision (perhaps as the
* secure object invocation did not include a configuration attribute a given
* provider is configured to respond to).
* </p>
* Provider-based implementation of {@link AfterInvocationManager}.<p>Handles configuration of a bean context
* defined list of {@link AfterInvocationProvider}s.</p>
* <p>Every <code>AfterInvocationProvider</code> will be polled when the {@link #decide(Authentication, Object,
* ConfigAttributeDefinition, Object)} method is called. The <code>Object</code> returned from each provider will be
* presented to the successive provider for processing. This means each provider <b>must</b> ensure they return the
* <code>Object</code>, even if they are not interested in the "after invocation" decision (perhaps as the secure
* object invocation did not include a configuration attribute a given provider is configured to respond to).</p>
*
* @author Ben Alex
* @version $Id$
*/
public class AfterInvocationProviderManager implements AfterInvocationManager,
InitializingBean {
//~ Static fields/initializers =============================================
public class AfterInvocationProviderManager implements AfterInvocationManager, InitializingBean {
//~ Static fields/initializers =====================================================================================
protected static final Log logger = LogFactory.getLog(AfterInvocationProviderManager.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private List providers;
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
checkIfValidList(this.providers);
}
private void checkIfValidList(List listToCheck) {
if ((listToCheck == null) || (listToCheck.size() == 0)) {
throw new IllegalArgumentException("A list of AfterInvocationProviders is required");
}
}
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config,
Object returnedObject) throws AccessDeniedException {
Iterator iter = this.providers.iterator();
Object result = returnedObject;
while (iter.hasNext()) {
AfterInvocationProvider provider = (AfterInvocationProvider) iter.next();
result = provider.decide(authentication, object, config, result);
}
return result;
}
public List getProviders() {
return this.providers;
}
public void setProviders(List newList) {
checkIfValidList(newList);
@ -77,8 +94,7 @@ public class AfterInvocationProviderManager implements AfterInvocationManager,
AfterInvocationProvider attemptToCast = (AfterInvocationProvider) currentObject;
} catch (ClassCastException cce) {
throw new IllegalArgumentException("AfterInvocationProvider "
+ currentObject.getClass().getName()
throw new IllegalArgumentException("AfterInvocationProvider " + currentObject.getClass().getName()
+ " must implement AfterInvocationProvider");
}
}
@ -86,36 +102,11 @@ public class AfterInvocationProviderManager implements AfterInvocationManager,
this.providers = newList;
}
public List getProviders() {
return this.providers;
}
public void afterPropertiesSet() throws Exception {
checkIfValidList(this.providers);
}
public Object decide(Authentication authentication, Object object,
ConfigAttributeDefinition config, Object returnedObject)
throws AccessDeniedException {
Iterator iter = this.providers.iterator();
Object result = returnedObject;
while (iter.hasNext()) {
AfterInvocationProvider provider = (AfterInvocationProvider) iter
.next();
result = provider.decide(authentication, object, config, result);
}
return result;
}
public boolean supports(ConfigAttribute attribute) {
Iterator iter = this.providers.iterator();
while (iter.hasNext()) {
AfterInvocationProvider provider = (AfterInvocationProvider) iter
.next();
AfterInvocationProvider provider = (AfterInvocationProvider) iter.next();
if (logger.isDebugEnabled()) {
logger.debug("Evaluating " + attribute + " against " + provider);
@ -130,27 +121,19 @@ public class AfterInvocationProviderManager implements AfterInvocationManager,
}
/**
* Iterates through all <code>AfterInvocationProvider</code>s and ensures
* each can support the presented class.
*
* <p>
* If one or more providers cannot support the presented class,
* <code>false</code> is returned.
* </p>
* Iterates through all <code>AfterInvocationProvider</code>s and ensures each can support the presented
* class.<p>If one or more providers cannot support the presented class, <code>false</code> is returned.</p>
*
* @param clazz the secure object class being queries
*
* @return if the <code>AfterInvocationProviderManager</code> can support
* the secure object class, which requires every one of its
* <code>AfterInvocationProvider</code>s to support the secure
* object class
* @return if the <code>AfterInvocationProviderManager</code> can support the secure object class, which requires
* every one of its <code>AfterInvocationProvider</code>s to support the secure object class
*/
public boolean supports(Class clazz) {
Iterator iter = this.providers.iterator();
while (iter.hasNext()) {
AfterInvocationProvider provider = (AfterInvocationProvider) iter
.next();
AfterInvocationProvider provider = (AfterInvocationProvider) iter.next();
if (!provider.supports(clazz)) {
return false;
@ -159,11 +142,4 @@ public class AfterInvocationProviderManager implements AfterInvocationManager,
return true;
}
private void checkIfValidList(List listToCheck) {
if ((listToCheck == null) || (listToCheck.size() == 0)) {
throw new IllegalArgumentException(
"A list of AfterInvocationProviders is required");
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -20,6 +20,7 @@ import org.acegisecurity.Authentication;
import org.acegisecurity.AuthorizationServiceException;
import org.acegisecurity.ConfigAttribute;
import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.acl.AclEntry;
import org.acegisecurity.acl.AclManager;
import org.acegisecurity.acl.basic.BasicAclEntry;
@ -42,125 +43,61 @@ import java.util.Set;
/**
* <p>
* Given a <code>Collection</code> of domain object instances returned from a
* secure object invocation, remove any <code>Collection</code> elements the
* principal does not have appropriate permission to access as defined by the
* {@link AclManager}.
* </p>
*
* <p>
* The <code>AclManager</code> is used to retrieve the access control list
* (ACL) permissions associated with each <code>Collection</code> domain
* object instance element for the current <code>Authentication</code> object.
* This class is designed to process {@link AclEntry}s that are subclasses of
* {@link org.acegisecurity.acl.basic.BasicAclEntry} only.
* Generally these are obtained by using the {@link
* org.acegisecurity.acl.basic.BasicAclProvider}.
* </p>
*
* <p>
* This after invocation provider will fire if any {@link
* ConfigAttribute#getAttribute()} matches the {@link
* #processConfigAttribute}. The provider will then lookup the ACLs from the
* <code>AclManager</code> and ensure the principal is {@link
* org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for
* at least one of the {@link #requirePermission}s for each
* <code>Collection</code> element. If the principal does not have at least
* one of the permissions, that element will not be included in the returned
* <code>Collection</code>.
* </p>
*
* <p>
* Often users will setup a <code>BasicAclEntryAfterInvocationProvider</code>
* with a {@link #processConfigAttribute} of
* <code>AFTER_ACL_COLLECTION_READ</code> and a {@link #requirePermission} of
* <code>SimpleAclEntry.READ</code>. These are also the defaults.
* </p>
*
* <p>
* The <code>AclManager</code> is allowed to return any implementations of
* <code>AclEntry</code> it wishes. However, this provider will only be able
* to validate against <code>BasicAclEntry</code>s, and thus a
* <code>Collection</code> element will be filtered from the resulting
* <code>Collection</code> if no <code>AclEntry</code> is of type
* <code>BasicAclEntry</code>.
* </p>
*
* <p>
* If the provided <code>returnObject</code> is <code>null</code>, a
* <code>null</code><code>Collection</code> will be returned. If the provided
* <code>returnObject</code> is not a <code>Collection</code>, an {@link
* AuthorizationServiceException} will be thrown.
* </p>
*
* <p>
* All comparisons and prefixes are case sensitive.
* </p>
* <p>Given a <code>Collection</code> of domain object instances returned from a secure object invocation, remove
* any <code>Collection</code> elements the principal does not have appropriate permission to access as defined by the
* {@link AclManager}.</p>
* <p>The <code>AclManager</code> is used to retrieve the access control list (ACL) permissions associated with
* each <code>Collection</code> domain object instance element for the current <code>Authentication</code> object.
* This class is designed to process {@link AclEntry}s that are subclasses of {@link
* org.acegisecurity.acl.basic.BasicAclEntry} only. Generally these are obtained by using the {@link
* org.acegisecurity.acl.basic.BasicAclProvider}.</p>
* <p>This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
* #processConfigAttribute}. The provider will then lookup the ACLs from the <code>AclManager</code> and ensure the
* principal is {@link org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link
* #requirePermission}s for each <code>Collection</code> element. If the principal does not have at least one of the
* permissions, that element will not be included in the returned <code>Collection</code>.</p>
* <p>Often users will setup a <code>BasicAclEntryAfterInvocationProvider</code> with a {@link
* #processConfigAttribute} of <code>AFTER_ACL_COLLECTION_READ</code> and a {@link #requirePermission} of
* <code>SimpleAclEntry.READ</code>. These are also the defaults.</p>
* <p>The <code>AclManager</code> is allowed to return any implementations of <code>AclEntry</code> it wishes.
* However, this provider will only be able to validate against <code>BasicAclEntry</code>s, and thus a
* <code>Collection</code> element will be filtered from the resulting <code>Collection</code> if no
* <code>AclEntry</code> is of type <code>BasicAclEntry</code>.</p>
* <p>If the provided <code>returnObject</code> is <code>null</code>, a <code>null</code><code>Collection</code>
* will be returned. If the provided <code>returnObject</code> is not a <code>Collection</code>, an {@link
* AuthorizationServiceException} will be thrown.</p>
* <p>All comparisons and prefixes are case sensitive.</p>
*
* @author Ben Alex
* @author Paulo Neves
* @version $Id$
*/
public class BasicAclEntryAfterInvocationCollectionFilteringProvider
implements AfterInvocationProvider, InitializingBean {
//~ Static fields/initializers =============================================
public class BasicAclEntryAfterInvocationCollectionFilteringProvider implements AfterInvocationProvider,
InitializingBean {
//~ Static fields/initializers =====================================================================================
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private AclManager aclManager;
private Class processDomainObjectClass = Object.class;
private String processConfigAttribute = "AFTER_ACL_COLLECTION_READ";
private int[] requirePermission = {SimpleAclEntry.READ};
private Class processDomainObjectClass = Object.class;
//~ Methods ================================================================
public void setProcessDomainObjectClass(Class processDomainObjectClass) {
Assert.notNull(processDomainObjectClass,
"processDomainObjectClass cannot be set to null");
this.processDomainObjectClass = processDomainObjectClass;
}
public void setAclManager(AclManager aclManager) {
this.aclManager = aclManager;
}
public AclManager getAclManager() {
return aclManager;
}
public void setProcessConfigAttribute(String processConfigAttribute) {
this.processConfigAttribute = processConfigAttribute;
}
public String getProcessConfigAttribute() {
return processConfigAttribute;
}
public void setRequirePermission(int[] requirePermission) {
this.requirePermission = requirePermission;
}
public int[] getRequirePermission() {
return requirePermission;
}
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.notNull(processConfigAttribute,
"A processConfigAttribute is mandatory");
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
Assert.notNull(aclManager, "An aclManager is mandatory");
if ((requirePermission == null) || (requirePermission.length == 0)) {
throw new IllegalArgumentException(
"One or more requirePermission entries is mandatory");
throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
}
}
public Object decide(Authentication authentication, Object object,
ConfigAttributeDefinition config, Object returnedObject)
throws AccessDeniedException {
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config,
Object returnedObject) throws AccessDeniedException {
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
@ -203,7 +140,7 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider
if (domainObject == null) {
hasPermission = true;
} else if (!processDomainObjectClass.isAssignableFrom(domainObject.getClass())) {
hasPermission = true;
hasPermission = true;
} else {
acls = aclManager.getAcls(domainObject, authentication);
}
@ -212,21 +149,16 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider
for (int i = 0; i < acls.length; i++) {
// Locate processable AclEntrys
if (acls[i] instanceof BasicAclEntry) {
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
// See if principal has any of the required permissions
for (int y = 0; y < requirePermission.length;
y++) {
if (processableAcl.isPermitted(
requirePermission[y])) {
for (int y = 0; y < requirePermission.length; y++) {
if (processableAcl.isPermitted(requirePermission[y])) {
hasPermission = true;
if (logger.isDebugEnabled()) {
logger.debug(
"Principal is authorised for element: "
+ domainObject
+ " due to ACL: "
+ processableAcl.toString());
logger.debug("Principal is authorised for element: " + domainObject
+ " due to ACL: " + processableAcl.toString());
}
}
}
@ -238,9 +170,7 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider
filterer.remove(domainObject);
if (logger.isDebugEnabled()) {
logger.debug(
"Principal is NOT authorised for element: "
+ domainObject);
logger.debug("Principal is NOT authorised for element: " + domainObject);
}
}
}
@ -252,9 +182,37 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider
return returnedObject;
}
public AclManager getAclManager() {
return aclManager;
}
public String getProcessConfigAttribute() {
return processConfigAttribute;
}
public int[] getRequirePermission() {
return requirePermission;
}
public void setAclManager(AclManager aclManager) {
this.aclManager = aclManager;
}
public void setProcessConfigAttribute(String processConfigAttribute) {
this.processConfigAttribute = processConfigAttribute;
}
public void setProcessDomainObjectClass(Class processDomainObjectClass) {
Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null");
this.processDomainObjectClass = processDomainObjectClass;
}
public void setRequirePermission(int[] requirePermission) {
this.requirePermission = requirePermission;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& attribute.getAttribute().equals(getProcessConfigAttribute())) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
return true;
} else {
return false;
@ -262,8 +220,7 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider
}
/**
* This implementation supports any type of class, because it does not
* query the presented secure object.
* This implementation supports any type of class, because it does not query the presented secure object.
*
* @param clazz the secure object
*
@ -279,7 +236,7 @@ public class BasicAclEntryAfterInvocationCollectionFilteringProvider
* Filter strategy interface.
*/
interface Filterer {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Gets the filtered collection or array.
@ -308,11 +265,11 @@ interface Filterer {
* A filter used to filter Collections.
*/
class CollectionFilterer implements Filterer {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private Collection collection;
@ -321,7 +278,7 @@ class CollectionFilterer implements Filterer {
private Iterator collectionIter;
private Set removeList;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
CollectionFilterer(Collection collection) {
this.collection = collection;
@ -336,9 +293,10 @@ class CollectionFilterer implements Filterer {
removeList = new HashSet();
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
*
* @see org.acegisecurity.afterinvocation.Filterer#getFilteredObject()
*/
public Object getFilteredObject() {
@ -352,14 +310,15 @@ class CollectionFilterer implements Filterer {
}
if (logger.isDebugEnabled()) {
logger.debug("Original collection contained " + originalSize
+ " elements; now contains " + collection.size() + " elements");
logger.debug("Original collection contained " + originalSize + " elements; now contains "
+ collection.size() + " elements");
}
return collection;
}
/**
*
* @see org.acegisecurity.afterinvocation.Filterer#iterator()
*/
public Iterator iterator() {
@ -369,6 +328,7 @@ class CollectionFilterer implements Filterer {
}
/**
*
* @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object)
*/
public void remove(Object object) {
@ -381,16 +341,16 @@ class CollectionFilterer implements Filterer {
* A filter used to filter arrays.
*/
class ArrayFilterer implements Filterer {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationCollectionFilteringProvider.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private Set removeList;
private Object[] list;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
ArrayFilterer(Object[] list) {
this.list = list;
@ -401,18 +361,17 @@ class ArrayFilterer implements Filterer {
removeList = new HashSet();
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
*
* @see org.acegisecurity.afterinvocation.Filterer#getFilteredObject()
*/
public Object getFilteredObject() {
// Recreate an array of same type and filter the removed objects.
int originalSize = list.length;
int sizeOfResultingList = originalSize - removeList.size();
Object[] filtered = (Object[]) Array.newInstance(list.getClass()
.getComponentType(),
sizeOfResultingList);
Object[] filtered = (Object[]) Array.newInstance(list.getClass().getComponentType(), sizeOfResultingList);
for (int i = 0, j = 0; i < list.length; i++) {
Object object = list[i];
@ -424,8 +383,7 @@ class ArrayFilterer implements Filterer {
}
if (logger.isDebugEnabled()) {
logger.debug("Original array contained " + originalSize
+ " elements; now contains " + sizeOfResultingList
logger.debug("Original array contained " + originalSize + " elements; now contains " + sizeOfResultingList
+ " elements");
}
@ -433,6 +391,7 @@ class ArrayFilterer implements Filterer {
}
/**
*
* @see org.acegisecurity.afterinvocation.Filterer#iterator()
*/
public Iterator iterator() {
@ -440,6 +399,7 @@ class ArrayFilterer implements Filterer {
}
/**
*
* @see org.acegisecurity.afterinvocation.Filterer#remove(java.lang.Object)
*/
public void remove(Object object) {

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -15,116 +15,81 @@
package org.acegisecurity.afterinvocation;
import java.util.Iterator;
import org.acegisecurity.AccessDeniedException;
import org.acegisecurity.AcegiMessageSource;
import org.acegisecurity.Authentication;
import org.acegisecurity.ConfigAttribute;
import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.acl.AclEntry;
import org.acegisecurity.acl.AclManager;
import org.acegisecurity.acl.basic.BasicAclEntry;
import org.acegisecurity.acl.basic.SimpleAclEntry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.util.Assert;
import java.util.Iterator;
/**
* <p>
* Given a domain object instance returned from a secure object invocation,
* ensures the principal has appropriate permission as defined by the {@link
* AclManager}.
* </p>
*
* <p>
* The <code>AclManager</code> is used to retrieve the access control list
* (ACL) permissions associated with a domain object instance for the current
* <code>Authentication</code> object. This class is designed to process
* {@link AclEntry}s that are subclasses of {@link
* org.acegisecurity.acl.basic.BasicAclEntry} only. Generally these are
* obtained by using the {@link org.acegisecurity.acl.basic.BasicAclProvider}.
* </p>
*
* <p>
* This after invocation provider will fire if any {@link
* ConfigAttribute#getAttribute()} matches the {@link
* #processConfigAttribute}. The provider will then lookup the ACLs from the
* <code>AclManager</code> and ensure the principal is {@link
* org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for at least
* one of the {@link #requirePermission}s.
* </p>
*
* <p>
* Often users will setup a <code>BasicAclEntryAfterInvocationProvider</code>
* with a {@link #processConfigAttribute} of <code>AFTER_ACL_READ</code> and a
* {@link #requirePermission} of <code>SimpleAclEntry.READ</code>. These are
* also the defaults.
* </p>
*
* <p>
* If the principal does not have sufficient permissions, an
* <code>AccessDeniedException</code> will be thrown.
* </p>
*
* <p>
* The <code>AclManager</code> is allowed to return any implementations of
* <code>AclEntry</code> it wishes. However, this provider will only be able
* to validate against <code>BasicAclEntry</code>s, and thus access will be
* denied if no <code>AclEntry</code> is of type <code>BasicAclEntry</code>.
* </p>
*
* <p>
* If the provided <code>returnObject</code> is <code>null</code>, permission
* will always be granted and <code>null</code> will be returned.
* </p>
*
* <p>
* All comparisons and prefixes are case sensitive.
* </p>
* <p>Given a domain object instance returned from a secure object invocation, ensures the principal has
* appropriate permission as defined by the {@link AclManager}.</p>
* <p>The <code>AclManager</code> is used to retrieve the access control list (ACL) permissions associated with a
* domain object instance for the current <code>Authentication</code> object. This class is designed to process {@link
* AclEntry}s that are subclasses of {@link org.acegisecurity.acl.basic.BasicAclEntry} only. Generally these are
* obtained by using the {@link org.acegisecurity.acl.basic.BasicAclProvider}.</p>
* <p>This after invocation provider will fire if any {@link ConfigAttribute#getAttribute()} matches the {@link
* #processConfigAttribute}. The provider will then lookup the ACLs from the <code>AclManager</code> and ensure the
* principal is {@link org.acegisecurity.acl.basic.BasicAclEntry#isPermitted(int)} for at least one of the {@link
* #requirePermission}s.</p>
* <p>Often users will setup a <code>BasicAclEntryAfterInvocationProvider</code> with a {@link
* #processConfigAttribute} of <code>AFTER_ACL_READ</code> and a {@link #requirePermission} of
* <code>SimpleAclEntry.READ</code>. These are also the defaults.</p>
* <p>If the principal does not have sufficient permissions, an <code>AccessDeniedException</code> will be thrown.</p>
* <p>The <code>AclManager</code> is allowed to return any implementations of <code>AclEntry</code> it wishes.
* However, this provider will only be able to validate against <code>BasicAclEntry</code>s, and thus access will be
* denied if no <code>AclEntry</code> is of type <code>BasicAclEntry</code>.</p>
* <p>If the provided <code>returnObject</code> is <code>null</code>, permission will always be granted and
* <code>null</code> will be returned.</p>
* <p>All comparisons and prefixes are case sensitive.</p>
*/
public class BasicAclEntryAfterInvocationProvider
implements AfterInvocationProvider, InitializingBean, MessageSourceAware {
//~ Static fields/initializers =============================================
public class BasicAclEntryAfterInvocationProvider implements AfterInvocationProvider, InitializingBean,
MessageSourceAware {
//~ Static fields/initializers =====================================================================================
protected static final Log logger = LogFactory.getLog(BasicAclEntryAfterInvocationProvider.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
private AclManager aclManager;
private Class processDomainObjectClass = Object.class;
protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor();
private String processConfigAttribute = "AFTER_ACL_READ";
private int[] requirePermission = {SimpleAclEntry.READ};
private Class processDomainObjectClass = Object.class;
//~ Methods ================================================================
//~ Methods ========================================================================================================
public void setProcessDomainObjectClass(Class processDomainObjectClass) {
Assert.notNull(processDomainObjectClass,
"processDomainObjectClass cannot be set to null");
this.processDomainObjectClass = processDomainObjectClass;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(processConfigAttribute,
"A processConfigAttribute is mandatory");
public void afterPropertiesSet() throws Exception {
Assert.notNull(processConfigAttribute, "A processConfigAttribute is mandatory");
Assert.notNull(aclManager, "An aclManager is mandatory");
Assert.notNull(messages, "A message source must be set");
if ((requirePermission == null) || (requirePermission.length == 0)) {
throw new IllegalArgumentException(
"One or more requirePermission entries is mandatory");
throw new IllegalArgumentException("One or more requirePermission entries is mandatory");
}
}
public Object decide(Authentication authentication, Object object,
ConfigAttributeDefinition config, Object returnedObject)
throws AccessDeniedException {
public Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config,
Object returnedObject) throws AccessDeniedException {
Iterator iter = config.getConfigAttributes();
while (iter.hasNext()) {
@ -141,7 +106,7 @@ public class BasicAclEntryAfterInvocationProvider
return null;
}
if (!processDomainObjectClass.isAssignableFrom(returnedObject.getClass())) {
if (logger.isDebugEnabled()) {
logger.debug("Return object is not applicable for this provider, skipping");
@ -150,8 +115,7 @@ public class BasicAclEntryAfterInvocationProvider
return null;
}
AclEntry[] acls = aclManager.getAcls(returnedObject,
authentication);
AclEntry[] acls = aclManager.getAcls(returnedObject, authentication);
if ((acls == null) || (acls.length == 0)) {
throw new AccessDeniedException(messages.getMessage(
@ -169,10 +133,8 @@ public class BasicAclEntryAfterInvocationProvider
for (int y = 0; y < requirePermission.length; y++) {
if (processableAcl.isPermitted(requirePermission[y])) {
if (logger.isDebugEnabled()) {
logger.debug(
"Principal DOES have permission to return object: "
+ returnedObject + " due to ACL: "
+ processableAcl.toString());
logger.debug("Principal DOES have permission to return object: " + returnedObject
+ " due to ACL: " + processableAcl.toString());
}
return returnedObject;
@ -216,13 +178,17 @@ public class BasicAclEntryAfterInvocationProvider
this.processConfigAttribute = processConfigAttribute;
}
public void setProcessDomainObjectClass(Class processDomainObjectClass) {
Assert.notNull(processDomainObjectClass, "processDomainObjectClass cannot be set to null");
this.processDomainObjectClass = processDomainObjectClass;
}
public void setRequirePermission(int[] requirePermission) {
this.requirePermission = requirePermission;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute.getAttribute() != null)
&& attribute.getAttribute().equals(getProcessConfigAttribute())) {
if ((attribute.getAttribute() != null) && attribute.getAttribute().equals(getProcessConfigAttribute())) {
return true;
} else {
return false;
@ -230,8 +196,7 @@ public class BasicAclEntryAfterInvocationProvider
}
/**
* This implementation supports any type of class, because it does not
* query the presented secure object.
* This implementation supports any type of class, because it does not query the presented secure object.
*
* @param clazz the secure object
*

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,25 +19,21 @@
package org.acegisecurity.captcha;
/**
* <p>
* return false if ny CaptchaChannelProcessorTemplate of mapped urls has been
* requested more than thresold; <br>
* Default keyword : REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS
* </p>
* <p>return false if ny CaptchaChannelProcessorTemplate of mapped urls has been requested more than thresold; <br>
* Default keyword : REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS</p>
*
* @author Marc-Antoine Garrigue
* @version $Id$
*/
public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessor
extends CaptchaChannelProcessorTemplate {
//~ Static fields/initializers =============================================
public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate {
//~ Static fields/initializers =====================================================================================
/** Keyword for this channelProcessor */
public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_ABOVE_THRESOLD_REQUESTS";
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructor
*/
public AlwaysTestAfterMaxRequestsCaptchaChannelProcessor() {
@ -45,7 +41,7 @@ public class AlwaysTestAfterMaxRequestsCaptchaChannelProcessor
this.setKeyword(DEFAULT_KEYWORD);
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Verify wheter the context is valid concerning humanity

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -12,27 +12,25 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.acegisecurity.captcha;
/**
* <p>
* return false if thresold is greater than millis since last captcha test has occured;<br>
* Default keyword : REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS
* </p>
* <p>return false if thresold is greater than millis since last captcha test has occured;<br>
* Default keyword : REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS</p>
*
* @author Marc-Antoine Garrigue
* @version $Id$
*/
public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessor
extends CaptchaChannelProcessorTemplate {
//~ Static fields/initializers =============================================
public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessor extends CaptchaChannelProcessorTemplate {
//~ Static fields/initializers =====================================================================================
/** Keyword for this channelProcessor */
public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_AFTER_THRESOLD_IN_MILLIS";
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructor
*/
public AlwaysTestAfterTimeInMillisCaptchaChannelProcessor() {
@ -40,7 +38,7 @@ public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessor
this.setKeyword(DEFAULT_KEYWORD);
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Verify wheter the context is valid concerning humanity
@ -50,15 +48,12 @@ public class AlwaysTestAfterTimeInMillisCaptchaChannelProcessor
* @return true if valid, false otherwise
*/
boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) {
if ((System.currentTimeMillis()
- context.getLastPassedCaptchaDateInMillis()) < getThresold()) {
logger.debug(
"context is valid : last passed captcha date - current time < thresold");
if ((System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis()) < getThresold()) {
logger.debug("context is valid : last passed captcha date - current time < thresold");
return true;
} else {
logger.debug(
"context is not valid : last passed captcha date - current time > thresold");
logger.debug("context is not valid : last passed captcha date - current time > thresold");
return false;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,26 +19,23 @@ import org.springframework.util.Assert;
/**
* <p>
* return false if thresold is lower than average time millis between any
* CaptchaChannelProcessorTemplate mapped urls requests and is human;<br>
* <p>return false if thresold is lower than average time millis between any CaptchaChannelProcessorTemplate mapped
* urls requests and is human;<br>
* Default keyword : REQUIRES_CAPTCHA_BELOW_AVERAGE_TIME_IN_MILLIS_REQUESTS <br>
* Note : before first humanity check
* </p>
* Note : before first humanity check</p>
*
* @author Marc-Antoine Garrigue
* @version $Id$
*/
public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
extends CaptchaChannelProcessorTemplate {
//~ Static fields/initializers =============================================
public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor extends CaptchaChannelProcessorTemplate {
//~ Static fields/initializers =====================================================================================
/** Keyword for this channelProcessor */
public static final String DEFAULT_KEYWORD = "REQUIRES_CAPTCHA_BELOW_AVERAGE_TIME_IN_MILLIS_REQUESTS";
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
/**
/**
* Constructor
*/
public AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor() {
@ -46,7 +43,7 @@ public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
this.setKeyword(DEFAULT_KEYWORD);
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Verify if thresold is &gt; 0
@ -68,8 +65,7 @@ public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
boolean isContextValidConcerningHumanity(CaptchaSecurityContext context) {
int req = context.getHumanRestrictedResourcesRequestsCount();
float thresold = getThresold();
float duration = System.currentTimeMillis()
- context.getLastPassedCaptchaDateInMillis();
float duration = System.currentTimeMillis() - context.getLastPassedCaptchaDateInMillis();
float average;
if (req == 0) {
@ -79,13 +75,11 @@ public class AlwaysTestBelowAverageTimeInMillisBetweenRequestsChannelProcessor
}
if (context.isHuman() && (average > thresold)) {
logger.debug(
"context is valid : average time between requests < thresold && is human");
logger.debug("context is valid : average time between requests < thresold && is human");
return true;
} else {
logger.debug(
"context is not valid : request count > thresold or is not human");
logger.debug("context is not valid : request count > thresold or is not human");
return false;
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,8 +17,11 @@ package org.acegisecurity.captcha;
import org.acegisecurity.ConfigAttribute;
import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.context.SecurityContextHolder;
import org.acegisecurity.intercept.web.FilterInvocation;
import org.acegisecurity.securechannel.ChannelEntryPoint;
import org.acegisecurity.securechannel.ChannelProcessor;
@ -37,67 +40,32 @@ import javax.servlet.ServletException;
/**
* <p>
* CaptchaChannel template : Ensures the user has enough human privileges by
* review of the {@link CaptchaSecurityContext} and using an abstract routine
* {@link #isContextValidConcerningHumanity(CaptchaSecurityContext)}
* (implemented by sub classes)
* </p>
*
* <P>
* The component uses 2 main parameters for its configuration :
*
* <ul>
* <li>
* a keyword to be mapped to urls in the {@link
* org.acegisecurity.securechannel.ChannelProcessingFilter} configuration<br>
* default value provided by sub classes.
* </li>
* <li>
* and a thresold : used by the routine {@link
* #isContextValidConcerningHumanity(CaptchaSecurityContext)} to evaluate
* whether the {@link CaptchaSecurityContext} is valid default value = 0
* </li>
* </ul>
* </p>
* <p>CaptchaChannel template : Ensures the user has enough human privileges by review of the {@link
* CaptchaSecurityContext} and using an abstract routine {@link
* #isContextValidConcerningHumanity(CaptchaSecurityContext)} (implemented by sub classes)</p>
* <P>The component uses 2 main parameters for its configuration :
* <ul>
* <li>a keyword to be mapped to urls in the {@link
* org.acegisecurity.securechannel.ChannelProcessingFilter} configuration<br>
* default value provided by sub classes.</li>
* <li>and a thresold : used by the routine {@link
* #isContextValidConcerningHumanity(CaptchaSecurityContext)} to evaluate whether the {@link
* CaptchaSecurityContext} is valid default value = 0</li>
* </ul>
* </p>
*
* @author marc antoine Garrigue
* @version $Id$
*/
public abstract class CaptchaChannelProcessorTemplate
implements ChannelProcessor, InitializingBean {
//~ Instance fields ========================================================
public abstract class CaptchaChannelProcessorTemplate implements ChannelProcessor, InitializingBean {
//~ Instance fields ================================================================================================
protected Log logger = LogFactory.getLog(this.getClass());
private ChannelEntryPoint entryPoint;
protected Log logger = LogFactory.getLog(this.getClass());
private String keyword = null;
private int thresold = 0;
//~ Methods ================================================================
public void setEntryPoint(ChannelEntryPoint entryPoint) {
this.entryPoint = entryPoint;
}
public ChannelEntryPoint getEntryPoint() {
return entryPoint;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getKeyword() {
return keyword;
}
public void setThresold(int thresold) {
this.thresold = thresold;
}
public int getThresold() {
return thresold;
}
//~ Methods ========================================================================================================
/**
* Verify if entryPoint and keyword are ok
@ -109,8 +77,8 @@ public abstract class CaptchaChannelProcessorTemplate
Assert.hasLength(keyword, "keyword required");
}
public void decide(FilterInvocation invocation,
ConfigAttributeDefinition config) throws IOException, ServletException {
public void decide(FilterInvocation invocation, ConfigAttributeDefinition config)
throws IOException, ServletException {
if ((invocation == null) || (config == null)) {
throw new IllegalArgumentException("Nulls cannot be provided");
}
@ -127,12 +95,10 @@ public abstract class CaptchaChannelProcessorTemplate
logger.debug("supports this attribute : " + attribute);
if (!isContextValidConcerningHumanity(context)) {
logger.debug(
"context is not allowed to access ressource, redirect to captcha entry point");
logger.debug("context is not allowed to access ressource, redirect to captcha entry point");
redirectToEntryPoint(invocation);
} else {
logger.debug(
"has been successfully checked this keyword, increment request count");
logger.debug("has been successfully checked this keyword, increment request count");
context.incrementHumanRestrictedRessoucesRequestsCount();
}
} else {
@ -141,16 +107,19 @@ public abstract class CaptchaChannelProcessorTemplate
}
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute != null) && (keyword.equals(attribute.getAttribute()))) {
return true;
} else {
return false;
}
public ChannelEntryPoint getEntryPoint() {
return entryPoint;
}
abstract boolean isContextValidConcerningHumanity(
CaptchaSecurityContext context);
public String getKeyword() {
return keyword;
}
public int getThresold() {
return thresold;
}
abstract boolean isContextValidConcerningHumanity(CaptchaSecurityContext context);
private void redirectToEntryPoint(FilterInvocation invocation)
throws IOException, ServletException {
@ -160,4 +129,24 @@ public abstract class CaptchaChannelProcessorTemplate
entryPoint.commence(invocation.getRequest(), invocation.getResponse());
}
public void setEntryPoint(ChannelEntryPoint entryPoint) {
this.entryPoint = entryPoint;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public void setThresold(int thresold) {
this.thresold = thresold;
}
public boolean supports(ConfigAttribute attribute) {
if ((attribute != null) && (keyword.equals(attribute.getAttribute()))) {
return true;
} else {
return false;
}
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,6 +16,7 @@
package org.acegisecurity.captcha;
import org.acegisecurity.securechannel.ChannelEntryPoint;
import org.acegisecurity.util.PortMapper;
import org.acegisecurity.util.PortMapperImpl;
import org.acegisecurity.util.PortResolver;
@ -43,47 +44,25 @@ import javax.servlet.http.HttpServletResponse;
/**
* The captcha entry point : redirect to the captcha test page. <br>
*
* <p>
* This entry point can force the use of SSL : see {@link #getForceHttps()}<br>
* </p>
* This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}<br>
* / Original request can be added to the redirect path using a custom
* translation : see {@link #setIncludeOriginalRequest(boolean)}<br>
* Original request is translated using URLEncoding and the following
* translation mapping in the redirect url :
*
* <ul>
* <li>
* original url => {@link #getOriginalRequestUrlParameterName()}
* </li>
* <li>
* If {@link #isIncludeOriginalParameters()}
* </li>
* <li>
* original method => {@link #getOriginalRequestMethodParameterName()}
* </li>
* <li>
* original parameters => {@link #getOriginalRequestParametersParameterName()}
* </li>
* <li>
* The original parameters string is contructed using :
*
* <ul>
* <li>
* a parameter separator {@link #getOriginalRequestParametersSeparator()}
* </li>
* <li>
* a parameter name value pair separator for each parameter {@link
* #getOriginalRequestParametersNameValueSeparator()}
* </li>
* </ul>
*
* </li>
* </ul>
*
* <br><br>
* The captcha entry point : redirect to the captcha test page. <br><p>This entry point can force the use of SSL :
* see {@link #getForceHttps()}<br></p>
* This entry point allows internal OR external redirect : see {@link #setOutsideWebApp(boolean)}<br>
* / Original request can be added to the redirect path using a custom translation : see {@link #setIncludeOriginalRequest(boolean)}<br>
* Original request is translated using URLEncoding and the following translation mapping in the redirect url :
* <ul>
* <li>original url => {@link #getOriginalRequestUrlParameterName()}</li>
* <li>If {@link #isIncludeOriginalParameters()}</li>
* <li>original method => {@link #getOriginalRequestMethodParameterName()}</li>
* <li>original parameters => {@link #getOriginalRequestParametersParameterName()}</li>
* <li>The original parameters string is contructed using :
* <ul>
* <li>a parameter separator {@link #getOriginalRequestParametersSeparator()}</li>
* <li>a parameter name value pair separator for each parameter {@link
* #getOriginalRequestParametersNameValueSeparator()}</li>
* </ul>
* </li>
* </ul>
* <br><br>
* Default values :<br>
* forceHttps = false<br>
* includesOriginalRequest = true<br>
@ -100,13 +79,13 @@ import javax.servlet.http.HttpServletResponse;
* @version $Id$
*/
public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
//~ Static fields/initializers =============================================
//~ Static fields/initializers =====================================================================================
// ~ Static fields/initializers
// =============================================
private static final Log logger = LogFactory.getLog(CaptchaEntryPoint.class);
//~ Instance fields ========================================================
//~ Instance fields ================================================================================================
// ~ Instance fields
// ========================================================
@ -124,197 +103,24 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
private boolean includeOriginalRequest = true;
private boolean isOutsideWebApp = false;
//~ Methods ================================================================
/**
* The URL where the <code>CaptchaProcessingFilter</code> login page can be
* found. Should be relative to the web-app context path, and include a
* leading <code>/</code>
*
* @param captchaFormUrl
*/
public void setCaptchaFormUrl(String captchaFormUrl) {
this.captchaFormUrl = captchaFormUrl;
}
/**
* DOCUMENT ME!
*
* @return the captcha test page to redirect to.
*/
public String getCaptchaFormUrl() {
return captchaFormUrl;
}
// ~ Methods
// ================================================================
/**
* Set to true to force captcha form access to be via https. If this value
* is ture (the default is false), and the incoming request for the
* protected resource which triggered the interceptor was not already
* <code>https</code>, then
*
* @param forceHttps
*/
public void setForceHttps(boolean forceHttps) {
this.forceHttps = forceHttps;
}
public boolean getForceHttps() {
return forceHttps;
}
public void setIncludeOriginalParameters(boolean includeOriginalParameters) {
this.includeOriginalParameters = includeOriginalParameters;
}
public boolean isIncludeOriginalParameters() {
return includeOriginalParameters;
}
/**
* If set to true, the original request url will be appended to the
* redirect url using the {@link #getOriginalRequestUrlParameterName()}.
*
* @param includeOriginalRequest
*/
public void setIncludeOriginalRequest(boolean includeOriginalRequest) {
this.includeOriginalRequest = includeOriginalRequest;
}
public boolean isIncludeOriginalRequest() {
return includeOriginalRequest;
}
public void setOriginalRequestMethodParameterName(
String originalRequestMethodParameterName) {
this.originalRequestMethodParameterName = originalRequestMethodParameterName;
}
public String getOriginalRequestMethodParameterName() {
return originalRequestMethodParameterName;
}
public void setOriginalRequestParametersNameValueSeparator(
String originalRequestParametersNameValueSeparator) {
this.originalRequestParametersNameValueSeparator = originalRequestParametersNameValueSeparator;
}
public String getOriginalRequestParametersNameValueSeparator() {
return originalRequestParametersNameValueSeparator;
}
public void setOriginalRequestParametersParameterName(
String originalRequestParametersParameterName) {
this.originalRequestParametersParameterName = originalRequestParametersParameterName;
}
public String getOriginalRequestParametersParameterName() {
return originalRequestParametersParameterName;
}
public void setOriginalRequestParametersSeparator(
String originalRequestParametersSeparator) {
this.originalRequestParametersSeparator = originalRequestParametersSeparator;
}
public String getOriginalRequestParametersSeparator() {
return originalRequestParametersSeparator;
}
public void setOriginalRequestUrlParameterName(
String originalRequestUrlParameterName) {
this.originalRequestUrlParameterName = originalRequestUrlParameterName;
}
public String getOriginalRequestUrlParameterName() {
return originalRequestUrlParameterName;
}
/**
* if set to true, the {@link #commence(ServletRequest, ServletResponse)}
* method uses the {@link #getCaptchaFormUrl()} as a complete URL, else it
* as a 'inside WebApp' path.
*
* @param isOutsideWebApp
*/
public void setOutsideWebApp(boolean isOutsideWebApp) {
this.isOutsideWebApp = isOutsideWebApp;
}
public boolean isOutsideWebApp() {
return isOutsideWebApp;
}
public void setPortMapper(PortMapper portMapper) {
this.portMapper = portMapper;
}
public PortMapper getPortMapper() {
return portMapper;
}
public void setPortResolver(PortResolver portResolver) {
this.portResolver = portResolver;
}
public PortResolver getPortResolver() {
return portResolver;
}
public void setUrlEncodingCharset(String urlEncodingCharset) {
this.urlEncodingCharset = urlEncodingCharset;
}
public String getUrlEncodingCharset() {
return urlEncodingCharset;
}
//~ Methods ========================================================================================================
public void afterPropertiesSet() throws Exception {
Assert.hasLength(captchaFormUrl, "captchaFormUrl must be specified");
Assert.hasLength(originalRequestMethodParameterName,
"originalRequestMethodParameterName must be specified");
Assert.hasLength(originalRequestMethodParameterName, "originalRequestMethodParameterName must be specified");
Assert.hasLength(originalRequestParametersNameValueSeparator,
"originalRequestParametersNameValueSeparator must be specified");
Assert.hasLength(originalRequestParametersParameterName,
"originalRequestParametersParameterName must be specified");
Assert.hasLength(originalRequestParametersSeparator,
"originalRequestParametersSeparator must be specified");
Assert.hasLength(originalRequestUrlParameterName,
"originalRequestUrlParameterName must be specified");
Assert.hasLength(urlEncodingCharset,
"urlEncodingCharset must be specified");
Assert.hasLength(originalRequestParametersSeparator, "originalRequestParametersSeparator must be specified");
Assert.hasLength(originalRequestUrlParameterName, "originalRequestUrlParameterName must be specified");
Assert.hasLength(urlEncodingCharset, "urlEncodingCharset must be specified");
Assert.notNull(portMapper, "portMapper must be specified");
Assert.notNull(portResolver, "portResolver must be specified");
URLEncoder.encode(" fzaef é& à ", urlEncodingCharset);
}
public void commence(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
StringBuffer redirectUrl = new StringBuffer();
HttpServletRequest req = (HttpServletRequest) request;
if (isOutsideWebApp) {
redirectUrl = redirectUrl.append(captchaFormUrl);
} else {
buildInternalRedirect(redirectUrl, req);
}
if (includeOriginalRequest) {
includeOriginalRequest(redirectUrl, req);
}
// add post parameter? DONE!
if (logger.isDebugEnabled()) {
logger.debug("Redirecting to: " + redirectUrl);
}
((HttpServletResponse) response).sendRedirect(redirectUrl.toString());
}
private void buildInternalRedirect(StringBuffer redirectUrl,
HttpServletRequest req) {
private void buildInternalRedirect(StringBuffer redirectUrl, HttpServletRequest req) {
// construct it
StringBuffer simpleRedirect = new StringBuffer();
@ -373,8 +179,75 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
}
}
private void includeOriginalRequest(StringBuffer redirectUrl,
HttpServletRequest req) {
public void commence(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
StringBuffer redirectUrl = new StringBuffer();
HttpServletRequest req = (HttpServletRequest) request;
if (isOutsideWebApp) {
redirectUrl = redirectUrl.append(captchaFormUrl);
} else {
buildInternalRedirect(redirectUrl, req);
}
if (includeOriginalRequest) {
includeOriginalRequest(redirectUrl, req);
}
// add post parameter? DONE!
if (logger.isDebugEnabled()) {
logger.debug("Redirecting to: " + redirectUrl);
}
((HttpServletResponse) response).sendRedirect(redirectUrl.toString());
}
/**
* DOCUMENT ME!
*
* @return the captcha test page to redirect to.
*/
public String getCaptchaFormUrl() {
return captchaFormUrl;
}
public boolean getForceHttps() {
return forceHttps;
}
public String getOriginalRequestMethodParameterName() {
return originalRequestMethodParameterName;
}
public String getOriginalRequestParametersNameValueSeparator() {
return originalRequestParametersNameValueSeparator;
}
public String getOriginalRequestParametersParameterName() {
return originalRequestParametersParameterName;
}
public String getOriginalRequestParametersSeparator() {
return originalRequestParametersSeparator;
}
public String getOriginalRequestUrlParameterName() {
return originalRequestUrlParameterName;
}
public PortMapper getPortMapper() {
return portMapper;
}
public PortResolver getPortResolver() {
return portResolver;
}
public String getUrlEncodingCharset() {
return urlEncodingCharset;
}
private void includeOriginalRequest(StringBuffer redirectUrl, HttpServletRequest req) {
// add original request to the url
if (redirectUrl.indexOf("?") >= 0) {
redirectUrl.append("&");
@ -386,8 +259,7 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
redirectUrl.append("=");
try {
redirectUrl.append(URLEncoder.encode(req.getRequestURL().toString(),
urlEncodingCharset));
redirectUrl.append(URLEncoder.encode(req.getRequestURL().toString(), urlEncodingCharset));
} catch (UnsupportedEncodingException e) {
logger.warn(e);
}
@ -423,11 +295,101 @@ public class CaptchaEntryPoint implements ChannelEntryPoint, InitializingBean {
}
try {
redirectUrl.append(URLEncoder.encode(qp.toString(),
urlEncodingCharset));
redirectUrl.append(URLEncoder.encode(qp.toString(), urlEncodingCharset));
} catch (Exception e) {
logger.warn(e);
}
}
}
public boolean isIncludeOriginalParameters() {
return includeOriginalParameters;
}
public boolean isIncludeOriginalRequest() {
return includeOriginalRequest;
}
public boolean isOutsideWebApp() {
return isOutsideWebApp;
}
/**
* The URL where the <code>CaptchaProcessingFilter</code> login page can be found. Should be relative to
* the web-app context path, and include a leading <code>/</code>
*
* @param captchaFormUrl
*/
public void setCaptchaFormUrl(String captchaFormUrl) {
this.captchaFormUrl = captchaFormUrl;
}
// ~ Methods
// ================================================================
/**
* Set to true to force captcha form access to be via https. If this value is ture (the default is false),
* and the incoming request for the protected resource which triggered the interceptor was not already
* <code>https</code>, then
*
* @param forceHttps
*/
public void setForceHttps(boolean forceHttps) {
this.forceHttps = forceHttps;
}
public void setIncludeOriginalParameters(boolean includeOriginalParameters) {
this.includeOriginalParameters = includeOriginalParameters;
}
/**
* If set to true, the original request url will be appended to the redirect url using the {@link
* #getOriginalRequestUrlParameterName()}.
*
* @param includeOriginalRequest
*/
public void setIncludeOriginalRequest(boolean includeOriginalRequest) {
this.includeOriginalRequest = includeOriginalRequest;
}
public void setOriginalRequestMethodParameterName(String originalRequestMethodParameterName) {
this.originalRequestMethodParameterName = originalRequestMethodParameterName;
}
public void setOriginalRequestParametersNameValueSeparator(String originalRequestParametersNameValueSeparator) {
this.originalRequestParametersNameValueSeparator = originalRequestParametersNameValueSeparator;
}
public void setOriginalRequestParametersParameterName(String originalRequestParametersParameterName) {
this.originalRequestParametersParameterName = originalRequestParametersParameterName;
}
public void setOriginalRequestParametersSeparator(String originalRequestParametersSeparator) {
this.originalRequestParametersSeparator = originalRequestParametersSeparator;
}
public void setOriginalRequestUrlParameterName(String originalRequestUrlParameterName) {
this.originalRequestUrlParameterName = originalRequestUrlParameterName;
}
/**
* if set to true, the {@link #commence(ServletRequest, ServletResponse)} method uses the {@link
* #getCaptchaFormUrl()} as a complete URL, else it as a 'inside WebApp' path.
*
* @param isOutsideWebApp
*/
public void setOutsideWebApp(boolean isOutsideWebApp) {
this.isOutsideWebApp = isOutsideWebApp;
}
public void setPortMapper(PortMapper portMapper) {
this.portMapper = portMapper;
}
public void setPortResolver(PortResolver portResolver) {
this.portResolver = portResolver;
}
public void setUrlEncodingCharset(String urlEncodingCharset) {
this.urlEncodingCharset = urlEncodingCharset;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -24,12 +24,26 @@ import org.acegisecurity.context.SecurityContext;
* @author marc antoine garrigue
*/
public interface CaptchaSecurityContext extends SecurityContext {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* set human attribute, should called after captcha validation.
* DOCUMENT ME!
*
* @return number of human restricted resources requests since the last passed captcha.
*/
void setHuman();
int getHumanRestrictedResourcesRequestsCount();
/**
* DOCUMENT ME!
*
* @return the date of the last passed Captcha in millis, 0 if the user never passed captcha.
*/
long getLastPassedCaptchaDateInMillis();
/**
* Method to increment the human Restricted Resrouces Requests Count;
*/
void incrementHumanRestrictedRessoucesRequestsCount();
/**
* DOCUMENT ME!
@ -39,23 +53,7 @@ public interface CaptchaSecurityContext extends SecurityContext {
boolean isHuman();
/**
* DOCUMENT ME!
*
* @return number of human restricted resources requests since the last
* passed captcha.
* set human attribute, should called after captcha validation.
*/
int getHumanRestrictedResourcesRequestsCount();
/**
* DOCUMENT ME!
*
* @return the date of the last passed Captcha in millis, 0 if the user
* never passed captcha.
*/
long getLastPassedCaptchaDateInMillis();
/**
* Method to increment the human Restricted Resrouces Requests Count;
*/
void incrementHumanRestrictedRessoucesRequestsCount();
void setHuman();
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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,15 +23,14 @@ import org.acegisecurity.context.SecurityContextImpl;
*
* @author mag
*/
public class CaptchaSecurityContextImpl extends SecurityContextImpl
implements CaptchaSecurityContext {
//~ Instance fields ========================================================
public class CaptchaSecurityContextImpl extends SecurityContextImpl implements CaptchaSecurityContext {
//~ Instance fields ================================================================================================
private boolean human;
private int humanRestrictedResourcesRequestsCount;
private long lastPassedCaptchaDate;
//~ Constructors ===========================================================
//~ Constructors ===================================================================================================
public CaptchaSecurityContextImpl() {
super();
@ -40,19 +39,28 @@ public class CaptchaSecurityContextImpl extends SecurityContextImpl
humanRestrictedResourcesRequestsCount = 0;
}
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* Reset the lastPassedCaptchaDate and count.
*/
public void setHuman() {
this.human = true;
this.lastPassedCaptchaDate = System.currentTimeMillis();
this.humanRestrictedResourcesRequestsCount = 0;
}
public boolean equals(Object obj) {
if (obj instanceof CaptchaSecurityContextImpl) {
CaptchaSecurityContextImpl rhs = (CaptchaSecurityContextImpl) obj;
public boolean isHuman() {
return human;
if (this.isHuman() != rhs.isHuman()) {
return false;
}
if (this.getHumanRestrictedResourcesRequestsCount() != rhs.getHumanRestrictedResourcesRequestsCount()) {
return false;
}
if (this.getLastPassedCaptchaDateInMillis() != rhs.getLastPassedCaptchaDateInMillis()) {
return false;
}
return super.equals(obj);
}
return false;
}
public int getHumanRestrictedResourcesRequestsCount() {
@ -63,6 +71,18 @@ public class CaptchaSecurityContextImpl extends SecurityContextImpl
return lastPassedCaptchaDate;
}
public int hashCode() {
int code = super.hashCode();
code ^= this.humanRestrictedResourcesRequestsCount;
code ^= this.lastPassedCaptchaDate;
if (this.isHuman()) {
code ^= -37;
}
return code;
}
/**
* Method to increment the human Restricted Resrouces Requests Count;
*/
@ -70,30 +90,16 @@ public class CaptchaSecurityContextImpl extends SecurityContextImpl
humanRestrictedResourcesRequestsCount++;
}
public boolean equals(Object obj) {
if (obj instanceof CaptchaSecurityContextImpl) {
CaptchaSecurityContextImpl rhs = (CaptchaSecurityContextImpl) obj;
if (this.isHuman() != rhs.isHuman()) {
return false;
}
if (this.getHumanRestrictedResourcesRequestsCount() != rhs.getHumanRestrictedResourcesRequestsCount()) {
return false;
}
if (this.getLastPassedCaptchaDateInMillis() != rhs.getLastPassedCaptchaDateInMillis()) {
return false;
}
return super.equals(obj);
}
return false;
}
public boolean isHuman() {
return human;
}
public int hashCode() {
int code = super.hashCode();
code ^= this.humanRestrictedResourcesRequestsCount;
code ^= this.lastPassedCaptchaDate;
if (this.isHuman()) {
code ^= -37;
}
return code;
}
/**
* Reset the lastPassedCaptchaDate and count.
*/
public void setHuman() {
this.human = true;
this.lastPassedCaptchaDate = System.currentTimeMillis();
this.humanRestrictedResourcesRequestsCount = 0;
}
}

View File

@ -1,4 +1,4 @@
/* Copyright 2004, 2005 Acegi Technology Pty Limited
/* Copyright 2004, 2005, 2006 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.
@ -15,8 +15,6 @@
package org.acegisecurity.captcha;
/**
* Provide a common interface for captcha validation.
*
@ -24,7 +22,7 @@ package org.acegisecurity.captcha;
* @version $Id$
*/
public interface CaptchaServiceProxy {
//~ Methods ================================================================
//~ Methods ========================================================================================================
/**
* DOCUMENT ME!
@ -32,8 +30,7 @@ public interface CaptchaServiceProxy {
* @param id the id token
* @param captchaResponse the user response
*
* @return true if the response is validated by the back end captcha
* service.
* @return true if the response is validated by the back end captcha service.
*/
boolean validateReponseForId(String id, Object captchaResponse);
}

Some files were not shown because too many files have changed in this diff Show More