1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.ui.basicauth;
17
18 import org.acegisecurity.MockAuthenticationEntryPoint;
19 import org.acegisecurity.MockAuthenticationManager;
20 import org.acegisecurity.MockFilterChain;
21 import org.acegisecurity.MockFilterConfig;
22
23 import org.acegisecurity.context.SecurityContextHolder;
24
25 import org.acegisecurity.providers.ProviderManager;
26 import org.acegisecurity.providers.dao.DaoAuthenticationProvider;
27
28 import org.acegisecurity.userdetails.UserDetails;
29 import org.acegisecurity.userdetails.memory.InMemoryDaoImpl;
30 import org.acegisecurity.userdetails.memory.UserMap;
31 import org.acegisecurity.userdetails.memory.UserMapEditor;
32
33 import org.apache.commons.codec.binary.Base64;
34
35 import org.jmock.Mock;
36 import org.jmock.MockObjectTestCase;
37
38 import org.springframework.context.ApplicationEvent;
39 import org.springframework.context.ApplicationEventPublisher;
40
41 import org.springframework.mock.web.MockHttpServletRequest;
42 import org.springframework.mock.web.MockHttpServletResponse;
43 import org.springframework.mock.web.MockHttpSession;
44
45 import java.io.IOException;
46
47 import java.util.Arrays;
48
49 import javax.servlet.Filter;
50 import javax.servlet.FilterChain;
51 import javax.servlet.ServletException;
52 import javax.servlet.ServletRequest;
53
54
55
56
57
58
59
60
61 public class BasicProcessingFilterTests extends MockObjectTestCase {
62
63
64 private BasicProcessingFilter filter;
65
66
67
68 public BasicProcessingFilterTests() {
69 super();
70 }
71
72 public BasicProcessingFilterTests(String arg0) {
73 super(arg0);
74 }
75
76
77
78 private MockHttpServletResponse executeFilterInContainerSimulator(Filter filter, ServletRequest request,
79 boolean expectChainToProceed) throws ServletException, IOException {
80 filter.init(new MockFilterConfig());
81
82 MockHttpServletResponse response = new MockHttpServletResponse();
83 Mock mockChain = mock(FilterChain.class);
84 FilterChain chain = (FilterChain) mockChain.proxy();
85
86 mockChain.expects(expectChainToProceed ? once() : never()).method("doFilter");
87
88 filter.doFilter(request, response, chain);
89 filter.destroy();
90
91 return response;
92 }
93
94 public static void main(String[] args) {
95 junit.textui.TestRunner.run(BasicProcessingFilterTests.class);
96 }
97
98 protected void setUp() throws Exception {
99 super.setUp();
100 SecurityContextHolder.clearContext();
101
102
103 InMemoryDaoImpl dao = new InMemoryDaoImpl();
104 UserMapEditor editor = new UserMapEditor();
105 editor.setAsText("marissa=koala,ROLE_ONE,ROLE_TWO,enabled\r\n");
106 dao.setUserMap((UserMap) editor.getValue());
107
108 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
109 provider.setUserDetailsService(dao);
110
111 ProviderManager manager = new ProviderManager();
112 manager.setProviders(Arrays.asList(new Object[] {provider}));
113 manager.setApplicationEventPublisher(new MockApplicationEventPublisher());
114 manager.afterPropertiesSet();
115
116 filter = new BasicProcessingFilter();
117 filter.setAuthenticationManager(manager);
118 filter.setAuthenticationEntryPoint(new BasicProcessingFilterEntryPoint());
119 }
120
121 protected void tearDown() throws Exception {
122 super.tearDown();
123 SecurityContextHolder.clearContext();
124 }
125
126 public void testDoFilterWithNonHttpServletRequestDetected()
127 throws Exception {
128 BasicProcessingFilter filter = new BasicProcessingFilter();
129
130 try {
131 filter.doFilter(null, new MockHttpServletResponse(), new MockFilterChain());
132 fail("Should have thrown ServletException");
133 } catch (ServletException expected) {
134 assertEquals("Can only process HttpServletRequest", expected.getMessage());
135 }
136 }
137
138 public void testDoFilterWithNonHttpServletResponseDetected()
139 throws Exception {
140 BasicProcessingFilter filter = new BasicProcessingFilter();
141
142 try {
143 filter.doFilter(new MockHttpServletRequest(null, null), null, new MockFilterChain());
144 fail("Should have thrown ServletException");
145 } catch (ServletException expected) {
146 assertEquals("Can only process HttpServletResponse", expected.getMessage());
147 }
148 }
149
150 public void testFilterIgnoresRequestsContainingNoAuthorizationHeader()
151 throws Exception {
152
153 MockHttpServletRequest request = new MockHttpServletRequest();
154 request.setServletPath("/some_file.html");
155
156
157 executeFilterInContainerSimulator(filter, request, true);
158
159 assertNull(SecurityContextHolder.getContext().getAuthentication());
160 }
161
162 public void testGettersSetters() {
163 BasicProcessingFilter filter = new BasicProcessingFilter();
164 filter.setAuthenticationManager(new MockAuthenticationManager());
165 assertTrue(filter.getAuthenticationManager() != null);
166
167 filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("sx"));
168 assertTrue(filter.getAuthenticationEntryPoint() != null);
169 }
170
171 public void testInvalidBasicAuthorizationTokenIsIgnored()
172 throws Exception {
173
174 String token = "NOT_A_VALID_TOKEN_AS_MISSING_COLON";
175 MockHttpServletRequest request = new MockHttpServletRequest();
176 request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
177 request.setServletPath("/some_file.html");
178 request.setSession(new MockHttpSession());
179
180
181 executeFilterInContainerSimulator(filter, request, false);
182
183 assertNull(SecurityContextHolder.getContext().getAuthentication());
184 }
185
186 public void testNormalOperation() throws Exception {
187
188 String token = "marissa:koala";
189 MockHttpServletRequest request = new MockHttpServletRequest();
190 request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
191 request.setServletPath("/some_file.html");
192 request.setSession(new MockHttpSession());
193
194
195 assertNull(SecurityContextHolder.getContext().getAuthentication());
196 executeFilterInContainerSimulator(filter, request, true);
197
198 assertNotNull(SecurityContextHolder.getContext().getAuthentication());
199 assertEquals("marissa",
200 ((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
201 }
202
203 public void testOtherAuthorizationSchemeIsIgnored()
204 throws Exception {
205
206 MockHttpServletRequest request = new MockHttpServletRequest();
207 request.addHeader("Authorization", "SOME_OTHER_AUTHENTICATION_SCHEME");
208 request.setServletPath("/some_file.html");
209
210
211 executeFilterInContainerSimulator(filter, request, true);
212
213 assertNull(SecurityContextHolder.getContext().getAuthentication());
214 }
215
216 public void testStartupDetectsMissingAuthenticationEntryPoint()
217 throws Exception {
218 try {
219 BasicProcessingFilter filter = new BasicProcessingFilter();
220 filter.setAuthenticationManager(new MockAuthenticationManager());
221 filter.afterPropertiesSet();
222 fail("Should have thrown IllegalArgumentException");
223 } catch (IllegalArgumentException expected) {
224 assertEquals("An AuthenticationEntryPoint is required", expected.getMessage());
225 }
226 }
227
228 public void testStartupDetectsMissingAuthenticationManager()
229 throws Exception {
230 try {
231 BasicProcessingFilter filter = new BasicProcessingFilter();
232 filter.setAuthenticationEntryPoint(new MockAuthenticationEntryPoint("x"));
233 filter.afterPropertiesSet();
234 fail("Should have thrown IllegalArgumentException");
235 } catch (IllegalArgumentException expected) {
236 assertEquals("An AuthenticationManager is required", expected.getMessage());
237 }
238 }
239
240 public void testSuccessLoginThenFailureLoginResultsInSessionLoosingToken()
241 throws Exception {
242
243 String token = "marissa:koala";
244 MockHttpServletRequest request = new MockHttpServletRequest();
245 request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
246 request.setServletPath("/some_file.html");
247 request.setSession(new MockHttpSession());
248
249
250 executeFilterInContainerSimulator(filter, request, true);
251
252 assertNotNull(SecurityContextHolder.getContext().getAuthentication());
253 assertEquals("marissa",
254 ((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
255
256
257
258 token = "otherUser:WRONG_PASSWORD";
259 request = new MockHttpServletRequest();
260 request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
261 request.setServletPath("/some_file.html");
262 request.setSession(new MockHttpSession());
263
264
265 MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
266
267 assertNull(SecurityContextHolder.getContext().getAuthentication());
268 assertEquals(401, response.getStatus());
269 }
270
271 public void testWrongPasswordContinuesFilterChainIfIgnoreFailureIsTrue()
272 throws Exception {
273
274 String token = "marissa:WRONG_PASSWORD";
275 MockHttpServletRequest request = new MockHttpServletRequest();
276 request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
277 request.setServletPath("/some_file.html");
278 request.setSession(new MockHttpSession());
279
280 filter.setIgnoreFailure(true);
281 assertTrue(filter.isIgnoreFailure());
282
283
284 MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, true);
285
286 assertNull(SecurityContextHolder.getContext().getAuthentication());
287 }
288
289 public void testWrongPasswordReturnsForbiddenIfIgnoreFailureIsFalse()
290 throws Exception {
291
292 String token = "marissa:WRONG_PASSWORD";
293 MockHttpServletRequest request = new MockHttpServletRequest();
294 request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
295 request.setServletPath("/some_file.html");
296 request.setSession(new MockHttpSession());
297 assertFalse(filter.isIgnoreFailure());
298
299
300 MockHttpServletResponse response = executeFilterInContainerSimulator(filter, request, false);
301
302 assertNull(SecurityContextHolder.getContext().getAuthentication());
303 assertEquals(401, response.getStatus());
304 }
305
306
307
308 private class MockApplicationEventPublisher implements ApplicationEventPublisher {
309 public MockApplicationEventPublisher() {}
310
311 public void publishEvent(ApplicationEvent event) {}
312 }
313 }