1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.security.providers.ldap.authenticator;
17
18 import org.springframework.security.Authentication;
19 import org.springframework.security.BadCredentialsException;
20 import org.springframework.security.ldap.LdapUtils;
21 import org.springframework.security.ldap.SpringSecurityLdapTemplate;
22 import org.springframework.security.providers.UsernamePasswordAuthenticationToken;
23 import org.springframework.security.providers.encoding.PasswordEncoder;
24 import org.springframework.security.userdetails.UsernameNotFoundException;
25 import org.springframework.ldap.NameNotFoundException;
26 import org.springframework.ldap.core.DirContextOperations;
27 import org.springframework.ldap.core.support.BaseLdapPathContextSource;
28 import org.springframework.util.Assert;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32
33 import java.util.Iterator;
34
35
36
37
38
39
40
41
42
43
44
45
46
47 public final class PasswordComparisonAuthenticator extends AbstractLdapAuthenticator {
48
49
50 private static final Log logger = LogFactory.getLog(PasswordComparisonAuthenticator.class);
51
52
53
54 private PasswordEncoder passwordEncoder = new LdapShaPasswordEncoder();
55 private String passwordAttributeName = "userPassword";
56
57
58
59 public PasswordComparisonAuthenticator(BaseLdapPathContextSource contextSource) {
60 super(contextSource);
61 }
62
63
64
65 public DirContextOperations authenticate(final Authentication authentication) {
66 Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
67 "Can only process UsernamePasswordAuthenticationToken objects");
68
69
70 DirContextOperations user = null;
71 String username = authentication.getName();
72 String password = (String)authentication.getCredentials();
73
74 Iterator dns = getUserDns(username).iterator();
75
76 SpringSecurityLdapTemplate ldapTemplate = new SpringSecurityLdapTemplate(getContextSource());
77
78 while (dns.hasNext() && user == null) {
79 final String userDn = (String) dns.next();
80
81 try {
82 user = ldapTemplate.retrieveEntry(userDn, getUserAttributes());
83 } catch (NameNotFoundException ignore) {
84 }
85 }
86
87 if (user == null && getUserSearch() != null) {
88 user = getUserSearch().searchForUser(username);
89 }
90
91 if (user == null) {
92 throw new UsernameNotFoundException("User not found: " + username, username);
93 }
94
95 if (logger.isDebugEnabled()) {
96 logger.debug("Performing LDAP compare of password attribute '" + passwordAttributeName + "' for user '" +
97 user.getDn() +"'");
98 }
99
100 String encodedPassword = passwordEncoder.encodePassword(password, null);
101 byte[] passwordBytes = LdapUtils.getUtf8Bytes(encodedPassword);
102
103 if (!ldapTemplate.compare(user.getDn().toString(), passwordAttributeName, passwordBytes)) {
104 throw new BadCredentialsException(messages.getMessage("PasswordComparisonAuthenticator.badCredentials",
105 "Bad credentials"));
106 }
107
108 return user;
109 }
110
111 public void setPasswordAttributeName(String passwordAttribute) {
112 Assert.hasLength(passwordAttribute, "passwordAttributeName must not be empty or null");
113 this.passwordAttributeName = passwordAttribute;
114 }
115
116 public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
117 Assert.notNull(passwordEncoder, "passwordEncoder must not be null.");
118 this.passwordEncoder = passwordEncoder;
119 }
120 }