1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.acegisecurity.providers.dao;
17
18 import java.util.HashMap;
19 import java.util.Map;
20
21 import junit.framework.TestCase;
22
23 import org.acegisecurity.AccountExpiredException;
24 import org.acegisecurity.Authentication;
25 import org.acegisecurity.AuthenticationServiceException;
26 import org.acegisecurity.BadCredentialsException;
27 import org.acegisecurity.CredentialsExpiredException;
28 import org.acegisecurity.DisabledException;
29 import org.acegisecurity.GrantedAuthority;
30 import org.acegisecurity.GrantedAuthorityImpl;
31 import org.acegisecurity.LockedException;
32 import org.acegisecurity.providers.TestingAuthenticationToken;
33 import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
34 import org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache;
35 import org.acegisecurity.providers.dao.cache.NullUserCache;
36 import org.acegisecurity.providers.dao.salt.SystemWideSaltSource;
37 import org.acegisecurity.providers.encoding.ShaPasswordEncoder;
38 import org.acegisecurity.userdetails.User;
39 import org.acegisecurity.userdetails.UserDetails;
40 import org.acegisecurity.userdetails.UserDetailsService;
41 import org.acegisecurity.userdetails.UsernameNotFoundException;
42 import org.springframework.dao.DataAccessException;
43 import org.springframework.dao.DataRetrievalFailureException;
44
45
46 /***
47 * Tests {@link DaoAuthenticationProvider}.
48 *
49 * @author Ben Alex
50 * @version $Id: DaoAuthenticationProviderTests.java,v 1.28 2005/11/30 01:23:34 benalex Exp $
51 */
52 public class DaoAuthenticationProviderTests extends TestCase {
53
54
55 public final void setUp() throws Exception {
56 super.setUp();
57 }
58
59 public static void main(String[] args) {
60 junit.textui.TestRunner.run(DaoAuthenticationProviderTests.class);
61 }
62
63 public void testAuthenticateFailsForIncorrectPasswordCase() {
64 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
65 "KOala");
66
67 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
68 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
69 provider.setUserCache(new MockUserCache());
70
71 try {
72 provider.authenticate(token);
73 fail("Should have thrown BadCredentialsException");
74 } catch (BadCredentialsException expected) {
75 assertTrue(true);
76 }
77 }
78
79 public void testAuthenticateFailsIfAccountExpired() {
80 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter",
81 "opal");
82
83 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
84 provider.setUserDetailsService(new MockAuthenticationDaoUserPeterAccountExpired());
85 provider.setUserCache(new MockUserCache());
86
87 try {
88 provider.authenticate(token);
89 fail("Should have thrown AccountExpiredException");
90 } catch (AccountExpiredException expected) {
91 assertTrue(true);
92 }
93 }
94
95 public void testAuthenticateFailsIfAccountLocked() {
96 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter",
97 "opal");
98
99 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
100 provider.setUserDetailsService(new MockAuthenticationDaoUserPeterAccountLocked());
101 provider.setUserCache(new MockUserCache());
102
103 try {
104 provider.authenticate(token);
105 fail("Should have thrown LockedException");
106 } catch (LockedException expected) {
107 assertTrue(true);
108 }
109 }
110
111 public void testAuthenticateFailsIfCredentialsExpired() {
112 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter",
113 "opal");
114
115 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
116 provider.setUserDetailsService(new MockAuthenticationDaoUserPeterCredentialsExpired());
117 provider.setUserCache(new MockUserCache());
118
119 try {
120 provider.authenticate(token);
121 fail("Should have thrown CredentialsExpiredException");
122 } catch (CredentialsExpiredException expected) {
123 assertTrue(true);
124 }
125
126
127 token = new UsernamePasswordAuthenticationToken("peter",
128 "wrong_password");
129
130 try {
131 provider.authenticate(token);
132 fail("Should have thrown BadCredentialsException");
133 } catch (BadCredentialsException expected) {
134 assertTrue(true);
135 }
136 }
137
138 public void testAuthenticateFailsIfUserDisabled() {
139 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("peter",
140 "opal");
141
142 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
143 provider.setUserDetailsService(new MockAuthenticationDaoUserPeter());
144 provider.setUserCache(new MockUserCache());
145
146 try {
147 provider.authenticate(token);
148 fail("Should have thrown DisabledException");
149 } catch (DisabledException expected) {
150 assertTrue(true);
151 }
152 }
153
154 public void testAuthenticateFailsWhenAuthenticationDaoHasBackendFailure() {
155 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
156 "koala");
157
158 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
159 provider.setUserDetailsService(new MockAuthenticationDaoSimulateBackendError());
160 provider.setUserCache(new MockUserCache());
161
162 try {
163 provider.authenticate(token);
164 fail("Should have thrown AuthenticationServiceException");
165 } catch (AuthenticationServiceException expected) {
166 assertTrue(true);
167 }
168 }
169
170 public void testAuthenticateFailsWithEmptyUsername() {
171 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null,
172 "koala");
173
174 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
175 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
176 provider.setUserCache(new MockUserCache());
177
178 try {
179 provider.authenticate(token);
180 fail("Should have thrown BadCredentialsException");
181 } catch (BadCredentialsException expected) {
182 assertTrue(true);
183 }
184 }
185
186 public void testAuthenticateFailsWithInvalidPassword() {
187 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
188 "INVALID_PASSWORD");
189
190 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
191 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
192 provider.setUserCache(new MockUserCache());
193
194 try {
195 provider.authenticate(token);
196 fail("Should have thrown BadCredentialsException");
197 } catch (BadCredentialsException expected) {
198 assertTrue(true);
199 }
200 }
201
202 public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionFalse() {
203 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER",
204 "koala");
205
206 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
207 provider.setHideUserNotFoundExceptions(false);
208 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
209 provider.setUserCache(new MockUserCache());
210
211 try {
212 provider.authenticate(token);
213 fail("Should have thrown UsernameNotFoundException");
214 } catch (UsernameNotFoundException expected) {
215 assertTrue(true);
216 }
217 }
218
219 public void testAuthenticateFailsWithInvalidUsernameAndHideUserNotFoundExceptionsWithDefaultOfTrue() {
220 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("INVALID_USER",
221 "koala");
222
223 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
224 assertTrue(provider.isHideUserNotFoundExceptions());
225 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
226 provider.setUserCache(new MockUserCache());
227
228 try {
229 provider.authenticate(token);
230 fail("Should have thrown BadCredentialsException");
231 } catch (BadCredentialsException expected) {
232 assertTrue(true);
233 }
234 }
235
236 public void testAuthenticateFailsWithMixedCaseUsernameIfDefaultChanged() {
237 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("MaRiSSA",
238 "koala");
239
240 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
241 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
242 provider.setUserCache(new MockUserCache());
243
244 try {
245 provider.authenticate(token);
246 fail("Should have thrown BadCredentialsException");
247 } catch (BadCredentialsException expected) {
248 assertTrue(true);
249 }
250 }
251
252 public void testAuthenticates() {
253 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
254 "koala");
255 token.setDetails("192.168.0.1");
256
257 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
258 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
259 provider.setUserCache(new MockUserCache());
260
261 Authentication result = provider.authenticate(token);
262
263 if (!(result instanceof UsernamePasswordAuthenticationToken)) {
264 fail(
265 "Should have returned instance of UsernamePasswordAuthenticationToken");
266 }
267
268 UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
269 assertEquals(User.class, castResult.getPrincipal().getClass());
270 assertEquals("koala", castResult.getCredentials());
271 assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority());
272 assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
273 assertEquals("192.168.0.1", castResult.getDetails());
274 }
275
276 public void testAuthenticatesASecondTime() {
277 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
278 "koala");
279
280 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
281 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
282 provider.setUserCache(new MockUserCache());
283
284 Authentication result = provider.authenticate(token);
285
286 if (!(result instanceof UsernamePasswordAuthenticationToken)) {
287 fail(
288 "Should have returned instance of UsernamePasswordAuthenticationToken");
289 }
290
291
292 Authentication result2 = provider.authenticate(result);
293
294 if (!(result2 instanceof UsernamePasswordAuthenticationToken)) {
295 fail(
296 "Should have returned instance of UsernamePasswordAuthenticationToken");
297 }
298
299 assertEquals(result.getCredentials(), result2.getCredentials());
300 }
301
302 public void testAuthenticatesWhenASaltIsUsed() {
303 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
304 "koala");
305
306 SystemWideSaltSource salt = new SystemWideSaltSource();
307 salt.setSystemWideSalt("SYSTEM_SALT_VALUE");
308
309 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
310 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissaWithSalt());
311 provider.setSaltSource(salt);
312 provider.setUserCache(new MockUserCache());
313
314 Authentication result = provider.authenticate(token);
315
316 if (!(result instanceof UsernamePasswordAuthenticationToken)) {
317 fail(
318 "Should have returned instance of UsernamePasswordAuthenticationToken");
319 }
320
321 UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
322 assertEquals(User.class, castResult.getPrincipal().getClass());
323
324
325 assertEquals("koala", castResult.getCredentials());
326 assertEquals("ROLE_ONE", castResult.getAuthorities()[0].getAuthority());
327 assertEquals("ROLE_TWO", castResult.getAuthorities()[1].getAuthority());
328 }
329
330 public void testAuthenticatesWithForcePrincipalAsString() {
331 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
332 "koala");
333
334 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
335 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
336 provider.setUserCache(new MockUserCache());
337 provider.setForcePrincipalAsString(true);
338
339 Authentication result = provider.authenticate(token);
340
341 if (!(result instanceof UsernamePasswordAuthenticationToken)) {
342 fail(
343 "Should have returned instance of UsernamePasswordAuthenticationToken");
344 }
345
346 UsernamePasswordAuthenticationToken castResult = (UsernamePasswordAuthenticationToken) result;
347 assertEquals(String.class, castResult.getPrincipal().getClass());
348 assertEquals("marissa", castResult.getPrincipal());
349 }
350
351 public void testDetectsNullBeingReturnedFromAuthenticationDao() {
352 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
353 "koala");
354
355 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
356 provider.setUserDetailsService(new MockAuthenticationDaoReturnsNull());
357
358 try {
359 provider.authenticate(token);
360 fail("Should have thrown AuthenticationServiceException");
361 } catch (AuthenticationServiceException expected) {
362 assertEquals("AuthenticationDao returned null, which is an interface contract violation",
363 expected.getMessage());
364 }
365 }
366
367 public void testGettersSetters() {
368 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
369 provider.setPasswordEncoder(new ShaPasswordEncoder());
370 assertEquals(ShaPasswordEncoder.class,
371 provider.getPasswordEncoder().getClass());
372
373 provider.setSaltSource(new SystemWideSaltSource());
374 assertEquals(SystemWideSaltSource.class,
375 provider.getSaltSource().getClass());
376
377 provider.setUserCache(new EhCacheBasedUserCache());
378 assertEquals(EhCacheBasedUserCache.class,
379 provider.getUserCache().getClass());
380
381 assertFalse(provider.isForcePrincipalAsString());
382 provider.setForcePrincipalAsString(true);
383 assertTrue(provider.isForcePrincipalAsString());
384 }
385
386 public void testGoesBackToAuthenticationDaoToObtainLatestPasswordIfCachedPasswordSeemsIncorrect() {
387 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("marissa",
388 "koala");
389
390 MockAuthenticationDaoUserMarissa authenticationDao = new MockAuthenticationDaoUserMarissa();
391 MockUserCache cache = new MockUserCache();
392 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
393 provider.setUserDetailsService(authenticationDao);
394 provider.setUserCache(cache);
395
396
397 provider.authenticate(token);
398
399
400 assertEquals("koala", cache.getUserFromCache("marissa").getPassword());
401
402
403 authenticationDao.setPassword("easternLongNeckTurtle");
404
405
406 token = new UsernamePasswordAuthenticationToken("marissa",
407 "easternLongNeckTurtle");
408 provider.authenticate(token);
409
410
411
412 assertEquals("easternLongNeckTurtle",
413 cache.getUserFromCache("marissa").getPassword());
414 }
415
416 public void testStartupFailsIfNoAuthenticationDao()
417 throws Exception {
418 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
419
420 try {
421 provider.afterPropertiesSet();
422 fail("Should have thrown IllegalArgumentException");
423 } catch (IllegalArgumentException expected) {
424 assertTrue(true);
425 }
426 }
427
428 public void testStartupFailsIfNoUserCacheSet() throws Exception {
429 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
430 provider.setUserDetailsService(new MockAuthenticationDaoUserMarissa());
431 assertEquals(NullUserCache.class, provider.getUserCache().getClass());
432 provider.setUserCache(null);
433
434 try {
435 provider.afterPropertiesSet();
436 fail("Should have thrown IllegalArgumentException");
437 } catch (IllegalArgumentException expected) {
438 assertTrue(true);
439 }
440 }
441
442 public void testStartupSuccess() throws Exception {
443 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
444 UserDetailsService dao = new MockAuthenticationDaoUserMarissa();
445 provider.setUserDetailsService(dao);
446 provider.setUserCache(new MockUserCache());
447 assertEquals(dao, provider.getUserDetailsService());
448 provider.afterPropertiesSet();
449 assertTrue(true);
450 }
451
452 public void testSupports() {
453 DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
454 assertTrue(provider.supports(UsernamePasswordAuthenticationToken.class));
455 assertTrue(!provider.supports(TestingAuthenticationToken.class));
456 }
457
458
459
460 private class MockAuthenticationDaoReturnsNull implements UserDetailsService {
461 public UserDetails loadUserByUsername(String username)
462 throws UsernameNotFoundException, DataAccessException {
463 return null;
464 }
465 }
466
467 private class MockAuthenticationDaoSimulateBackendError
468 implements UserDetailsService {
469 public UserDetails loadUserByUsername(String username)
470 throws UsernameNotFoundException, DataAccessException {
471 throw new DataRetrievalFailureException(
472 "This mock simulator is designed to fail");
473 }
474 }
475
476 private class MockAuthenticationDaoUserMarissa implements UserDetailsService {
477 private String password = "koala";
478
479 public void setPassword(String password) {
480 this.password = password;
481 }
482
483 public UserDetails loadUserByUsername(String username)
484 throws UsernameNotFoundException, DataAccessException {
485 if ("marissa".equals(username)) {
486 return new User("marissa", password, true, true, true, true,
487 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
488 "ROLE_TWO")});
489 } else {
490 throw new UsernameNotFoundException("Could not find: "
491 + username);
492 }
493 }
494 }
495
496 private class MockAuthenticationDaoUserMarissaWithSalt
497 implements UserDetailsService {
498 public UserDetails loadUserByUsername(String username)
499 throws UsernameNotFoundException, DataAccessException {
500 if ("marissa".equals(username)) {
501 return new User("marissa", "koala{SYSTEM_SALT_VALUE}", true,
502 true, true, true,
503 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
504 "ROLE_TWO")});
505 } else {
506 throw new UsernameNotFoundException("Could not find: "
507 + username);
508 }
509 }
510 }
511
512 private class MockAuthenticationDaoUserPeter implements UserDetailsService {
513 public UserDetails loadUserByUsername(String username)
514 throws UsernameNotFoundException, DataAccessException {
515 if ("peter".equals(username)) {
516 return new User("peter", "opal", false, true, true, true,
517 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
518 "ROLE_TWO")});
519 } else {
520 throw new UsernameNotFoundException("Could not find: "
521 + username);
522 }
523 }
524 }
525
526 private class MockAuthenticationDaoUserPeterAccountExpired
527 implements UserDetailsService {
528 public UserDetails loadUserByUsername(String username)
529 throws UsernameNotFoundException, DataAccessException {
530 if ("peter".equals(username)) {
531 return new User("peter", "opal", true, false, true, true,
532 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
533 "ROLE_TWO")});
534 } else {
535 throw new UsernameNotFoundException("Could not find: "
536 + username);
537 }
538 }
539 }
540
541 private class MockAuthenticationDaoUserPeterAccountLocked
542 implements UserDetailsService {
543 public UserDetails loadUserByUsername(String username)
544 throws UsernameNotFoundException, DataAccessException {
545 if ("peter".equals(username)) {
546 return new User("peter", "opal", true, true, true, false,
547 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
548 "ROLE_TWO")});
549 } else {
550 throw new UsernameNotFoundException("Could not find: "
551 + username);
552 }
553 }
554 }
555
556 private class MockAuthenticationDaoUserPeterCredentialsExpired
557 implements UserDetailsService {
558 public UserDetails loadUserByUsername(String username)
559 throws UsernameNotFoundException, DataAccessException {
560 if ("peter".equals(username)) {
561 return new User("peter", "opal", true, true, false, true,
562 new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
563 "ROLE_TWO")});
564 } else {
565 throw new UsernameNotFoundException("Could not find: "
566 + username);
567 }
568 }
569 }
570
571 private class MockUserCache implements UserCache {
572 private Map cache = new HashMap();
573
574 public UserDetails getUserFromCache(String username) {
575 return (User) cache.get(username);
576 }
577
578 public void putUserInCache(UserDetails user) {
579 cache.put(user.getUsername(), user);
580 }
581
582 public void removeUserFromCache(String username) {}
583 }
584 }