001 /** 002 * 003 */ 004 package org.springframework.richclient.security.support; 005 006 import java.util.ArrayList; 007 008 import junit.framework.TestCase; 009 010 import org.springframework.security.AccessDecisionManager; 011 import org.springframework.security.AccessDeniedException; 012 import org.springframework.security.Authentication; 013 import org.springframework.security.ConfigAttribute; 014 import org.springframework.security.ConfigAttributeDefinition; 015 import org.springframework.security.providers.TestingAuthenticationToken; 016 017 /** 018 * @author Larry Streepy 019 * 020 */ 021 public class SecurityControllerTests extends TestCase { 022 023 private TestAbstractSecurityController controller; 024 private TestAccessDecisionManager accessDecisionManager; 025 026 /* 027 * @see TestCase#setUp() 028 */ 029 protected void setUp() throws Exception { 030 super.setUp(); 031 controller = new TestAbstractSecurityController(); 032 accessDecisionManager = new TestAccessDecisionManager(); 033 controller.setAccessDecisionManager(accessDecisionManager); 034 } 035 036 /** 037 * Test that setting the authentication token updates all controlled objects. 038 */ 039 public void testSetAuthenticationToken() { 040 041 // Validate that the controller updates the controlled objects whenever the 042 // Authentication token is updated 043 TestAuthorizable a1 = new TestAuthorizable( true ); 044 TestAuthorizable a2 = new TestAuthorizable( true ); 045 controller.addControlledObject( a1 ); 046 controller.addControlledObject( a2 ); 047 assertFalse( "Object should not be authorized", a1.isAuthorized() ); 048 assertFalse( "Object should not be authorized", a2.isAuthorized() ); 049 050 a1.resetAuthCount(); 051 a2.resetAuthCount(); 052 053 // Set the decision manager to authorize 054 accessDecisionManager.setDecisionValue( true ); 055 056 // Now install a token, a should be updated 057 controller.setAuthenticationToken( new TestingAuthenticationToken( "USER2", "FOO") ); 058 assertTrue( "Object should be authorized", a1.isAuthorized() ); 059 assertEquals( "Object should be updated", a1.getAuthCount(), 1 ); 060 assertTrue( "Object should be authorized", a2.isAuthorized() ); 061 assertEquals( "Object should be updated", a2.getAuthCount(), 1 ); 062 063 controller.setAuthenticationToken( null ); 064 assertFalse( "Object should not be authorized", a1.isAuthorized() ); 065 assertEquals( "Object should be updated", a1.getAuthCount(), 2 ); 066 assertFalse( "Object should not be authorized", a2.isAuthorized() ); 067 assertEquals( "Object should be updated", a2.getAuthCount(), 2 ); 068 069 // Set the decision manager to NOT authorize 070 accessDecisionManager.setDecisionValue( false ); 071 072 // Now install a token, a should be updated 073 controller.setAuthenticationToken( new TestingAuthenticationToken( "USER2", "FOO") ); 074 assertFalse( "Object should not be authorized", a1.isAuthorized() ); 075 assertEquals( "Object should be updated", a1.getAuthCount(), 3 ); 076 assertFalse( "Object should not be authorized", a2.isAuthorized() ); 077 assertEquals( "Object should be updated", a2.getAuthCount(), 3 ); 078 } 079 080 public void testSetControlledObjects() { 081 082 TestAuthorizable a1 = new TestAuthorizable( true ); 083 TestAuthorizable a2 = new TestAuthorizable( true ); 084 ArrayList goodList = new ArrayList(); 085 goodList.add( a1 ); 086 goodList.add( a2 ); 087 088 ArrayList badList = new ArrayList(); 089 badList.add( new Object() ); 090 091 try { 092 controller.setControlledObjects( badList ); 093 fail( "Should reject objects that aren't Authorizable" ); 094 } catch( IllegalArgumentException e ) { 095 // expected 096 } 097 098 controller.setControlledObjects( goodList ); 099 assertFalse( "Object should not be authorized", a1.isAuthorized() ); 100 assertTrue( "Object should be updated", a1.getAuthCount() == 1 ); 101 assertFalse( "Object should not be authorized", a2.isAuthorized() ); 102 assertTrue( "Object should be updated", a2.getAuthCount() == 1 ); 103 } 104 105 /** 106 * Test that added objects are initially configured. 107 */ 108 public void testAddControlledObject() { 109 110 // Install an authentication token 111 controller.setAuthenticationToken( new TestingAuthenticationToken( "USER2", "FOO") ); 112 113 // Set the decision manager to authorize 114 accessDecisionManager.setDecisionValue( true ); 115 116 TestAuthorizable a1 = new TestAuthorizable( false ); 117 controller.addControlledObject( a1 ); 118 assertTrue( "Object should be authorized", a1.isAuthorized() ); 119 assertTrue( "Object should be updated", a1.getAuthCount() == 1 ); 120 121 // Set the decision manager to NOT authorize 122 accessDecisionManager.setDecisionValue( false ); 123 124 TestAuthorizable a2 = new TestAuthorizable( true ); 125 controller.addControlledObject( a2 ); 126 assertFalse( "Object should not be authorized", a2.isAuthorized() ); 127 assertTrue( "Object should be updated", a2.getAuthCount() == 1 ); 128 } 129 130 /** 131 * Test that once removed an object is no longer updated. 132 */ 133 public void testRemoveControlledObject() { 134 TestAuthorizable a = new TestAuthorizable( true ); 135 controller.addControlledObject( a ); 136 assertFalse( "Object should not be authorized", a.isAuthorized() ); 137 assertTrue( "Object should be updated", a.getAuthCount() == 1 ); 138 139 controller.removeControlledObject( a ); 140 a.resetAuthCount(); 141 142 // Set the decision manager to authorize 143 accessDecisionManager.setDecisionValue( true ); 144 controller.setAuthenticationToken( new TestingAuthenticationToken( "USER2", "FOO" ) ); 145 146 assertFalse( "Object should not be authorized", a.isAuthorized() ); 147 assertTrue( "Object should not be updated", a.getAuthCount() == 0 ); 148 } 149 150 /** 151 * Concrete implementation under test. 152 */ 153 public class TestAbstractSecurityController extends AbstractSecurityController { 154 155 public TestAbstractSecurityController() { 156 } 157 158 protected Object getSecuredObject() { 159 return null; 160 } 161 162 protected ConfigAttributeDefinition getConfigAttributeDefinition(Object securedObject) { 163 return null; 164 } 165 } 166 167 /** 168 * Controllable AccessDecisionManager 169 */ 170 public class TestAccessDecisionManager implements AccessDecisionManager { 171 172 private boolean decisionValue; 173 174 public void setDecisionValue(boolean decisionValue) { 175 this.decisionValue = decisionValue; 176 } 177 178 public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) 179 throws AccessDeniedException { 180 if( !decisionValue) { 181 throw new AccessDeniedException( "access denied" ); 182 } 183 } 184 185 public boolean supports(ConfigAttribute attribute) { 186 return false; 187 } 188 189 public boolean supports(Class clazz) { 190 return false; 191 } 192 } 193 }