Initial commit.
This commit is contained in:
88
core/src/test/java/org/acegisecurity/BankSecurityVoter.java
Normal file
88
core/src/test/java/org/acegisecurity/BankSecurityVoter.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity;
|
||||
|
||||
import net.sf.acegisecurity.vote.AccessDecisionVoter;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of an {@link AccessDecisionVoter} that provides a token
|
||||
* example of application-specific security.
|
||||
*
|
||||
* <p>
|
||||
* If the {@link ConfigAttribute#getAttribute()} has a value of
|
||||
* <code>BANKSECURITY_CUSTOMER</code>, the account number subject of the
|
||||
* method call to be compared with any granted authority prefixed with
|
||||
* <code>ACCOUNT_</code> and followed by that account number. For example, if
|
||||
* account number 12 was subject of the call, a search would be conducted for
|
||||
* a granted authority named <code>ACCOUNT_12</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* All comparisons are case sensitive.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BankSecurityVoter implements AccessDecisionVoter {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ("BANKSECURITY_CUSTOMER".equals(attribute.getAttribute())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int vote(Authentication authentication, MethodInvocation invocation,
|
||||
ConfigAttributeDefinition config) {
|
||||
int result = ACCESS_ABSTAIN;
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attribute)) {
|
||||
result = ACCESS_DENIED;
|
||||
|
||||
// Lookup the account number being passed
|
||||
Integer accountNumber = null;
|
||||
|
||||
for (int i = 0; i < invocation.getArgumentCount(); i++) {
|
||||
Class argClass = invocation.getArgument(i).getClass();
|
||||
|
||||
if (Integer.class.isAssignableFrom(argClass)) {
|
||||
accountNumber = (Integer) invocation.getArgument(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (accountNumber != null) {
|
||||
// Attempt to find a matching granted authority
|
||||
String targetAttribute = "ACCOUNT_"
|
||||
+ accountNumber.toString();
|
||||
|
||||
for (int i = 0; i < authentication.getAuthorities().length;
|
||||
i++) {
|
||||
if (targetAttribute.equals(
|
||||
authentication.getAuthorities()[i].getAuthority())) {
|
||||
return ACCESS_GRANTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity;
|
||||
|
||||
import net.sf.acegisecurity.context.ContextInvalidException;
|
||||
import net.sf.acegisecurity.context.SecureContextImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Demonstrates subclassing the {@link SecureContextImpl} with
|
||||
* application-specific requirements.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ExoticSecureContext extends SecureContextImpl {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private int magicNumber;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setMagicNumber(int magicNumber) {
|
||||
this.magicNumber = magicNumber;
|
||||
}
|
||||
|
||||
public int getMagicNumber() {
|
||||
return magicNumber;
|
||||
}
|
||||
|
||||
public void validate() throws ContextInvalidException {
|
||||
super.validate();
|
||||
|
||||
if (magicNumber != 7) {
|
||||
throw new ContextInvalidException("Magic number is not 7");
|
||||
}
|
||||
}
|
||||
}
|
||||
217
core/src/test/java/org/acegisecurity/SecurityTests.java
Normal file
217
core/src/test/java/org/acegisecurity/SecurityTests.java
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.context.Account;
|
||||
import net.sf.acegisecurity.context.BankManager;
|
||||
import net.sf.acegisecurity.context.Context;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.ContextImpl;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
import net.sf.acegisecurity.context.SecureContextImpl;
|
||||
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Tests security objects.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class SecurityTests extends TestCase {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public SecurityTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public SecurityTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ctx = new ClassPathXmlApplicationContext(
|
||||
"/net/sf/acegisecurity/applicationContext.xml");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(SecurityTests.class);
|
||||
}
|
||||
|
||||
public void testDetectsInvalidConfigAttribute() throws Exception {
|
||||
try {
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
|
||||
"/net/sf/acegisecurity/badContext.xml");
|
||||
fail("Should have thrown BeanCreationException");
|
||||
} catch (BeanCreationException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSecurityInterceptorCustomVoter() throws Exception {
|
||||
Account marissa = new Account(2, "marissa");
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
// Indicate the authenticated user holds an account number of 65
|
||||
GrantedAuthority[] useless = {new GrantedAuthorityImpl("ACCOUNT_65")};
|
||||
TestingAuthenticationToken auth = new TestingAuthenticationToken("Peter",
|
||||
"emu", useless);
|
||||
SecureContext secureContext = new SecureContextImpl();
|
||||
secureContext.setAuthentication(auth);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
// Confirm the absence of holding a valid account number rejects access
|
||||
try {
|
||||
bank.saveAccount(marissa);
|
||||
fail("Should have thrown an AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now setup a user with the correct account number
|
||||
GrantedAuthority[] account2 = {new GrantedAuthorityImpl("ACCOUNT_2")};
|
||||
auth = new TestingAuthenticationToken("Kristy", "opal", account2);
|
||||
secureContext.setAuthentication(auth);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
// Check the user can perform operations related to their account number
|
||||
bank.loadAccount(marissa.getId());
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
|
||||
public void testSecurityInterceptorDetectsInvalidContexts()
|
||||
throws Exception {
|
||||
// Normally the security interceptor does not need to detect these conditions,
|
||||
// because the context interceptor should with its validate method. However,
|
||||
// the security interceptor still checks it is passed the correct objects.
|
||||
Account ben = new Account(1, "ben");
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
// First try with a totally empty ContextHolder
|
||||
try {
|
||||
bank.saveAccount(ben);
|
||||
fail(
|
||||
"Should have thrown AuthenticationCredentialsNotFoundException");
|
||||
} catch (AuthenticationCredentialsNotFoundException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try with a ContextHolder but of the wrong type (not a SecureContext)
|
||||
Context context = new ContextImpl();
|
||||
ContextHolder.setContext(context);
|
||||
|
||||
try {
|
||||
bank.saveAccount(ben);
|
||||
fail(
|
||||
"Should have thrown AuthenticationCredentialsNotFoundException");
|
||||
} catch (AuthenticationCredentialsNotFoundException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Next try with a SecureContext but without an authentication object in it
|
||||
SecureContext secureContext = new SecureContextImpl();
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
bank.saveAccount(ben);
|
||||
fail(
|
||||
"Should have thrown AuthenticationCredentialsNotFoundException");
|
||||
} catch (AuthenticationCredentialsNotFoundException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try with a SecureContext, correctly setup, which should work
|
||||
GrantedAuthority[] granted = {new GrantedAuthorityImpl(
|
||||
"ROLE_SUPERVISOR")};
|
||||
TestingAuthenticationToken auth = new TestingAuthenticationToken("Jeni",
|
||||
"kangaroo", granted);
|
||||
secureContext.setAuthentication(auth);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
Account marissa = new Account(2, "marissa");
|
||||
marissa.deposit(2000);
|
||||
bank.saveAccount(marissa);
|
||||
assertTrue(2000 == bank.getBalance(marissa.getId()));
|
||||
|
||||
// Now confirm if we subclass SecureContextImpl it still works.
|
||||
// Note the validate method in our ExoticSecureContext will not be
|
||||
// called, as we do not have the context interceptor defined.
|
||||
ExoticSecureContext exoticContext = new ExoticSecureContext();
|
||||
exoticContext.setAuthentication(auth);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
Account scott = new Account(3, "scott");
|
||||
scott.deposit(50);
|
||||
bank.saveAccount(scott);
|
||||
assertTrue(50 == bank.getBalance(scott.getId()));
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
|
||||
public void testSecurityInterceptorEnforcesRoles()
|
||||
throws Exception {
|
||||
Account ben = new Account(1, "ben");
|
||||
ben.deposit(25);
|
||||
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
// Indicate the authenticated user holds a role that is not useful
|
||||
GrantedAuthority[] useless = {new GrantedAuthorityImpl(
|
||||
"ROLE_NOTHING_USEFUL")};
|
||||
TestingAuthenticationToken auth = new TestingAuthenticationToken("George",
|
||||
"koala", useless);
|
||||
SecureContext secureContext = new SecureContextImpl();
|
||||
secureContext.setAuthentication(auth);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
// Confirm the absence of holding a valid role rejects access
|
||||
try {
|
||||
bank.saveAccount(ben);
|
||||
fail("Should have thrown an AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try to call a public method (getBankFundsUnderControl)
|
||||
bank.getBankFundsUnderControl();
|
||||
|
||||
// Now setup a user with only a teller role
|
||||
GrantedAuthority[] teller = {new GrantedAuthorityImpl("ROLE_TELLER")};
|
||||
auth = new TestingAuthenticationToken("Michelle", "wombat", teller);
|
||||
secureContext.setAuthentication(auth);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
// Confirm the absence of ROLE_SUPERVISOR prevents calling deleteAccount
|
||||
try {
|
||||
bank.deleteAccount(ben.getId());
|
||||
fail("Should have thrown an AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Check the teller can perform ROLE_TELLER secured operations
|
||||
bank.saveAccount(ben);
|
||||
assertTrue(25 == bank.getBalance(ben.getId()));
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.adapters;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.AuthenticationManager;
|
||||
import net.sf.acegisecurity.adapters.jetty.JettyAcegiUserToken;
|
||||
import net.sf.acegisecurity.providers.ProviderNotFoundException;
|
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthByAdapterProvider}
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthByAdapterTests extends TestCase {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public AuthByAdapterTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public AuthByAdapterTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ctx = new ClassPathXmlApplicationContext(
|
||||
"/net/sf/acegisecurity/adapters/applicationContext.xml");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(AuthByAdapterTests.class);
|
||||
}
|
||||
|
||||
public void testAdapterProvider() throws Exception {
|
||||
AuthenticationManager authMgr = (AuthenticationManager) ctx.getBean(
|
||||
"providerManager");
|
||||
|
||||
// Should authenticate as JettySpringUser is interface of AuthByAdapter
|
||||
JettyAcegiUserToken jetty = new JettyAcegiUserToken("my_password",
|
||||
"Test", "Password", null);
|
||||
Authentication response = authMgr.authenticate(jetty);
|
||||
jetty = null;
|
||||
assertTrue(true);
|
||||
|
||||
// Should fail as UsernamePassword is not interface of AuthByAdapter
|
||||
UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken("Test",
|
||||
"Password");
|
||||
|
||||
try {
|
||||
Authentication response2 = authMgr.authenticate(user);
|
||||
fail("Should have thrown ProviderNotFoundException");
|
||||
} catch (ProviderNotFoundException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- Authentication provider that accepts as valid any adapter-created Authentication token -->
|
||||
<bean id="authByAdapterProvider" class="net.sf.acegisecurity.adapters.AuthByAdapterProvider">
|
||||
<property name="key"><value>my_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- The authentication manager that iterates through our authentication providers -->
|
||||
<bean id="providerManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref bean="authByAdapterProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
84
core/src/test/java/org/acegisecurity/applicationContext.xml
Normal file
84
core/src/test/java/org/acegisecurity/applicationContext.xml
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- This authentication provider accepts any presented TestingAuthenticationToken -->
|
||||
<bean id="testingAuthenticationProvider" class="net.sf.acegisecurity.providers.TestingAuthenticationProvider"/>
|
||||
|
||||
<!-- The authentication manager that iterates through our only authentication provider -->
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref bean="testingAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads BANKSECURITY_CUSTOMER configuaration settings -->
|
||||
<bean id="bankSecurityVoter" class="net.sf.acegisecurity.BankSecurityVoter"/>
|
||||
|
||||
<!-- An affirmative access decision manager -->
|
||||
<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
<ref bean="bankSecurityVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<!-- No declaration for BankManager.getBankFundsUnderControl() makes it public -->
|
||||
<bean id="bankManagerSecurity" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource">
|
||||
<value>
|
||||
net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR
|
||||
net.sf.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER
|
||||
net.sf.acegisecurity.context.BankManager.loadAccount=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER
|
||||
net.sf.acegisecurity.context.BankManager.saveAccount=ROLE_TELLER,ROLE_SUPERVISOR
|
||||
net.sf.acegisecurity.context.BankManager.transferFunds=ROLE_SUPERVISOR
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="bankManagerTarget" class="net.sf.acegisecurity.context.BankManagerImpl"/>
|
||||
|
||||
<!-- We don't include any context interceptor, although we should do so prior to the security interceptor -->
|
||||
<bean id="bankManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>net.sf.acegisecurity.context.BankManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>bankManagerSecurity</value>
|
||||
<value>bankManagerTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.attribute;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||
import net.sf.acegisecurity.MethodDefinitionAttributes;
|
||||
import net.sf.acegisecurity.SecurityConfig;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContextImpl;
|
||||
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author CameronBraid
|
||||
*/
|
||||
public class AttributesTests extends TestCase {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
ClassPathXmlApplicationContext applicationContext;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AttributesTests(String a) {
|
||||
super(a);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void testAttributesForImpl() throws Exception {
|
||||
ConfigAttributeDefinition def = getConfigAttributeDefinition(TestServiceImpl.class);
|
||||
Set set = toSet(def);
|
||||
assertTrue(set.contains(new SecurityConfig("ROLE_INTERFACE")));
|
||||
assertTrue(set.contains(new SecurityConfig("ROLE_INTERFACE_METHOD")));
|
||||
|
||||
assertTrue(set.contains(new SecurityConfig("ROLE_CLASS")));
|
||||
assertTrue(set.contains(new SecurityConfig("ROLE_CLASS_METHOD")));
|
||||
}
|
||||
|
||||
public void testAttributesForInterface() throws Exception {
|
||||
ConfigAttributeDefinition def = getConfigAttributeDefinition(TestService.class);
|
||||
Set set = toSet(def);
|
||||
System.out.println(set.toString());
|
||||
assertTrue(set.contains(new SecurityConfig("ROLE_INTERFACE")));
|
||||
assertTrue(set.contains(new SecurityConfig("ROLE_INTERFACE_METHOD")));
|
||||
}
|
||||
|
||||
public void testInterceptionWithMockAttributesAndSecureContext()
|
||||
throws Exception {
|
||||
applicationContext = new ClassPathXmlApplicationContext(
|
||||
"/net/sf/acegisecurity/attribute/applicationContext.xml");
|
||||
|
||||
TestService service = (TestService) applicationContext.getBean(
|
||||
"testService");
|
||||
|
||||
SecureContextImpl context = new SecureContextImpl();
|
||||
ContextHolder.setContext(context);
|
||||
|
||||
Authentication auth;
|
||||
|
||||
auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_CLASS"), new GrantedAuthorityImpl(
|
||||
"ROLE_INTERFACE"), new GrantedAuthorityImpl(
|
||||
"ROLE_CLASS_METHOD"), new GrantedAuthorityImpl(
|
||||
"ROLE_INTERFACE_METHOD")});
|
||||
|
||||
context.setAuthentication(auth);
|
||||
service.myMethod();
|
||||
|
||||
auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {});
|
||||
context.setAuthentication(auth);
|
||||
|
||||
try {
|
||||
service.myMethod();
|
||||
fail(
|
||||
"security interceptor should have detected insufficient permissions");
|
||||
} catch (Exception e) {}
|
||||
|
||||
applicationContext.close();
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
|
||||
private ConfigAttributeDefinition getConfigAttributeDefinition(Class clazz)
|
||||
throws Exception {
|
||||
final Method method = clazz.getMethod("myMethod", null);
|
||||
MethodDefinitionAttributes source = new MethodDefinitionAttributes();
|
||||
source.setAttributes(new TestAttributes());
|
||||
|
||||
ConfigAttributeDefinition config = source.getAttributes(new MockMethodInvocation() {
|
||||
public Method getMethod() {
|
||||
return method;
|
||||
}
|
||||
});
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a ConfigAttributeDefinition into a set of
|
||||
* <code>ConfigAttribute</code>(s)
|
||||
*
|
||||
* @param def DOCUMENT ME!
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Set toSet(ConfigAttributeDefinition def) {
|
||||
Set set = new HashSet();
|
||||
Iterator i = def.getConfigAttributes();
|
||||
|
||||
while (i.hasNext()) {
|
||||
ConfigAttribute a = (ConfigAttribute) i.next();
|
||||
set.add(a);
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.attribute;
|
||||
|
||||
import org.springframework.metadata.Attributes;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author CameronBraid
|
||||
*/
|
||||
public class MockAttributes implements Attributes {
|
||||
//~ Methods ================================================================
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.metadata.Attributes#getAttributes(java.lang.Class, java.lang.Class)
|
||||
*/
|
||||
public Collection getAttributes(Class arg0, Class arg1) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.metadata.Attributes#getAttributes(java.lang.Class)
|
||||
*/
|
||||
public Collection getAttributes(Class arg0) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.metadata.Attributes#getAttributes(java.lang.reflect.Field, java.lang.Class)
|
||||
*/
|
||||
public Collection getAttributes(Field arg0, Class arg1) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.metadata.Attributes#getAttributes(java.lang.reflect.Field)
|
||||
*/
|
||||
public Collection getAttributes(Field arg0) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.metadata.Attributes#getAttributes(java.lang.reflect.Method, java.lang.Class)
|
||||
*/
|
||||
public Collection getAttributes(Method arg0, Class arg1) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.metadata.Attributes#getAttributes(java.lang.reflect.Method)
|
||||
*/
|
||||
public Collection getAttributes(Method arg0) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.attribute;
|
||||
|
||||
import org.aopalliance.intercept.AttributeRegistry;
|
||||
import org.aopalliance.intercept.Invocation;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author CameronBraid
|
||||
*/
|
||||
public class MockMethodInvocation implements MethodInvocation {
|
||||
//~ Methods ================================================================
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Invocation#setArgument(int, java.lang.Object)
|
||||
*/
|
||||
public void setArgument(int arg0, Object arg1) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Invocation#getArgument(int)
|
||||
*/
|
||||
public Object getArgument(int arg0) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Invocation#getArgumentCount()
|
||||
*/
|
||||
public int getArgumentCount() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Invocation#getArguments()
|
||||
*/
|
||||
public Object[] getArguments() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Invocation#getAttachment(java.lang.String)
|
||||
*/
|
||||
public Object getAttachment(String arg0) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Invocation#getAttributeRegistry()
|
||||
*/
|
||||
public AttributeRegistry getAttributeRegistry() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.MethodInvocation#getMethod()
|
||||
*/
|
||||
public Method getMethod() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Joinpoint#getStaticPart()
|
||||
*/
|
||||
public AccessibleObject getStaticPart() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Joinpoint#getThis()
|
||||
*/
|
||||
public Object getThis() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Invocation#addAttachment(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
public Object addAttachment(String arg0, Object arg1) {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Invocation#cloneInstance()
|
||||
*/
|
||||
public Invocation cloneInstance() {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.Joinpoint#proceed()
|
||||
*/
|
||||
public Object proceed() throws Throwable {
|
||||
throw new UnsupportedOperationException("mock method not implemented");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.attribute;
|
||||
|
||||
import net.sf.acegisecurity.SecurityConfig;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author CameronBraid
|
||||
*/
|
||||
public class TestAttributes extends MockAttributes {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
List classAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
|
||||
"ROLE_CLASS")});
|
||||
List classMethodAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
|
||||
"ROLE_CLASS_METHOD")});
|
||||
List intrefaceAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
|
||||
"ROLE_INTERFACE")});
|
||||
List intrefaceMethodAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
|
||||
"ROLE_INTERFACE_METHOD")});
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public Collection getAttributes(Class clazz) {
|
||||
// interface
|
||||
if (clazz.equals(TestServiceImpl.class)) {
|
||||
return classAttributes;
|
||||
}
|
||||
|
||||
// class
|
||||
if (clazz.equals(TestService.class)) {
|
||||
return intrefaceAttributes;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection getAttributes(Method method) {
|
||||
// interface
|
||||
if (method.getDeclaringClass().equals(TestService.class)) {
|
||||
return intrefaceMethodAttributes;
|
||||
}
|
||||
|
||||
// class
|
||||
if (method.getDeclaringClass().equals(TestServiceImpl.class)) {
|
||||
return classMethodAttributes;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.attribute;
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author CameronBraid
|
||||
*/
|
||||
public interface TestService {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public abstract void myMethod();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.attribute;
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author CameronBraid
|
||||
*/
|
||||
public class TestServiceImpl implements TestService {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void myMethod() {}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- This authentication provider accepts any presented TestingAuthenticationToken -->
|
||||
<bean id="testingAuthenticationProvider" class="net.sf.acegisecurity.providers.TestingAuthenticationProvider"/>
|
||||
|
||||
<!-- The authentication manager that iterates through our only authentication provider -->
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref bean="testingAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An affirmative access decision manager -->
|
||||
<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<bean id="attributes" class="net.sf.acegisecurity.attribute.TestAttributes"/>
|
||||
<bean id="methodDefinitionSource" class="net.sf.acegisecurity.MethodDefinitionAttributes">
|
||||
<property name="attributes"><ref local="attributes"/></property>
|
||||
</bean>
|
||||
|
||||
<!-- We don't validate config attributes, as it's unsupported by MethodDefinitionAttributes -->
|
||||
<bean id="securityInterceptor" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="validateConfigAttributes"><value>false</value></property>
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource"><ref bean="methodDefinitionSource"/></property>
|
||||
</bean>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="testService" class="net.sf.acegisecurity.attribute.TestServiceImpl"/>
|
||||
|
||||
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
|
||||
|
||||
<!-- names of the interceptors that will be applied by the proxy -->
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>securityInterceptor</value>
|
||||
</list>
|
||||
</property>
|
||||
|
||||
<!-- the bean names to automatically generate proxies for -->
|
||||
<property name="beanNames">
|
||||
<list>
|
||||
<value>testService</value>
|
||||
</list>
|
||||
</property>
|
||||
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
66
core/src/test/java/org/acegisecurity/badContext.xml
Normal file
66
core/src/test/java/org/acegisecurity/badContext.xml
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- This authentication provider accepts any presented TestingAuthenticationToken -->
|
||||
<bean id="testingAuthenticationProvider" class="net.sf.acegisecurity.providers.TestingAuthenticationProvider"/>
|
||||
|
||||
<!-- The authentication manager that iterates through our only authentication provider -->
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref bean="testingAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads BANKSECURITY_CUSTOMER configuaration settings -->
|
||||
<bean id="bankSecurityVoter" class="net.sf.acegisecurity.BankSecurityVoter"/>
|
||||
|
||||
<!-- An affirmative access decision manager -->
|
||||
<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
<ref bean="bankSecurityVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<!-- Note the INVALID_ATTRIBUTE should be detected at bean context startup time -->
|
||||
<bean id="bankManagerSecurity" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource">
|
||||
<value>
|
||||
net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR
|
||||
net.sf.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,INVALID_ATTRIBUTE,BANKSECURITY_CUSTOMER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
57
core/src/test/java/org/acegisecurity/context/Account.java
Normal file
57
core/src/test/java/org/acegisecurity/context/Account.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.context;
|
||||
|
||||
/**
|
||||
* Models a bank account.
|
||||
*/
|
||||
public class Account {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private Integer id;
|
||||
private String owningUserName;
|
||||
private float balance;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public Account(Integer id, String owningUserName) {
|
||||
this.id = id;
|
||||
this.owningUserName = owningUserName;
|
||||
}
|
||||
|
||||
public Account(int id, String owningUserName) {
|
||||
this.id = new Integer(id);
|
||||
this.owningUserName = owningUserName;
|
||||
}
|
||||
|
||||
private Account() {
|
||||
super();
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public float getBalance() {
|
||||
return this.balance;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getOwningUserName() {
|
||||
return this.owningUserName;
|
||||
}
|
||||
|
||||
public void deposit(float amount) {
|
||||
this.balance = this.balance + amount;
|
||||
}
|
||||
|
||||
public void withdraw(float amount) {
|
||||
this.balance = this.balance - amount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.context;
|
||||
|
||||
/**
|
||||
* Simple business object of an in-memory banking system.
|
||||
*
|
||||
* <p>
|
||||
* We'll spare you from <code>InsufficientFundsExceptions</code> etc. After
|
||||
* all, this is intended to test security features rather than OO design!
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface BankManager {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public float getBalance(Integer accountNumber);
|
||||
|
||||
public float getBankFundsUnderControl();
|
||||
|
||||
public void deleteAccount(Integer accountNumber);
|
||||
|
||||
public Account loadAccount(Integer accountNumber);
|
||||
|
||||
public void saveAccount(Account account);
|
||||
|
||||
public void transferFunds(Integer fromAccountNumber,
|
||||
Integer toAccountNumber, float amount);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.context;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of {@link BankManager}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BankManagerImpl implements BankManager {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private Map accounts = new HashMap();
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public float getBalance(Integer accountNumber) {
|
||||
Account account = this.loadAccount(accountNumber);
|
||||
|
||||
return account.getBalance();
|
||||
}
|
||||
|
||||
public float getBankFundsUnderControl() {
|
||||
float total = 0;
|
||||
Iterator iter = this.accounts.keySet().iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Integer account = (Integer) iter.next();
|
||||
total = total + this.getBalance(account);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
public void deleteAccount(Integer accountNumber) {
|
||||
this.accounts.remove(accountNumber);
|
||||
}
|
||||
|
||||
public Account loadAccount(Integer accountNumber) {
|
||||
return (Account) accounts.get(accountNumber);
|
||||
}
|
||||
|
||||
public void saveAccount(Account account) {
|
||||
this.accounts.put(account.getId(), account);
|
||||
}
|
||||
|
||||
public void transferFunds(Integer fromAccountNumber,
|
||||
Integer toAccountNumber, float amount) {
|
||||
Account from = this.loadAccount(fromAccountNumber);
|
||||
Account to = this.loadAccount(toAccountNumber);
|
||||
from.withdraw(amount);
|
||||
to.deposit(amount);
|
||||
this.saveAccount(from);
|
||||
this.saveAccount(to);
|
||||
}
|
||||
}
|
||||
120
core/src/test/java/org/acegisecurity/context/ContextTests.java
Normal file
120
core/src/test/java/org/acegisecurity/context/ContextTests.java
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.context;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Tests context objects.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ContextTests extends TestCase {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public ContextTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ContextTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ctx = new ClassPathXmlApplicationContext(
|
||||
"/net/sf/acegisecurity/context/applicationContext.xml");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(ContextTests.class);
|
||||
}
|
||||
|
||||
public void testContextInterceptorDetectsEmptyContexts()
|
||||
throws Exception {
|
||||
Account ben = new Account(1, "ben");
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
try {
|
||||
bank.saveAccount(ben);
|
||||
fail("Should have thrown ContextHolderEmptyException");
|
||||
} catch (ContextHolderEmptyException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
Context context = new ContextImpl();
|
||||
ContextHolder.setContext(context);
|
||||
|
||||
Account marissa = new Account(2, "marissa");
|
||||
bank.saveAccount(marissa);
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
|
||||
public void testContextInterceptorProcessesValidations()
|
||||
throws Exception {
|
||||
ExoticContext context = new ExoticContext();
|
||||
ContextHolder.setContext(context);
|
||||
|
||||
Account ben = new Account(1, "ben");
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
try {
|
||||
bank.saveAccount(ben);
|
||||
fail(
|
||||
"Should have thrown ContextInvalidException (magic number is incorrect)");
|
||||
} catch (ContextInvalidException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
context.setMagicNumber(7);
|
||||
ContextHolder.setContext(context);
|
||||
|
||||
Account marissa = new Account(2, "marissa");
|
||||
bank.saveAccount(marissa);
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
|
||||
public void testContextInterceptorValidatesASecureContext()
|
||||
throws Exception {
|
||||
SecureContext context = new SecureContextImpl();
|
||||
ContextHolder.setContext((Context) context);
|
||||
|
||||
Account ben = new Account(1, "ben");
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
try {
|
||||
bank.saveAccount(ben);
|
||||
fail(
|
||||
"Should have thrown ContextInvalidException (no authentication object)");
|
||||
} catch (ContextInvalidException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
context.setAuthentication(new TestingAuthenticationToken("a", "b", null));
|
||||
ContextHolder.setContext((Context) context);
|
||||
|
||||
Account marissa = new Account(2, "marissa");
|
||||
bank.saveAccount(marissa);
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.context;
|
||||
|
||||
/**
|
||||
* Exotic implementation of a {@link Context}.
|
||||
*
|
||||
* <p>
|
||||
* Requires the context to be set with a <code>magicNumber</code> of 7. Tests
|
||||
* validation in the unit tests.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ExoticContext implements Context {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private int magicNumber;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setMagicNumber(int magicNumber) {
|
||||
this.magicNumber = magicNumber;
|
||||
}
|
||||
|
||||
public int getMagicNumber() {
|
||||
return magicNumber;
|
||||
}
|
||||
|
||||
public void validate() throws ContextInvalidException {
|
||||
if (magicNumber != 7) {
|
||||
throw new ContextInvalidException("Magic number is not 7");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== CONTEXT RELATED DEFINITIONS ================== -->
|
||||
|
||||
<bean id="contextInterceptor" class="net.sf.acegisecurity.context.ContextInterceptor"/>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="bankManagerTarget" class="net.sf.acegisecurity.context.BankManagerImpl"/>
|
||||
|
||||
<bean id="bankManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>net.sf.acegisecurity.context.BankManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>contextInterceptor</value>
|
||||
<value>bankManagerTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.providers.dao.memory;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
import net.sf.acegisecurity.BadCredentialsException;
|
||||
import net.sf.acegisecurity.DisabledException;
|
||||
import net.sf.acegisecurity.context.Account;
|
||||
import net.sf.acegisecurity.context.BankManager;
|
||||
import net.sf.acegisecurity.context.Context;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
import net.sf.acegisecurity.context.SecureContextImpl;
|
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link DaoAuthenticationProvider} with {@link InMemoryDaoImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class InMemoryDaoTests extends TestCase {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public InMemoryDaoTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public InMemoryDaoTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ctx = new ClassPathXmlApplicationContext(
|
||||
"/net/sf/acegisecurity/providers/dao/memory/applicationContext.xml");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(InMemoryDaoTests.class);
|
||||
}
|
||||
|
||||
public void testAuthentication() throws Exception {
|
||||
Account account = new Account(1, "someone");
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
// Try with an invalid username and password
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("jennifer",
|
||||
"zebra");
|
||||
SecureContext secureContext = new SecureContextImpl();
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
bank.saveAccount(account);
|
||||
fail("Should have thrown a BadCredentialsException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Check our token represents itself properly as a String
|
||||
System.out.println(token.toString());
|
||||
assertTrue(token.toString().length() > 10);
|
||||
|
||||
// Now try with a valid username, but invalid password
|
||||
token = new UsernamePasswordAuthenticationToken("marissa", "zebra");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
bank.saveAccount(account);
|
||||
fail("Should have thrown a BadCredentialsException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try with a valid username and password, but disabled user
|
||||
token = new UsernamePasswordAuthenticationToken("dianne", "emu");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
bank.saveAccount(account);
|
||||
fail("Should have thrown a DisabledException");
|
||||
} catch (DisabledException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try as a user who didn't have a password defined, and thus
|
||||
// would have been considered invalid at time of creation
|
||||
token = new UsernamePasswordAuthenticationToken("someoneelse", "");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
bank.saveAccount(account);
|
||||
fail("Should have thrown a BadCredentialsException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try as a user who had a password, but no granted authorities,
|
||||
// and thus would have been considered invalid at time of creation
|
||||
token = new UsernamePasswordAuthenticationToken("someone", "password");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
bank.saveAccount(account);
|
||||
fail("Should have thrown a BadCredentialsException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try with a valid mixed case username, valid mixed case password,
|
||||
// (application context requires passwords to be case matched)
|
||||
token = new UsernamePasswordAuthenticationToken("MaRiSsA", "kOaLa");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
bank.saveAccount(account);
|
||||
fail("Should have thrown a BadCredentialsException");
|
||||
} catch (BadCredentialsException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try with a valid mixed case username, correct case password,
|
||||
// (application context does not require usernames to be case matched)
|
||||
token = new UsernamePasswordAuthenticationToken("MaRiSsA", "koala");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
bank.saveAccount(account);
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
|
||||
public void testAuthorization() throws Exception {
|
||||
Account account = new Account(45, "someone");
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
// Try as a user without access to the account
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter",
|
||||
"opal");
|
||||
SecureContext secureContext = new SecureContextImpl();
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
// NB: account number 45 != granted authority for account 77
|
||||
bank.loadAccount(account.getId());
|
||||
fail("Should have thrown an AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try as user with access to account number 45
|
||||
token = new UsernamePasswordAuthenticationToken("scott", "wombat");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
bank.loadAccount(account.getId());
|
||||
assertTrue(true);
|
||||
|
||||
// Now try as user with ROLE_SUPERVISOR access to the account
|
||||
token = new UsernamePasswordAuthenticationToken("marissa", "koala");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
bank.loadAccount(account.getId());
|
||||
assertTrue(true);
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- Data access object which stores authentication information -->
|
||||
<!-- The two invalid entries at the bottom are provided for testing purposes -->
|
||||
<bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
|
||||
<property name="userMap">
|
||||
<value>
|
||||
marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR
|
||||
dianne=emu,disabled,ROLE_TELLER
|
||||
scott=wombat,ACCOUNT_45
|
||||
peter=opal,ACCOUNT_77
|
||||
someone=password
|
||||
someoneelse=
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Authentication provider that queries our data access object -->
|
||||
<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
||||
<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
|
||||
<property name="ignorePasswordCase"><value>false</value></property>
|
||||
<property name="ignoreUsernameCase"><value>true</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Authentication provider that accepts as valid our RunAsManagerImpl created tokens -->
|
||||
<bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- The authentication manager that iterates through our authentication providers -->
|
||||
<!-- Strictly we don't need runAsAuthenticationProvider given we haven't defined any RUN_AS configurations -->
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref bean="daoAuthenticationProvider"/>
|
||||
<ref bean="runAsAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads BANKSECURITY_CUSTOMER configuaration settings -->
|
||||
<bean id="bankSecurityVoter" class="net.sf.acegisecurity.BankSecurityVoter"/>
|
||||
|
||||
<!-- An affirmative access decision manager -->
|
||||
<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
<ref bean="bankSecurityVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<!-- No declaration for BankManager.getBankFundsUnderControl() makes it public -->
|
||||
<bean id="bankManagerSecurity" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource">
|
||||
<value>
|
||||
net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR
|
||||
net.sf.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER
|
||||
net.sf.acegisecurity.context.BankManager.loadAccount=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER
|
||||
net.sf.acegisecurity.context.BankManager.saveAccount=ROLE_TELLER,ROLE_SUPERVISOR
|
||||
net.sf.acegisecurity.context.BankManager.transferFunds=ROLE_SUPERVISOR
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="bankManagerTarget" class="net.sf.acegisecurity.context.BankManagerImpl"/>
|
||||
|
||||
<!-- We don't include any context interceptor, although we should do so prior to the security interceptor -->
|
||||
<bean id="bankManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>net.sf.acegisecurity.context.BankManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>bankManagerSecurity</value>
|
||||
<value>bankManagerTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.runas;
|
||||
|
||||
import net.sf.acegisecurity.context.Account;
|
||||
import net.sf.acegisecurity.context.BankManager;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
|
||||
/**
|
||||
* Acts as the "public facade" to a <code>BankManager</code>.
|
||||
*
|
||||
* <P>
|
||||
* The security configuration of this, the public facade, specifies authorities
|
||||
* that should be held by the end user. The security configuration of the
|
||||
* "backend", which is not accessible to the general public, specifies certain
|
||||
* authorities that are granted by the RunAsManagerImpl.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BankManagerPublicFacade implements BankManager, InitializingBean {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private BankManager backend;
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setBackend(BankManager backend) {
|
||||
this.backend = backend;
|
||||
}
|
||||
|
||||
public BankManager getBackend() {
|
||||
return backend;
|
||||
}
|
||||
|
||||
public float getBalance(Integer accountNumber) {
|
||||
return backend.getBalance(accountNumber);
|
||||
}
|
||||
|
||||
public float getBankFundsUnderControl() {
|
||||
return backend.getBankFundsUnderControl();
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (backend == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"A backend BankManager implementation is required");
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAccount(Integer accountNumber) {
|
||||
backend.deleteAccount(accountNumber);
|
||||
}
|
||||
|
||||
public Account loadAccount(Integer accountNumber) {
|
||||
return backend.loadAccount(accountNumber);
|
||||
}
|
||||
|
||||
public void saveAccount(Account account) {
|
||||
backend.saveAccount(account);
|
||||
}
|
||||
|
||||
public void transferFunds(Integer fromAccountNumber,
|
||||
Integer toAccountNumber, float amount) {
|
||||
backend.transferFunds(fromAccountNumber, toAccountNumber, amount);
|
||||
}
|
||||
}
|
||||
106
core/src/test/java/org/acegisecurity/runas/RunAsTests.java
Normal file
106
core/src/test/java/org/acegisecurity/runas/RunAsTests.java
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.runas;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
import net.sf.acegisecurity.context.Account;
|
||||
import net.sf.acegisecurity.context.BankManager;
|
||||
import net.sf.acegisecurity.context.Context;
|
||||
import net.sf.acegisecurity.context.ContextHolder;
|
||||
import net.sf.acegisecurity.context.SecureContext;
|
||||
import net.sf.acegisecurity.context.SecureContextImpl;
|
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link RunAsManagerImpl}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class RunAsTests extends TestCase {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public RunAsTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public RunAsTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ctx = new ClassPathXmlApplicationContext(
|
||||
"/net/sf/acegisecurity/runas/applicationContext.xml");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(RunAsTests.class);
|
||||
}
|
||||
|
||||
public void testRunAs() throws Exception {
|
||||
Account account = new Account(45, "someone");
|
||||
BankManager bank = (BankManager) ctx.getBean("bankManager");
|
||||
|
||||
// Try as a user without access to the account
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter",
|
||||
"opal");
|
||||
SecureContext secureContext = new SecureContextImpl();
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
// NB: account number 45 != granted authority for account 77
|
||||
bank.loadAccount(account.getId());
|
||||
fail("Should have thrown an AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
// Now try as user with access to account number 45
|
||||
// Proves ROLE_RUN_AS_SERVER is being allocated
|
||||
token = new UsernamePasswordAuthenticationToken("scott", "wombat");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
bank.loadAccount(account.getId());
|
||||
assertTrue(true);
|
||||
|
||||
// Now try as user with ROLE_SUPERVISOR access to the account
|
||||
// Proves ROLE_RUN_AS_SERVER is being allocated
|
||||
token = new UsernamePasswordAuthenticationToken("marissa", "koala");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
bank.loadAccount(account.getId());
|
||||
assertTrue(true);
|
||||
|
||||
// Now try to call a method that ROLE_RUN_AS_BACKEND not granted for
|
||||
token = new UsernamePasswordAuthenticationToken("marissa", "koala");
|
||||
secureContext.setAuthentication(token);
|
||||
ContextHolder.setContext((Context) secureContext);
|
||||
|
||||
try {
|
||||
bank.saveAccount(account);
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
ContextHolder.setContext(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- =================== SECURITY SYSTEM DEFINITIONS ================== -->
|
||||
|
||||
<!-- RunAsManager -->
|
||||
<bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHENTICATION DEFINITIONS ~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- Data access object which stores authentication information -->
|
||||
<!-- The two invalid entries at the bottom are provided for testing purposes -->
|
||||
<bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl">
|
||||
<property name="userMap">
|
||||
<value>
|
||||
marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR
|
||||
dianne=emu,disabled,ROLE_TELLER
|
||||
scott=wombat,ACCOUNT_45
|
||||
peter=opal,ACCOUNT_77
|
||||
someone=password
|
||||
someoneelse=
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Authentication provider that queries our data access object -->
|
||||
<bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider">
|
||||
<property name="authenticationDao"><ref bean="inMemoryDaoImpl"/></property>
|
||||
<property name="ignorePasswordCase"><value>false</value></property>
|
||||
<property name="ignoreUsernameCase"><value>true</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Authentication provider that accepts as valid our RunAsManagerImpl created tokens -->
|
||||
<bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider">
|
||||
<property name="key"><value>my_run_as_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- The authentication manager that iterates through our authentication providers -->
|
||||
<bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager">
|
||||
<property name="providers">
|
||||
<list>
|
||||
<ref bean="daoAuthenticationProvider"/>
|
||||
<ref bean="runAsAuthenticationProvider"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads BANKSECURITY_CUSTOMER configuaration settings -->
|
||||
<bean id="bankSecurityVoter" class="net.sf.acegisecurity.BankSecurityVoter"/>
|
||||
|
||||
<!-- An affirmative access decision manager -->
|
||||
<bean id="accessDecisionManager" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
<ref bean="bankSecurityVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ===================== SECURITY DEFINITIONS ======================= -->
|
||||
|
||||
<!-- Note we don't specify to grant RUN_AS_SERVER to saveAccount invocations -->
|
||||
<bean id="publicBankManagerSecurity" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource">
|
||||
<value>
|
||||
net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER
|
||||
net.sf.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER
|
||||
net.sf.acegisecurity.context.BankManager.loadAccount=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER
|
||||
net.sf.acegisecurity.context.BankManager.saveAccount=ROLE_TELLER,ROLE_SUPERVISOR
|
||||
net.sf.acegisecurity.context.BankManager.transferFunds=ROLE_SUPERVISOR,RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- We expect all callers of the backend object to hold the role ROLE_RUN_AS_SERVER -->
|
||||
<bean id="backendBankManagerSecurity" class="net.sf.acegisecurity.SecurityInterceptor">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="accessDecisionManager"><ref bean="accessDecisionManager"/></property>
|
||||
<property name="runAsManager"><ref bean="runAsManager"/></property>
|
||||
<property name="methodDefinitionSource">
|
||||
<value>
|
||||
net.sf.acegisecurity.context.BankManager.delete*=ROLE_RUN_AS_SERVER
|
||||
net.sf.acegisecurity.context.BankManager.getBalance=ROLE_RUN_AS_SERVER
|
||||
net.sf.acegisecurity.context.BankManager.loadAccount=ROLE_RUN_AS_SERVER
|
||||
net.sf.acegisecurity.context.BankManager.saveAccount=ROLE_RUN_AS_SERVER
|
||||
net.sf.acegisecurity.context.BankManager.transferFunds=ROLE_RUN_AS_SERVER
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- ======================= BUSINESS DEFINITIONS ===================== -->
|
||||
|
||||
<bean id="bankManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>net.sf.acegisecurity.context.BankManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>publicBankManagerSecurity</value>
|
||||
<value>publicBankManagerTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="publicBankManagerTarget" class="net.sf.acegisecurity.runas.BankManagerPublicFacade">
|
||||
<property name="backend"><ref bean="backendBankManager"/></property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendBankManager" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces"><value>net.sf.acegisecurity.context.BankManager</value></property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<value>backendBankManagerSecurity</value>
|
||||
<value>backendBankManagerTarget</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="backendBankManagerTarget" class="net.sf.acegisecurity.context.BankManagerImpl"/>
|
||||
|
||||
</beans>
|
||||
268
core/src/test/java/org/acegisecurity/vote/VoterManagerTests.java
Normal file
268
core/src/test/java/org/acegisecurity/vote/VoterManagerTests.java
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.vote;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.AccessDecisionManager;
|
||||
import net.sf.acegisecurity.AccessDeniedException;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||
import net.sf.acegisecurity.SecurityConfig;
|
||||
import net.sf.acegisecurity.providers.TestingAuthenticationToken;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Tests voter decision managers.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class VoterManagerTests extends TestCase {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ClassPathXmlApplicationContext ctx;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public VoterManagerTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public VoterManagerTests(String arg0) {
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
ctx = new ClassPathXmlApplicationContext(
|
||||
"/net/sf/acegisecurity/vote/applicationContext.xml");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(VoterManagerTests.class);
|
||||
}
|
||||
|
||||
public void testAffirmative() throws Exception {
|
||||
AccessDecisionManager mgr = (AccessDecisionManager) ctx.getBean(
|
||||
"affirmativeBased");
|
||||
ConfigAttributeDefinition config;
|
||||
TestingAuthenticationToken auth;
|
||||
|
||||
auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl(
|
||||
"ROLE_2"), new GrantedAuthorityImpl("ROLE_MAGIC")});
|
||||
|
||||
// Check if we'd get access if ROLE_2 was all that is acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get access if YYYY was all that is acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("YYYY")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get access if everything was acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant and return
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // not tested
|
||||
config.addConfigAttribute(new SecurityConfig("XXXX")); // grant
|
||||
config.addConfigAttribute(new SecurityConfig("YYYY")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get denied access if ROLE_9 was acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_9")); // deny
|
||||
|
||||
try {
|
||||
mgr.decide(auth, null, config);
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl(
|
||||
"ROLE_2"),});
|
||||
|
||||
// Check if we'd get access if ROLE_1 and 2 was acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant and return
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // not tested
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get granted access even if one returned deny
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant and return
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // not tested
|
||||
config.addConfigAttribute(new SecurityConfig("XXXX")); // deny
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get denied access if all returned deny
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("YYYY")); // deny
|
||||
|
||||
try {
|
||||
mgr.decide(auth, null, config);
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testConsensus() throws Exception {
|
||||
AccessDecisionManager mgr = (AccessDecisionManager) ctx.getBean(
|
||||
"consensusBased");
|
||||
ConfigAttributeDefinition config;
|
||||
TestingAuthenticationToken auth;
|
||||
|
||||
auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl(
|
||||
"ROLE_2"), new GrantedAuthorityImpl("ROLE_MAGIC")});
|
||||
|
||||
// Check if we'd get access if ROLE_2 was all that is acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get access if YYYY was all that is acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("YYYY")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get access if everything was acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant and return
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // not tested
|
||||
config.addConfigAttribute(new SecurityConfig("XXXX")); // grant
|
||||
config.addConfigAttribute(new SecurityConfig("YYYY")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get denied access if ROLE_9 was acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_9")); // deny
|
||||
|
||||
try {
|
||||
mgr.decide(auth, null, config);
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl(
|
||||
"ROLE_2"),});
|
||||
|
||||
// Check if we'd get access if ROLE_1 and 2 was acceptable
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant and return
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // not tested
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get granted access even if one returned deny
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant and return
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // not tested
|
||||
config.addConfigAttribute(new SecurityConfig("XXXX")); // deny
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get denied access if all returned deny
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("XXXX")); // deny
|
||||
|
||||
try {
|
||||
mgr.decide(auth, null, config);
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnanimous() throws Exception {
|
||||
AccessDecisionManager mgr = (AccessDecisionManager) ctx.getBean(
|
||||
"unanimousBased");
|
||||
ConfigAttributeDefinition config;
|
||||
TestingAuthenticationToken auth;
|
||||
|
||||
auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl(
|
||||
"ROLE_2"), new GrantedAuthorityImpl("ROLE_MAGIC")});
|
||||
|
||||
// Check if we'd get access if ROLE_2 was all that is required
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get access if YYYY was all that is required
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("YYYY")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get access if everything was required
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant
|
||||
config.addConfigAttribute(new SecurityConfig("XXXX")); // grant
|
||||
config.addConfigAttribute(new SecurityConfig("YYYY")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get denied access if ROLE_9 was required
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_9")); // deny
|
||||
|
||||
try {
|
||||
mgr.decide(auth, null, config);
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
auth = new TestingAuthenticationToken("test", "test",
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_1"), new GrantedAuthorityImpl(
|
||||
"ROLE_2"),});
|
||||
|
||||
// Check if we'd get access if ROLE_1 and 2 was required
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant
|
||||
mgr.decide(auth, null, config);
|
||||
assertTrue(true);
|
||||
|
||||
// Check if we'd get denied access if all any return deny at all
|
||||
config = new ConfigAttributeDefinition();
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_1")); // grant
|
||||
config.addConfigAttribute(new SecurityConfig("ROLE_2")); // grant
|
||||
config.addConfigAttribute(new SecurityConfig("XXXX")); // deny
|
||||
|
||||
try {
|
||||
mgr.decide(auth, null, config);
|
||||
fail("Should have thrown AccessDeniedException");
|
||||
} catch (AccessDeniedException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
70
core/src/test/java/org/acegisecurity/vote/XVoter.java
Normal file
70
core/src/test/java/org/acegisecurity/vote/XVoter.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.vote;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of an {@link AccessDecisionVoter} for unit testing.
|
||||
*
|
||||
* <p>
|
||||
* If the {@link ConfigAttribute#getAttribute()} has a value of
|
||||
* <code>XXXX</code>, a granted authority that equals <code>ROLE_MAGIC</code>
|
||||
* will cause a grant vote. The voter will abstain if there is no
|
||||
* configuration attribute named <code>XXXX</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* All comparisons are case sensitive.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class XVoter implements AccessDecisionVoter {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ("XXXX".equals(attribute.getAttribute())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int vote(Authentication authentication, MethodInvocation invocation,
|
||||
ConfigAttributeDefinition config) {
|
||||
int result = ACCESS_ABSTAIN;
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attribute)) {
|
||||
result = ACCESS_DENIED;
|
||||
|
||||
for (int i = 0; i < authentication.getAuthorities().length;
|
||||
i++) {
|
||||
if ("ROLE_MAGIC".equals(
|
||||
authentication.getAuthorities()[i].getAuthority())) {
|
||||
return ACCESS_GRANTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
70
core/src/test/java/org/acegisecurity/vote/YVoter.java
Normal file
70
core/src/test/java/org/acegisecurity/vote/YVoter.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
*
|
||||
* Visit http://acegisecurity.sourceforge.net for further details.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.vote;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.ConfigAttribute;
|
||||
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of an {@link AccessDecisionVoter} for unit testing.
|
||||
*
|
||||
* <p>
|
||||
* If the {@link ConfigAttribute#getAttribute()} has a value of
|
||||
* <code>YYYY</code>, a granted authority that equals <code>ROLE_MAGIC</code>
|
||||
* will cause a grant vote. The voter will abstain if there is no
|
||||
* configuration attribute named <code>YYYY</code>.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* All comparisons are case sensitive.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class YVoter implements AccessDecisionVoter {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
if ("YYYY".equals(attribute.getAttribute())) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int vote(Authentication authentication, MethodInvocation invocation,
|
||||
ConfigAttributeDefinition config) {
|
||||
int result = ACCESS_ABSTAIN;
|
||||
Iterator iter = config.getConfigAttributes();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
ConfigAttribute attribute = (ConfigAttribute) iter.next();
|
||||
|
||||
if (this.supports(attribute)) {
|
||||
result = ACCESS_DENIED;
|
||||
|
||||
for (int i = 0; i < authentication.getAuthorities().length;
|
||||
i++) {
|
||||
if ("ROLE_MAGIC".equals(
|
||||
authentication.getAuthorities()[i].getAuthority())) {
|
||||
return ACCESS_GRANTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<!--
|
||||
* The Acegi Security System for Spring is published under the terms
|
||||
* of the Apache Software License.
|
||||
* $Id$
|
||||
-->
|
||||
|
||||
<beans>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~ AUTHORIZATION DEFINITIONS ~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
||||
<!-- An access decision voter that reads ROLE_* configuaration settings -->
|
||||
<bean id="roleVoter" class="net.sf.acegisecurity.vote.RoleVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads XXXX configuaration settings -->
|
||||
<bean id="xVoter" class="net.sf.acegisecurity.vote.XVoter"/>
|
||||
|
||||
<!-- An access decision voter that reads YYYY configuaration settings -->
|
||||
<bean id="yVoter" class="net.sf.acegisecurity.vote.YVoter"/>
|
||||
|
||||
<bean id="unanimousBased" class="net.sf.acegisecurity.vote.UnanimousBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
<ref bean="xVoter"/>
|
||||
<ref bean="yVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="affirmativeBased" class="net.sf.acegisecurity.vote.AffirmativeBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
<ref bean="xVoter"/>
|
||||
<ref bean="yVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="consensusBased" class="net.sf.acegisecurity.vote.ConsensusBased">
|
||||
<property name="allowIfAllAbstainDecisions"><value>false</value></property>
|
||||
<property name="allowIfEqualGrantedDeniedDecisions"><value>true</value></property>
|
||||
<property name="decisionVoters">
|
||||
<list>
|
||||
<ref bean="roleVoter"/>
|
||||
<ref bean="xVoter"/>
|
||||
<ref bean="yVoter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
</beans>
|
||||
Reference in New Issue
Block a user