001: /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.acegisecurity.ui;
017:
018: import junit.framework.TestCase;
019:
020: import org.acegisecurity.AccessDeniedException;
021: import org.acegisecurity.BadCredentialsException;
022: import org.acegisecurity.GrantedAuthority;
023: import org.acegisecurity.GrantedAuthorityImpl;
024: import org.acegisecurity.MockAuthenticationEntryPoint;
025: import org.acegisecurity.MockPortResolver;
026:
027: import org.acegisecurity.context.SecurityContextHolder;
028:
029: import org.acegisecurity.providers.anonymous.AnonymousAuthenticationToken;
030:
031: import org.springframework.mock.web.MockHttpServletRequest;
032: import org.springframework.mock.web.MockHttpServletResponse;
033:
034: import java.io.IOException;
035:
036: import javax.servlet.FilterChain;
037: import javax.servlet.ServletException;
038: import javax.servlet.ServletRequest;
039: import javax.servlet.ServletResponse;
040:
041: /**
042: * Tests {@link ExceptionTranslationFilter}.
043: *
044: * @author Ben Alex
045: * @version $Id: ExceptionTranslationFilterTests.java 1496 2006-05-23 13:38:33Z
046: * benalex $
047: */
048: public class ExceptionTranslationFilterTests extends TestCase {
049: // ~ Constructors
050: // ===================================================================================================
051:
052: public ExceptionTranslationFilterTests() {
053: super ();
054: }
055:
056: public ExceptionTranslationFilterTests(String arg0) {
057: super (arg0);
058: }
059:
060: // ~ Methods
061: // ========================================================================================================
062:
063: public static void main(String[] args) {
064: junit.textui.TestRunner
065: .run(ExceptionTranslationFilterTests.class);
066: }
067:
068: public final void setUp() throws Exception {
069: super .setUp();
070: }
071:
072: protected void tearDown() throws Exception {
073: super .tearDown();
074: SecurityContextHolder.clearContext();
075: }
076:
077: public void testAccessDeniedWhenAnonymous() throws Exception {
078: // Setup our HTTP request
079: MockHttpServletRequest request = new MockHttpServletRequest();
080: request.setServletPath("/secure/page.html");
081: request.setServerPort(80);
082: request.setScheme("http");
083: request.setServerName("www.example.com");
084: request.setContextPath("/mycontext");
085: request.setRequestURI("/mycontext/secure/page.html");
086:
087: // Setup the FilterChain to thrown an access denied exception
088: MockFilterChain chain = new MockFilterChain(true, false, false,
089: false);
090:
091: // Setup SecurityContextHolder, as filter needs to check if user is
092: // anonymous
093: SecurityContextHolder
094: .getContext()
095: .setAuthentication(
096: new AnonymousAuthenticationToken(
097: "ignored",
098: "ignored",
099: new GrantedAuthority[] { new GrantedAuthorityImpl(
100: "IGNORED") }));
101:
102: // Test
103: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
104: filter
105: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
106: "/login.jsp"));
107:
108: MockHttpServletResponse response = new MockHttpServletResponse();
109: filter.doFilter(request, response, chain);
110: assertEquals("/mycontext/login.jsp", response
111: .getRedirectedUrl());
112: assertEquals(
113: "http://www.example.com/mycontext/secure/page.html",
114: AbstractProcessingFilter.obtainFullRequestUrl(request));
115: }
116:
117: public void testAccessDeniedWhenNonAnonymous() throws Exception {
118: // Setup our HTTP request
119: MockHttpServletRequest request = new MockHttpServletRequest();
120: request.setServletPath("/secure/page.html");
121:
122: // Setup the FilterChain to thrown an access denied exception
123: MockFilterChain chain = new MockFilterChain(true, false, false,
124: false);
125:
126: // Setup SecurityContextHolder, as filter needs to check if user is
127: // anonymous
128: SecurityContextHolder.getContext().setAuthentication(null);
129:
130: // Setup a new AccessDeniedHandlerImpl that will do a "forward"
131: AccessDeniedHandlerImpl adh = new AccessDeniedHandlerImpl();
132: adh.setErrorPage("/error.jsp");
133:
134: // Test
135: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
136: filter
137: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
138: "/login.jsp"));
139: filter.setAccessDeniedHandler(adh);
140:
141: MockHttpServletResponse response = new MockHttpServletResponse();
142: filter.doFilter(request, response, chain);
143: assertEquals(403, response.getStatus());
144: assertEquals(
145: AccessDeniedException.class,
146: request
147: .getAttribute(
148: AccessDeniedHandlerImpl.ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY)
149: .getClass());
150: }
151:
152: public void testDoFilterWithNonHttpServletRequestDetected()
153: throws Exception {
154: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
155:
156: try {
157: filter.doFilter(null, new MockHttpServletResponse(),
158: new MockFilterChain(false, false, false, false));
159: fail("Should have thrown ServletException");
160: } catch (ServletException expected) {
161: assertEquals("HttpServletRequest required", expected
162: .getMessage());
163: }
164: }
165:
166: public void testDoFilterWithNonHttpServletResponseDetected()
167: throws Exception {
168: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
169:
170: try {
171: filter.doFilter(new MockHttpServletRequest(null, null),
172: null, new MockFilterChain(false, false, false,
173: false));
174: fail("Should have thrown ServletException");
175: } catch (ServletException expected) {
176: assertEquals("HttpServletResponse required", expected
177: .getMessage());
178: }
179: }
180:
181: public void testGettersSetters() {
182: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
183:
184: filter
185: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
186: "/login.jsp"));
187: assertTrue(filter.getAuthenticationEntryPoint() != null);
188:
189: filter.setPortResolver(new MockPortResolver(80, 443));
190: assertTrue(filter.getPortResolver() != null);
191: }
192:
193: public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException()
194: throws Exception {
195: // Setup our HTTP request
196: MockHttpServletRequest request = new MockHttpServletRequest();
197: request.setServletPath("/secure/page.html");
198: request.setServerPort(80);
199: request.setScheme("http");
200: request.setServerName("www.example.com");
201: request.setContextPath("/mycontext");
202: request.setRequestURI("/mycontext/secure/page.html");
203:
204: // Setup the FilterChain to thrown an authentication failure exception
205: MockFilterChain chain = new MockFilterChain(false, true, false,
206: false);
207:
208: // Test
209: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
210: filter
211: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
212: "/login.jsp"));
213: filter.setPortResolver(new MockPortResolver(80, 443));
214: /*
215: * Disabled the call to afterPropertiesSet as it requires
216: * applicationContext to be injected before it is invoked. We do not
217: * have this filter configured in IOC for this test hence no
218: * ApplicationContext
219: */
220: // filter.afterPropertiesSet();
221: MockHttpServletResponse response = new MockHttpServletResponse();
222: filter.doFilter(request, response, chain);
223: assertEquals("/mycontext/login.jsp", response
224: .getRedirectedUrl());
225: assertEquals(
226: "http://www.example.com/mycontext/secure/page.html",
227: AbstractProcessingFilter.obtainFullRequestUrl(request));
228: }
229:
230: public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWithExoticPortWhenAuthenticationException()
231: throws Exception {
232: // Setup our HTTP request
233: MockHttpServletRequest request = new MockHttpServletRequest();
234: request.setServletPath("/secure/page.html");
235: request.setServerPort(8080);
236: request.setScheme("http");
237: request.setServerName("www.example.com");
238: request.setContextPath("/mycontext");
239: request.setRequestURI("/mycontext/secure/page.html");
240:
241: // Setup the FilterChain to thrown an authentication failure exception
242: MockFilterChain chain = new MockFilterChain(false, true, false,
243: false);
244:
245: // Test
246: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
247: filter
248: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
249: "/login.jsp"));
250: filter.setPortResolver(new MockPortResolver(8080, 8443));
251: /*
252: * Disabled the call to afterPropertiesSet as it requires
253: * applicationContext to be injected before it is invoked. We do not
254: * have this filter configured in IOC for this test hence no
255: * ApplicationContext
256: */
257: // filter.afterPropertiesSet();
258: MockHttpServletResponse response = new MockHttpServletResponse();
259: filter.doFilter(request, response, chain);
260: assertEquals("/mycontext/login.jsp", response
261: .getRedirectedUrl());
262: assertEquals(
263: "http://www.example.com:8080/mycontext/secure/page.html",
264: AbstractProcessingFilter.obtainFullRequestUrl(request));
265: }
266:
267: public void testStartupDetectsMissingAuthenticationEntryPoint()
268: throws Exception {
269: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
270:
271: try {
272: filter.afterPropertiesSet();
273: fail("Should have thrown IllegalArgumentException");
274: } catch (IllegalArgumentException expected) {
275: assertEquals("authenticationEntryPoint must be specified",
276: expected.getMessage());
277: }
278: }
279:
280: public void testStartupDetectsMissingPortResolver()
281: throws Exception {
282: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
283: filter
284: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
285: "/login.jsp"));
286: filter.setPortResolver(null);
287:
288: try {
289: filter.afterPropertiesSet();
290: fail("Should have thrown IllegalArgumentException");
291: } catch (IllegalArgumentException expected) {
292: assertEquals("portResolver must be specified", expected
293: .getMessage());
294: }
295: }
296:
297: public void testSuccessfulAccessGrant() throws Exception {
298: // Setup our HTTP request
299: MockHttpServletRequest request = new MockHttpServletRequest();
300: request.setServletPath("/secure/page.html");
301:
302: // Setup the FilterChain to thrown no exceptions
303: MockFilterChain chain = new MockFilterChain(false, false,
304: false, false);
305:
306: // Test
307: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
308: filter
309: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
310: "/login.jsp"));
311:
312: MockHttpServletResponse response = new MockHttpServletResponse();
313: filter.doFilter(request, response, chain);
314: }
315:
316: public void testSuccessfulStartupAndShutdownDown() throws Exception {
317: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
318:
319: filter.init(null);
320: filter.destroy();
321: assertTrue(true);
322: }
323:
324: public void testThrowIOException() throws Exception {
325: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
326:
327: filter
328: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
329: ""));
330: /*
331: * Disabled the call to afterPropertiesSet as it requires
332: * applicationContext to be injected before it is invoked. We do not
333: * have this filter configured in IOC for this test hence no
334: * ApplicationContext
335: */
336: // filter.afterPropertiesSet();
337: try {
338: filter.doFilter(new MockHttpServletRequest(),
339: new MockHttpServletResponse(), new MockFilterChain(
340: false, false, false, true));
341: fail("Should have thrown IOException");
342: } catch (IOException e) {
343: assertNull(
344: "The IOException thrown should not have been wrapped",
345: e.getCause());
346: }
347: }
348:
349: public void testThrowServletException() throws Exception {
350: ExceptionTranslationFilter filter = new ExceptionTranslationFilter();
351:
352: filter
353: .setAuthenticationEntryPoint(new MockAuthenticationEntryPoint(
354: ""));
355: /*
356: * Disabled the call to afterPropertiesSet as it requires
357: * applicationContext to be injected before it is invoked. We do not
358: * have this filter configured in IOC for this test hence no
359: * ApplicationContext
360: */
361: // filter.afterPropertiesSet();
362: try {
363: filter.doFilter(new MockHttpServletRequest(),
364: new MockHttpServletResponse(), new MockFilterChain(
365: false, false, true, false));
366: fail("Should have thrown ServletException");
367: } catch (ServletException e) {
368: assertNull(
369: "The ServletException thrown should not have been wrapped",
370: e.getCause());
371: }
372: }
373:
374: // ~ Inner Classes
375: // ==================================================================================================
376:
377: private class MockFilterChain implements FilterChain {
378: private boolean throwAccessDenied;
379:
380: private boolean throwAuthenticationFailure;
381:
382: private boolean throwIOException;
383:
384: private boolean throwServletException;
385:
386: public MockFilterChain(boolean throwAccessDenied,
387: boolean throwAuthenticationFailure,
388: boolean throwServletException, boolean throwIOException) {
389: this .throwAccessDenied = throwAccessDenied;
390: this .throwAuthenticationFailure = throwAuthenticationFailure;
391: this .throwServletException = throwServletException;
392: this .throwIOException = throwIOException;
393: }
394:
395: public void doFilter(ServletRequest request,
396: ServletResponse response) throws IOException,
397: ServletException {
398: if (throwAccessDenied) {
399: throw new AccessDeniedException("As requested");
400: }
401:
402: if (throwAuthenticationFailure) {
403: throw new BadCredentialsException("As requested");
404: }
405:
406: if (throwServletException) {
407: throw new ServletException("As requested");
408: }
409:
410: if (throwIOException) {
411: throw new IOException("As requested");
412: }
413: }
414: }
415: }
|