1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.ui;
17
18 import junit.framework.TestCase;
19
20 import org.acegisecurity.AccountExpiredException;
21 import org.acegisecurity.Authentication;
22 import org.acegisecurity.AuthenticationException;
23 import org.acegisecurity.BadCredentialsException;
24 import org.acegisecurity.GrantedAuthority;
25 import org.acegisecurity.GrantedAuthorityImpl;
26 import org.acegisecurity.MockAuthenticationManager;
27 import org.acegisecurity.context.SecurityContextHolder;
28 import org.acegisecurity.context.SecurityContextImpl;
29 import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
30 import org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices;
31
32 import org.springframework.mock.web.MockFilterConfig;
33 import org.springframework.mock.web.MockHttpServletRequest;
34 import org.springframework.mock.web.MockHttpServletResponse;
35
36 import java.io.IOException;
37
38 import java.util.Properties;
39
40 import javax.servlet.Filter;
41 import javax.servlet.FilterChain;
42 import javax.servlet.FilterConfig;
43 import javax.servlet.ServletException;
44 import javax.servlet.ServletRequest;
45 import javax.servlet.ServletResponse;
46 import javax.servlet.http.HttpServletRequest;
47 import javax.servlet.http.HttpServletResponse;
48
49
50 /***
51 * Tests {@link AbstractProcessingFilter}.
52 *
53 * @author Ben Alex
54 * @version $Id: AbstractProcessingFilterTests.java,v 1.13 2005/11/17 00:56:29 benalex Exp $
55 */
56 public class AbstractProcessingFilterTests extends TestCase {
57
58
59 public AbstractProcessingFilterTests() {
60 super();
61 }
62
63 public AbstractProcessingFilterTests(String arg0) {
64 super(arg0);
65 }
66
67
68
69 public static void main(String[] args) {
70 junit.textui.TestRunner.run(AbstractProcessingFilterTests.class);
71 }
72
73 public void testDefaultProcessesFilterUrlWithPathParameter() {
74 MockHttpServletRequest request = createMockRequest();
75 MockHttpServletResponse response = new MockHttpServletResponse();
76 MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter();
77 filter.setFilterProcessesUrl("/j_acegi_security_check");
78
79 request.setRequestURI(
80 "/mycontext/j_acegi_security_check;jsessionid=I8MIONOSTHOR");
81 assertTrue(filter.requiresAuthentication(request, response));
82 }
83
84 public void testDoFilterWithNonHttpServletRequestDetected()
85 throws Exception {
86 AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
87
88 try {
89 filter.doFilter(null, new MockHttpServletResponse(),
90 new MockFilterChain());
91 fail("Should have thrown ServletException");
92 } catch (ServletException expected) {
93 assertEquals("Can only process HttpServletRequest",
94 expected.getMessage());
95 }
96 }
97
98 public void testDoFilterWithNonHttpServletResponseDetected()
99 throws Exception {
100 AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
101
102 try {
103 filter.doFilter(new MockHttpServletRequest(null, null), null,
104 new MockFilterChain());
105 fail("Should have thrown ServletException");
106 } catch (ServletException expected) {
107 assertEquals("Can only process HttpServletResponse",
108 expected.getMessage());
109 }
110 }
111
112 public void testFailedAuthenticationRedirectsAppropriately()
113 throws Exception {
114
115 MockHttpServletRequest request = createMockRequest();
116
117
118 MockFilterConfig config = new MockFilterConfig(null);
119
120
121 MockFilterChain chain = new MockFilterChain(false);
122 MockHttpServletResponse response = new MockHttpServletResponse();
123
124
125 MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false);
126 filter.setAuthenticationFailureUrl("/myApp/failed.jsp");
127
128
129 executeFilterInContainerSimulator(config, filter, request, response,
130 chain);
131
132 assertEquals("/myApp/failed.jsp", response.getRedirectedUrl());
133 assertNull(SecurityContextHolder.getContext().getAuthentication());
134
135
136 filter = new MockAbstractProcessingFilter(new AccountExpiredException(
137 "You're account is expired"));
138 filter.setAuthenticationFailureUrl("/myApp/failed.jsp");
139
140 Properties exceptionMappings = filter.getExceptionMappings();
141 exceptionMappings.setProperty(AccountExpiredException.class.getName(),
142 "/myApp/accountExpired.jsp");
143 filter.setExceptionMappings(exceptionMappings);
144 response = new MockHttpServletResponse();
145
146
147 executeFilterInContainerSimulator(config, filter, request, response,
148 chain);
149
150 assertEquals("/myApp/accountExpired.jsp", response.getRedirectedUrl());
151 assertNull(SecurityContextHolder.getContext().getAuthentication());
152 }
153
154 public void testFilterProcessesUrlVariationsRespected()
155 throws Exception {
156
157 MockHttpServletRequest request = createMockRequest();
158 request.setServletPath("/j_OTHER_LOCATION");
159 request.setRequestURI("/mycontext/j_OTHER_LOCATION");
160
161
162 MockFilterConfig config = new MockFilterConfig(null);
163
164
165 MockFilterChain chain = new MockFilterChain(false);
166 MockHttpServletResponse response = new MockHttpServletResponse();
167
168
169 MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
170 filter.setFilterProcessesUrl("/j_OTHER_LOCATION");
171 filter.setDefaultTargetUrl("/logged_in.jsp");
172
173
174 executeFilterInContainerSimulator(config, filter, request, response,
175 chain);
176 assertEquals("/logged_in.jsp", response.getRedirectedUrl());
177 assertNotNull(SecurityContextHolder.getContext().getAuthentication());
178 assertEquals("test",
179 SecurityContextHolder.getContext().getAuthentication().getPrincipal()
180 .toString());
181 }
182
183 public void testGettersSetters() {
184 AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
185 assertNotNull(filter.getRememberMeServices());
186 filter.setRememberMeServices(new TokenBasedRememberMeServices());
187 assertEquals(TokenBasedRememberMeServices.class,
188 filter.getRememberMeServices().getClass());
189
190 filter.setAuthenticationFailureUrl("/x");
191 assertEquals("/x", filter.getAuthenticationFailureUrl());
192
193 filter.setAuthenticationManager(new MockAuthenticationManager());
194 assertTrue(filter.getAuthenticationManager() != null);
195
196 filter.setDefaultTargetUrl("/default");
197 assertEquals("/default", filter.getDefaultTargetUrl());
198
199 filter.setFilterProcessesUrl("/p");
200 assertEquals("/p", filter.getFilterProcessesUrl());
201
202 filter.setAuthenticationFailureUrl("/fail");
203 assertEquals("/fail", filter.getAuthenticationFailureUrl());
204 }
205
206 public void testIgnoresAnyServletPathOtherThanFilterProcessesUrl()
207 throws Exception {
208
209 MockHttpServletRequest request = createMockRequest();
210 request.setServletPath("/some.file.html");
211 request.setRequestURI("/mycontext/some.file.html");
212
213
214 MockFilterConfig config = new MockFilterConfig(null);
215
216
217 MockFilterChain chain = new MockFilterChain(true);
218 MockHttpServletResponse response = new MockHttpServletResponse();
219
220
221 MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(false);
222
223
224 executeFilterInContainerSimulator(config, filter, request, response,
225 chain);
226 }
227
228 public void testNormalOperationWithDefaultFilterProcessesUrl()
229 throws Exception {
230
231 MockHttpServletRequest request = createMockRequest();
232
233
234 MockFilterConfig config = new MockFilterConfig(null);
235
236
237 MockFilterChain chain = new MockFilterChain(false);
238 MockHttpServletResponse response = new MockHttpServletResponse();
239
240
241 MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
242 filter.setFilterProcessesUrl("/j_mock_post");
243 filter.setDefaultTargetUrl("/logged_in.jsp");
244 filter.setAuthenticationFailureUrl("/failure.jsp");
245 filter.setAuthenticationManager(new MockAuthenticationManager(true));
246 filter.afterPropertiesSet();
247
248
249 executeFilterInContainerSimulator(config, filter, request, response,
250 chain);
251 assertEquals("/logged_in.jsp", response.getRedirectedUrl());
252 assertNotNull(SecurityContextHolder.getContext().getAuthentication());
253 assertEquals("test",
254 SecurityContextHolder.getContext().getAuthentication().getPrincipal()
255 .toString());
256 }
257
258 public void testStartupDetectsInvalidAuthenticationFailureUrl()
259 throws Exception {
260 AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
261 filter.setAuthenticationManager(new MockAuthenticationManager());
262 filter.setDefaultTargetUrl("/");
263 filter.setFilterProcessesUrl("/j_acegi_security_check");
264
265 try {
266 filter.afterPropertiesSet();
267 fail("Should have thrown IllegalArgumentException");
268 } catch (IllegalArgumentException expected) {
269 assertEquals("authenticationFailureUrl must be specified",
270 expected.getMessage());
271 }
272 }
273
274 public void testStartupDetectsInvalidAuthenticationManager()
275 throws Exception {
276 AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
277 filter.setAuthenticationFailureUrl("/failed.jsp");
278 filter.setDefaultTargetUrl("/");
279 filter.setFilterProcessesUrl("/j_acegi_security_check");
280
281 try {
282 filter.afterPropertiesSet();
283 fail("Should have thrown IllegalArgumentException");
284 } catch (IllegalArgumentException expected) {
285 assertEquals("authenticationManager must be specified",
286 expected.getMessage());
287 }
288 }
289
290 public void testStartupDetectsInvalidDefaultTargetUrl()
291 throws Exception {
292 AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
293 filter.setAuthenticationFailureUrl("/failed.jsp");
294 filter.setAuthenticationManager(new MockAuthenticationManager());
295 filter.setFilterProcessesUrl("/j_acegi_security_check");
296
297 try {
298 filter.afterPropertiesSet();
299 fail("Should have thrown IllegalArgumentException");
300 } catch (IllegalArgumentException expected) {
301 assertEquals("defaultTargetUrl must be specified",
302 expected.getMessage());
303 }
304 }
305
306 public void testStartupDetectsInvalidFilterProcessesUrl()
307 throws Exception {
308 AbstractProcessingFilter filter = new MockAbstractProcessingFilter();
309 filter.setAuthenticationFailureUrl("/failed.jsp");
310 filter.setAuthenticationManager(new MockAuthenticationManager());
311 filter.setDefaultTargetUrl("/");
312 filter.setFilterProcessesUrl(null);
313
314 try {
315 filter.afterPropertiesSet();
316 fail("Should have thrown IllegalArgumentException");
317 } catch (IllegalArgumentException expected) {
318 assertEquals("filterProcessesUrl must be specified",
319 expected.getMessage());
320 }
321 }
322
323 public void testSuccessLoginThenFailureLoginResultsInSessionLosingToken()
324 throws Exception {
325
326 MockHttpServletRequest request = createMockRequest();
327
328
329 MockFilterConfig config = new MockFilterConfig(null);
330
331
332 MockFilterChain chain = new MockFilterChain(false);
333 MockHttpServletResponse response = new MockHttpServletResponse();
334
335
336 MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
337 filter.setFilterProcessesUrl("/j_mock_post");
338 filter.setDefaultTargetUrl("/logged_in.jsp");
339
340
341 executeFilterInContainerSimulator(config, filter, request, response,
342 chain);
343 assertEquals("/logged_in.jsp", response.getRedirectedUrl());
344 assertNotNull(SecurityContextHolder.getContext().getAuthentication());
345 assertEquals("test",
346 SecurityContextHolder.getContext().getAuthentication().getPrincipal()
347 .toString());
348
349
350
351
352 chain = new MockFilterChain(false);
353 response = new MockHttpServletResponse();
354
355
356 filter = new MockAbstractProcessingFilter(false);
357 filter.setFilterProcessesUrl("/j_mock_post");
358 filter.setAuthenticationFailureUrl("/failed.jsp");
359
360
361 executeFilterInContainerSimulator(config, filter, request, response,
362 chain);
363 assertNull(SecurityContextHolder.getContext().getAuthentication());
364 }
365
366 public void testSuccessfulAuthenticationButWithAlwaysUseDefaultTargetUrlCausesRedirectToDefaultTargetUrl()
367 throws Exception {
368
369 MockHttpServletRequest request = createMockRequest();
370 request.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY,
371 "/my-destination");
372
373
374 MockFilterConfig config = new MockFilterConfig(null);
375
376
377 MockFilterChain chain = new MockFilterChain(true);
378 MockHttpServletResponse response = new MockHttpServletResponse();
379
380
381 MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
382 filter.setFilterProcessesUrl("/j_mock_post");
383 filter.setDefaultTargetUrl("/foobar");
384 assertFalse(filter.isAlwaysUseDefaultTargetUrl());
385 filter.setAlwaysUseDefaultTargetUrl(true);
386 assertTrue(filter.isAlwaysUseDefaultTargetUrl());
387
388
389 executeFilterInContainerSimulator(config, filter, request, response,
390 chain);
391 assertEquals("/foobar", response.getRedirectedUrl());
392 assertNotNull(SecurityContextHolder.getContext().getAuthentication());
393 }
394
395 public void testSuccessfulAuthenticationCausesRedirectToSessionSpecifiedUrl()
396 throws Exception {
397
398 MockHttpServletRequest request = createMockRequest();
399 request.getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY,
400 "/my-destination");
401
402
403 MockFilterConfig config = new MockFilterConfig(null);
404
405
406 MockFilterChain chain = new MockFilterChain(true);
407 MockHttpServletResponse response = new MockHttpServletResponse();
408
409
410 MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true);
411 filter.setFilterProcessesUrl("/j_mock_post");
412
413
414 executeFilterInContainerSimulator(config, filter, request, response,
415 chain);
416 assertEquals("/my-destination", response.getRedirectedUrl());
417 assertNotNull(SecurityContextHolder.getContext().getAuthentication());
418 }
419
420 protected void setUp() throws Exception {
421 super.setUp();
422 SecurityContextHolder.setContext(new SecurityContextImpl());
423 }
424
425 protected void tearDown() throws Exception {
426 super.tearDown();
427 SecurityContextHolder.setContext(new SecurityContextImpl());
428 }
429
430 private MockHttpServletRequest createMockRequest() {
431 MockHttpServletRequest request = new MockHttpServletRequest();
432
433 request.setServletPath("/j_mock_post");
434 request.setScheme("http");
435 request.setServerName("www.example.com");
436 request.setRequestURI("/mycontext/j_mock_post");
437
438 return request;
439 }
440
441 private void executeFilterInContainerSimulator(FilterConfig filterConfig,
442 Filter filter, ServletRequest request, ServletResponse response,
443 FilterChain filterChain) throws ServletException, IOException {
444 filter.init(filterConfig);
445 filter.doFilter(request, response, filterChain);
446 filter.destroy();
447 }
448
449
450
451 private class MockAbstractProcessingFilter extends AbstractProcessingFilter {
452 private AuthenticationException exceptionToThrow;
453 private boolean grantAccess;
454
455 public MockAbstractProcessingFilter(boolean grantAccess) {
456 this.grantAccess = grantAccess;
457 this.exceptionToThrow = new BadCredentialsException(
458 "Mock requested to do so");
459 }
460
461 public MockAbstractProcessingFilter(
462 AuthenticationException exceptionToThrow) {
463 this.grantAccess = false;
464 this.exceptionToThrow = exceptionToThrow;
465 }
466
467 private MockAbstractProcessingFilter() {
468 super();
469 }
470
471 public String getDefaultFilterProcessesUrl() {
472 return "/j_mock_post";
473 }
474
475 public Authentication attemptAuthentication(HttpServletRequest request)
476 throws AuthenticationException {
477 if (grantAccess) {
478 return new UsernamePasswordAuthenticationToken("test", "test",
479 new GrantedAuthority[] {new GrantedAuthorityImpl("TEST")});
480 } else {
481 throw exceptionToThrow;
482 }
483 }
484
485 public void init(FilterConfig arg0) throws ServletException {}
486
487 public boolean requiresAuthentication(HttpServletRequest request,
488 HttpServletResponse response) {
489 return super.requiresAuthentication(request, response);
490 }
491 }
492
493 private class MockFilterChain implements FilterChain {
494 private boolean expectToProceed;
495
496 public MockFilterChain(boolean expectToProceed) {
497 this.expectToProceed = expectToProceed;
498 }
499
500 private MockFilterChain() {
501 super();
502 }
503
504 public void doFilter(ServletRequest request, ServletResponse response)
505 throws IOException, ServletException {
506 if (expectToProceed) {
507 assertTrue(true);
508 } else {
509 fail("Did not expect filter chain to proceed");
510 }
511 }
512 }
513 }