View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2005 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  package ch.elca.el4j.tests.services.security;
18  
19  import java.util.ArrayList;
20  import java.util.Collection;
21  
22  import org.junit.After;
23  import org.junit.Before;
24  import org.junit.Test;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  import org.springframework.context.ConfigurableApplicationContext;
28  import org.springframework.security.access.AccessDeniedException;
29  import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
30  import org.springframework.security.authentication.BadCredentialsException;
31  import org.springframework.security.core.Authentication;
32  import org.springframework.security.core.GrantedAuthority;
33  import org.springframework.security.core.authority.GrantedAuthorityImpl;
34  
35  import static org.junit.Assert.assertEquals;
36  import static org.junit.Assert.fail;
37  
38  import ch.elca.el4j.core.context.ModuleApplicationContext;
39  import ch.elca.el4j.services.security.authentication.AuthenticationService;
40  import ch.elca.el4j.services.security.encryption.RSACipher;
41  import ch.elca.el4j.tests.services.security.provider.ExtendedTestingAuthenticationProvider;
42  import ch.elca.el4j.tests.services.security.sample.SampleService;
43  import ch.elca.el4j.tests.services.security.server.AuthorizationServer;
44  
45  // Checkstyle: EmptyBlock off
46  // Checkstyle: MagicNumber off
47  
48  /**
49   * Tests various logins and authorization in a distributed environment. <br>
50   * <ul>
51   * <li>first runs AuthorizationServer (server part, no server case)</li>
52   * <li>then runs AuthorizationTestDistributed as unit server</li>
53   * </ul>
54   *
55   * @svnLink $Revision: 4091 $;$Date: 2010-01-15 12:21:07 +0100 (Fr, 15. Jan 2010) $;$Author: jonasha $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/security/src/test/java/ch/elca/el4j/tests/services/security/AuthorizationDistributedTest.java $
56   *
57   * @author Raphael Boog (RBO)
58   */
59  public class AuthorizationDistributedTest {
60  	/**
61  	 * Private logger.
62  	 */
63  	private static Logger s_logger = LoggerFactory
64  		.getLogger(AuthorizationDistributedTest.class);
65  	
66  	/**
67  	 * Method access role.
68  	 */
69  	private static final String METHOD_ACCESS_ROLE = "ROLE_PERMISSION_ADDONE";
70  
71  	/**
72  	 * Server config locations.
73  	 */
74  	private String[] m_configLocationsServer = new String[] {
75  		"classpath*:mandatory/*.xml",
76  		"classpath:optional/security-attributes.xml",
77  		"classpath:scenarios/services/sampleService.xml",
78  		"classpath:scenarios/server/applicationContextTest.xml",
79  		"classpath:scenarios/securityscope/distributed-security-scope-server.xml",
80  		"classpath:optional/rmi-protocol-config.xml",
81  		"classpath:scenarios/services/serviceExporter.xml"};
82  
83  	/**
84  	 * Client config locations.
85  	 */
86  	private String[] m_configLocationsClient = new String[] {
87  		"classpath*:mandatory/*.xml",
88  		"classpath:scenarios/services/serviceProxy.xml",
89  		"classpath:scenarios/securityscope/distributed-security-scope-client.xml",
90  		"classpath:optional/rmi-protocol-config.xml"};
91  
92  	/**
93  	 * Application context.
94  	 */
95  	private ConfigurableApplicationContext m_ac;
96  
97  	
98  	/**
99  	 * {@inheritDoc}
100 	 */
101 	@Before
102 	public void setUp() {
103 		s_logger.debug("Starting server.");
104 		AuthorizationServer.main(m_configLocationsServer);
105 		s_logger.debug("Server started. Loading client context.");
106 
107 		m_ac = new ModuleApplicationContext(m_configLocationsClient, false);
108 		s_logger.debug("Client context loaded.");
109 	}
110 	
111 	/**
112 	 * {@inheritDoc}
113 	 */
114 	@After
115 	public void tearDown() {
116 		AuthorizationServer.close();
117 		m_ac.close();
118 	}
119 	
120 	/**
121 	 * Test tries to execute the target method without authentication.
122 	 *
123 	 * @throws Exception
124 	 *             If something.
125 	 */
126 	@Test
127 	public void testMethodCallWithoutLogin() throws Exception {
128 		try {
129 			getSampleService().addOne(1234);
130 			fail("User should not be able to execute this method "
131 				+ "without login");
132 		} catch (AuthenticationCredentialsNotFoundException e) {
133 			// o.k.
134 		}
135 	}
136 
137 	/**
138 	 * Test does a correct authorization. Then it does a remote call to the
139 	 * sample service.
140 	 *
141 	 * @throws Exception If something.
142 	 */
143 	@Test
144 	public void testCorrectAuthorization() throws Exception {
145 		createSecureContext("server", "server", METHOD_ACCESS_ROLE);
146 		int result = getSampleService().addOne(1234);
147 		assertEquals(result, 1235);
148 	}
149 	
150 	/**
151 	 * Test does a correct authorization. Then it does a remote call to the
152 	 * sample service. Afterwards, it logs out, tries to call the method again
153 	 * and fails.
154 	 *
155 	 * @throws Exception If something.
156 	 */
157 	@Test
158 	public void testCorrectAuthorizationAfterLogoutNoAccess() throws Exception {
159 		createSecureContext("server", "server", METHOD_ACCESS_ROLE);
160 		int result = getSampleService().addOne(1234);
161 		assertEquals(result, 1235);
162 
163 		destroySecureContext("server", "server");
164 
165 		try {
166 			getSampleService().addOne(1234);
167 			fail("An AccessDeniedException should have been thrown.");
168 		} catch (AccessDeniedException e) {
169 			// ok.
170 		}
171 	}
172 
173 	/**
174 	 * Test does a correct login with the wrong role. Then it does a remote call
175 	 * to the sample service. Since the required permission is not given, the
176 	 * call should throw an exception.
177 	 *
178 	 * @throws Exception If something.
179 	 */
180 	@Test
181 	public void testFailedAuthorization() throws Exception {
182 		createSecureContext("test4", "test4", "ROLE_NO_PERMISSION");
183 
184 		try {
185 			getSampleService().addOne(1234);
186 			fail("An AccessDeniedException should have been thrown.");
187 		} catch (AccessDeniedException e) {
188 			// ok.
189 		}
190 	}
191 
192 	/**
193 	 * Test tries to authenticate with a wrong username/password combination. An
194 	 * exception should be thrown.
195 	 *
196 	 * @throws Exception If something.
197 	 */
198 	@Test
199 	public void testFailedAuthentication() throws Exception {
200 		try {
201 			createSecureContext("Different username", "than password", "ROLE_TELLER");
202 			fail("User should not be able to authenticate since the password "
203 					+ "is not valid.");
204 		} catch (BadCredentialsException e) {
205 			// o.k.
206 		}
207 	}
208 
209 	/**
210 	 * @return Returns the authentication service.
211 	 */
212 	private AuthenticationService getAuthenticationService() {
213 		return (AuthenticationService) m_ac.getBean("authenticationService");
214 	}
215 
216 	/**
217 	 * Returns the authentication provider of the authorization server.
218 	 * 
219 	 * @return The ExtendedTestingAuthenticationProvider of the server.
220 	 */
221 	private ExtendedTestingAuthenticationProvider getAuthenticationProvider() {
222 		
223 		return (ExtendedTestingAuthenticationProvider)
224 			AuthorizationServer.getApplicationContext().
225 			getBean("extendedTestingAuthenticationProvider");
226 	}
227 	
228 	/**
229 	 * @return Returns the sample service.
230 	 */
231 	private SampleService getSampleService() {
232 		return (SampleService) m_ac.getBean("sampleService");
233 	}
234 
235 	/**
236 	 * Create a secure context with a TestingAuthenticationToken, i.e. a token
237 	 * where the user can define which roles it possesses.
238 	 *
239 	 * @param principal
240 	 *            The username
241 	 * @param credential
242 	 *            The password
243 	 * @param role
244 	 *            The role
245 	 */
246 	private void createSecureContext(String principal, String credential,
247 		String role) {
248 		
249 		String publicKey = getAuthenticationProvider().getPublicKey();
250 		RSACipher rsaCipher = new RSACipher(publicKey);
251 		String encryptedCredential = rsaCipher.encrypt(credential);
252 		
253 		Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
254 		authorities.add(new GrantedAuthorityImpl("ROLE_TELLER"));
255 		authorities.add(new GrantedAuthorityImpl(role));
256 		
257 		Authentication auth = new TestingAuthenticationToken(principal,
258 			encryptedCredential, authorities);
259 
260 		getAuthenticationService().authenticate(auth);
261 	}
262 
263 	/**
264 	 * Delete the secure context, i.e. logging out the user.
265 	 *
266 	 * @param principal Is the principal.
267 	 * @param credential is the credential.
268 	 */
269 	private void destroySecureContext(String principal, String credential) {
270 		
271 		String publicKey = getAuthenticationProvider().getPublicKey();
272 		RSACipher rsaCipher = new RSACipher(publicKey);
273 		String encryptedCredential = rsaCipher.encrypt(credential);
274 		
275 		Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
276 		
277 		Authentication auth = new TestingAuthenticationToken(principal,
278 			encryptedCredential, authorities);
279 		
280 		getAuthenticationService().authenticate(auth);
281 	}
282 }
283 //Checkstyle: EmptyBlock on
284 //Checkstyle: MagicNumber on