This project has retired. For details please refer to its
Attic page.
LdapBindAuthenticator xref
1 package org.apache.archiva.redback.authentication.ldap;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.archiva.redback.authentication.AbstractAuthenticator;
23 import org.apache.archiva.redback.common.ldap.connection.DefaultLdapConnection;
24 import org.apache.archiva.redback.common.ldap.connection.LdapConnection;
25 import org.apache.archiva.redback.common.ldap.user.UserMapper;
26 import org.apache.archiva.redback.common.ldap.connection.LdapConnectionFactory;
27 import org.apache.archiva.redback.configuration.UserConfiguration;
28 import org.apache.archiva.redback.configuration.UserConfigurationKeys;
29 import org.apache.commons.lang.StringUtils;
30 import org.apache.archiva.redback.authentication.AuthenticationDataSource;
31 import org.apache.archiva.redback.authentication.AuthenticationException;
32 import org.apache.archiva.redback.authentication.AuthenticationResult;
33 import org.apache.archiva.redback.authentication.Authenticator;
34 import org.apache.archiva.redback.authentication.PasswordBasedAuthenticationDataSource;
35 import org.apache.archiva.redback.common.ldap.connection.LdapException;
36 import org.apache.archiva.redback.users.ldap.service.LdapCacheService;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.springframework.stereotype.Service;
40
41 import javax.inject.Inject;
42 import javax.inject.Named;
43 import javax.naming.NamingEnumeration;
44 import javax.naming.NamingException;
45 import javax.naming.directory.DirContext;
46 import javax.naming.directory.SearchControls;
47 import javax.naming.directory.SearchResult;
48
49
50
51
52
53
54 @Service( "authenticator#ldap" )
55 public class LdapBindAuthenticator
56 extends AbstractAuthenticator
57 implements Authenticator
58 {
59
60 private Logger log = LoggerFactory.getLogger( getClass() );
61
62 @Inject
63 @Named( value = "userMapper#ldap" )
64 private UserMapper mapper;
65
66 @Inject
67 @Named( value = "ldapConnectionFactory#configurable" )
68 private LdapConnectionFactory connectionFactory;
69
70 @Inject
71 @Named( value = "userConfiguration#default" )
72 private UserConfiguration config;
73
74 @Inject
75 private LdapCacheService ldapCacheService;
76
77 public String getId()
78 {
79 return "LdapBindAuthenticator";
80 }
81
82 public AuthenticationResult authenticate( AuthenticationDataSource s )
83 throws AuthenticationException
84 {
85 PasswordBasedAuthenticationDataSource source = (PasswordBasedAuthenticationDataSource) s;
86
87 if ( !config.getBoolean( UserConfigurationKeys.LDAP_BIND_AUTHENTICATOR_ENABLED ) || (
88 !config.getBoolean( UserConfigurationKeys.LDAP_BIND_AUTHENTICATOR_ALLOW_EMPTY_PASSWORDS, false )
89 && StringUtils.isEmpty( source.getPassword() ) ) )
90 {
91 return new AuthenticationResult( false, source.getUsername(), null );
92 }
93
94 SearchControls ctls = new SearchControls();
95
96 ctls.setCountLimit( 1 );
97
98 ctls.setDerefLinkFlag( true );
99 ctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
100
101 String filter = "(&(objectClass=" + mapper.getUserObjectClass() + ")" + ( mapper.getUserFilter() != null
102 ? mapper.getUserFilter()
103 : "" ) + "(" + mapper.getUserIdAttribute() + "=" + source.getUsername() + "))";
104
105 log.debug( "Searching for users with filter: '{}' from base dn: {}", filter, mapper.getUserBaseDn() );
106
107 LdapConnection ldapConnection = null;
108 LdapConnection authLdapConnection = null;
109 NamingEnumeration<SearchResult> results = null;
110 try
111 {
112 ldapConnection = getLdapConnection();
113
114 String userDn = ldapCacheService.getLdapUserDn( source.getUsername() );
115
116 if ( userDn == null )
117 {
118 log.debug( "userDn for user {} not found in cache. Retrieving from ldap server..",
119 source.getUsername() );
120
121 DirContext context = ldapConnection.getDirContext();
122
123 results = context.search( mapper.getUserBaseDn(), filter, ctls );
124
125 log.debug( "Found user '{}': {}", source.getUsername(), results.hasMoreElements() );
126
127 if ( results.hasMoreElements() )
128 {
129 SearchResult result = results.nextElement();
130
131 userDn = result.getNameInNamespace();
132
133 log.debug( "Adding userDn {} for user {} to the cache..", userDn, source.getUsername() );
134
135
136 ldapCacheService.addLdapUserDn( source.getUsername(), userDn );
137 }
138 else
139 {
140 return new AuthenticationResult( false, source.getUsername(), null );
141 }
142 }
143
144 log.debug( "Attempting Authenication: {}", userDn );
145
146 authLdapConnection = connectionFactory.getConnection( userDn, source.getPassword() );
147
148 log.info( "user '{}' authenticated", source.getUsername() );
149
150 return new AuthenticationResult( true, source.getUsername(), null );
151 }
152 catch ( LdapException e )
153 {
154 return new AuthenticationResult( false, source.getUsername(), e );
155 }
156 catch ( NamingException e )
157 {
158 return new AuthenticationResult( false, source.getUsername(), e );
159 }
160 finally
161 {
162 closeNamingEnumeration( results );
163 closeLdapConnection( ldapConnection );
164 if ( authLdapConnection != null )
165 {
166 closeLdapConnection( authLdapConnection );
167 }
168 }
169 }
170
171 public boolean supportsDataSource( AuthenticationDataSource source )
172 {
173 return ( source instanceof PasswordBasedAuthenticationDataSource );
174 }
175
176 private LdapConnection getLdapConnection()
177 throws LdapException
178 {
179 return connectionFactory.getConnection();
180 }
181
182 private void closeLdapConnection( LdapConnection ldapConnection )
183 {
184 if ( ldapConnection != null )
185 {
186 ldapConnection.close();
187 }
188 }
189
190 private void closeNamingEnumeration( NamingEnumeration<SearchResult> results )
191 {
192 try
193 {
194 if ( results != null )
195 {
196 results.close();
197 }
198 }
199 catch ( NamingException e )
200 {
201 log.warn( "skip exception closing naming search result " + e.getMessage() );
202 }
203 }
204 }