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