Возможно, вы захотите взглянуть здесь: https://jira.springsource.org/browse/SEC-876. Хотя этот кодовый вклад был отклонен, с разумным ответом он может дать вам подсказки.
Мы используем следующую конфигурацию:
Spring XML
<bean id="ldapUserService" class="MyUserDetailService">
<constructor-arg ref="ldapUserSearch"/>
<constructor-arg ref="ldapAuthoritiesPopulator"/>
</bean>
<bean id="ldapUserSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg value="OU=FOO-Accounts,OU=FOO,OU=OU-GLOBAL"/> <!-- user search base, RELATIVE TO SERVER CONTEXT (URL & base of configured LDAP server)! -->
<constructor-arg value="(sAMAccountName={0})"/> <!-- user search filter -->
<constructor-arg ref="ldapServer"/>
</bean>
<bean id="ldapAuthoritiesPopulator" class="MyLdapAuthoritiesPopulator">
<constructor-arg ref="ldapServer" />
<constructor-arg value="=OU=SomeFooBar,OU=FOO-Global-Security,OU=FOO-Groups,OU=FOO,OU=OU-GLOBAL" /> <!-- group search base, RELATIVE TO SERVER CONTEXT (URL & base of configured LDAP server)! -->
<constructor-arg ref="roleMappings"/>
<property name="groupRoleAttribute" value="cn" />
<property name="groupSearchFilter" value="(member={0})" />
</bean>
Populator
Существует много проприетарного кода, которым я не могу поделиться, потому что у нашего клиента есть дополнительная информация в AD, которую мы должны извлечь. Я удалил это, поскольку это не беспокоило вопрос. Следовательно, этот код не будет компилироваться.
public class MyLdapAuthoritiesPopulator extends DefaultLdapAuthoritiesPopulator {
/**
* Prefix assigned by Spring Security to each group/role from LDAP.
*/
public static final String AUTHORITY_ROLE_PREFIX = "ROLE_";
private Properties roleMappings;
private Properties invertedRoleMappings;
/**
*
* @param contextSource supplies the contexts used to search for user roles.
* @param groupSearchBase if this is an empty string the search will be performed from the root DN
* of the context factory. If null, no search will be performed.
* @param roleMappings maps logical (internal) role names to names as delivered by LDAP
*/
@SuppressWarnings("deprecation")
public MyLdapAuthoritiesPopulator(final ContextSource contextSource,
final String groupSearchBase,
final Properties roleMappings) {
super(contextSource, groupSearchBase);
setConvertToUpperCase(false);
setRolePrefix("");
this.roleMappings = roleMappings;
this.invertedRoleMappings = invertRoleMappings();
logger.info("Processing LDAP roles based on the following mapping: {}.", roleMappings);
}
.....
@Override
public Set<GrantedAuthority> getGroupMembershipRoles(final String userDn, final String username) {
final Set<GrantedAuthority> effectiveGroupMembershipRoles = super.getGroupMembershipRoles(
userDn, username);
return mapEffectiveRolesToApplicationRoles(effectiveGroupMembershipRoles);
}
/**
* Maps effective LDAP roles such as 'foo_boston_dispatcher' or 'foo_boston_readonly' to
* FOO internal roles. The internal role (i.e. the {@link GrantedAuthority}) is a combination
* of the 'ROLE_' prefix and a {@link Role} enum value. .........
*/
Set<GrantedAuthority> mapEffectiveRolesToApplicationRoles(final Set<GrantedAuthority> effectiveGroupMembershipRoles) {
logger.info("Processing effective roles from LDAP: {}.", effectiveGroupMembershipRoles);
final Set<GrantedAuthority> internalRoles = new HashSet<GrantedAuthority>();
final List<String> effectiveRoleNames = extractRoleNamesFrom(effectiveGroupMembershipRoles);
final List<String> unmappedGroupMembershipRoles = new ArrayList<String>();
......
// in a method invoked here we do something like internalRoles.add(new GrantedAuthority(AUTHORITY_ROLE_PREFIX + role));
......
logger.info("Created internal roles {}.", internalRoles);
logger.trace(
"The following group membership roles were not mapped to an internal equivalent: {}",
unmappedGroupMembershipRoles);
return internalRoles;
}
......
private List<String> extractRoleNamesFrom(final Collection<GrantedAuthority> authorities) {
final List<String> authorityNames = new ArrayList<String>(authorities.size());
for (GrantedAuthority authority : authorities) {
authorityNames.add(authority.getAuthority());
}
return authorityNames;
}
}