2020import java .util .Collection ;
2121import java .util .HashSet ;
2222import java .util .List ;
23+ import java .util .Map ;
2324import java .util .Set ;
25+ import java .util .function .Function ;
2426
2527import javax .naming .directory .SearchControls ;
2628
2729import org .apache .commons .logging .Log ;
2830import org .apache .commons .logging .LogFactory ;
29-
3031import org .springframework .ldap .core .ContextSource ;
3132import org .springframework .ldap .core .DirContextOperations ;
3233import org .springframework .ldap .core .LdapTemplate ;
@@ -137,15 +138,22 @@ public class DefaultLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator
137138 * The pattern to be used for the user search. {0} is the user's DN
138139 */
139140 private String groupSearchFilter = "(member={0})" ;
141+
140142 /**
141143 * The role prefix that will be prepended to each role name
142144 */
143145 private String rolePrefix = "ROLE_" ;
146+
144147 /**
145148 * Should we convert the role name to uppercase
146149 */
147150 private boolean convertToUpperCase = true ;
148151
152+ /**
153+ * The mapping function to be used to populate authorities.
154+ */
155+ private Function <Map <String , List <String >>, GrantedAuthority > authorityMapper ;
156+
149157 // ~ Constructors
150158 // ===================================================================================================
151159
@@ -171,6 +179,16 @@ else if (groupSearchBase.length() == 0) {
171179 logger .info (
172180 "groupSearchBase is empty. Searches will be performed from the context source base" );
173181 }
182+
183+ this .authorityMapper = record -> {
184+ String role = record .get (this .groupRoleAttribute ).get (0 );
185+
186+ if (this .convertToUpperCase ) {
187+ role = role .toUpperCase ();
188+ }
189+
190+ return new SimpleGrantedAuthority (this .rolePrefix + role );
191+ };
174192 }
175193
176194 // ~ Methods
@@ -238,21 +256,18 @@ public Set<GrantedAuthority> getGroupMembershipRoles(String userDn, String usern
238256 + " in search base '" + getGroupSearchBase () + "'" );
239257 }
240258
241- Set <String > userRoles = getLdapTemplate ().searchForSingleAttributeValues (
242- getGroupSearchBase (), this .groupSearchFilter ,
243- new String [] { userDn , username }, this .groupRoleAttribute );
259+ Set <Map <String , List <String >>> userRoles = getLdapTemplate ()
260+ .searchForMultipleAttributeValues (getGroupSearchBase (),
261+ this .groupSearchFilter ,
262+ new String [] { userDn , username },
263+ new String [] { this .groupRoleAttribute });
244264
245265 if (logger .isDebugEnabled ()) {
246266 logger .debug ("Roles from search: " + userRoles );
247267 }
248268
249- for (String role : userRoles ) {
250-
251- if (this .convertToUpperCase ) {
252- role = role .toUpperCase ();
253- }
254-
255- authorities .add (new SimpleGrantedAuthority (this .rolePrefix + role ));
269+ for (Map <String , List <String >> role : userRoles ) {
270+ authorities .add (authorityMapper .apply (role ));
256271 }
257272
258273 return authorities ;
@@ -325,6 +340,17 @@ public void setIgnorePartialResultException(boolean ignore) {
325340 getLdapTemplate ().setIgnorePartialResultException (ignore );
326341 }
327342
343+ /**
344+ * Sets the mapping function which will be used to create instances of {@link GrantedAuthority}
345+ * given the context record.
346+ *
347+ * @param authorityMapper the mapping function
348+ */
349+ public void setAuthorityMapper (Function <Map <String , List <String >>, GrantedAuthority > authorityMapper ) {
350+ Assert .notNull (authorityMapper , "authorityMapper must not be null" );
351+ this .authorityMapper = authorityMapper ;
352+ }
353+
328354 /**
329355 * Returns the current LDAP template. Method available so that classes extending this
330356 * can override the template used
0 commit comments