Обработка ролей при аутентификации в активный каталог с помощью spring security 3.1
Я пытаюсь использовать аутентификацию с Active Directory с помощью Spring Security 3.1.
Я получаю аутентификацию, и все хорошо.
<sec:ldap-server id="ldapServer" url="ldap://ldap/dc=sub,dc=domain,dc=com" port="389" />
<sec:authentication-manager erase-credentials="true" >
<sec:authentication-provider ref="ldapActiveDirectoryAuthProvider" />
</sec:authentication-manager>
<bean id="ldapActiveDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="domain" />
<constructor-arg value="ldap://server:389/"/>
</bean>
Теперь на вопрос. Как обрабатывать роли для пользователя, чтобы настроить фильтры?
например.
<sec:intercept-url pattern="/**" access="ROLE_USER"/>
Решение
Я узнал, как это сделать, используя UserDetailContextMapper и сопоставляю мои группы AD с ROLE_USER, ROLE_ADMIN и т.д.
<bean id="ldapActiveDirectoryAuthProvider"
class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="domain" />
<constructor-arg value="ldap://host:389/"/>
<property name="userDetailsContextMapper" ref="tdrUserDetailsContextMapper"/>
<property name="useAuthenticationRequestCredentials" value="true"/>
</bean>
<bean id="tdrUserDetailsContextMapper" class="com.bla.bla.UserDetailsContextMapperImpl"/>
Класс сопоставления:
public class UserDetailsContextMapperImpl implements UserDetailsContextMapper, Serializable{
private static final long serialVersionUID = 3962976258168853954L;
@Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authority) {
List<GrantedAuthority> mappedAuthorities = new ArrayList<GrantedAuthority>();
for (GrantedAuthority granted : authority) {
if (granted.getAuthority().equalsIgnoreCase("MY USER GROUP")) {
mappedAuthorities.add(new GrantedAuthority(){
private static final long serialVersionUID = 4356967414267942910L;
@Override
public String getAuthority() {
return "ROLE_USER";
}
});
} else if(granted.getAuthority().equalsIgnoreCase("MY ADMIN GROUP")) {
mappedAuthorities.add(new GrantedAuthority() {
private static final long serialVersionUID = -5167156646226168080L;
@Override
public String getAuthority() {
return "ROLE_ADMIN";
}
});
}
}
return new User(username, "", true, true, true, true, mappedAuthorities);
}
@Override
public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {
}
}
Ответы
Ответ 1
Роли в beans.xml должны быть точным совпадением имени CN (общего имени) атрибута значения memberOf. Вы должны прочитать руководство по основам каталогов.
Скажите, есть ли у этого пользователя:
CN=Michael-O,OU=Users,OU=department,DC=sub,DC=company,DC=net
В его контексте существует это значение memberOf CN=Group Name,OU=Permissions,OU=Groups,OU=department,DC=sub,DC=company,DC=net
Bean найдет это значение memberOf и извлечет Group Name
. Вы beans.xml должны иметь именно это значение.
Ответ 2
Вы также можете ввести GrantedAuthoritiesMapper
, который был введен в 3.1 в качестве общей стратегии для изменения полномочий. Кроме того, вы можете использовать SimpleGrantedAuthority
для реализации GrantedAuthority
. В качестве альтернативы вы можете использовать перечисление, поскольку у вас есть фиксированный набор значений:
enum MyAuthority implements GrantedAuthority {
ROLE_ADMIN,
ROLE_USER;
public String getAuthority() {
return name();
}
}
class MyAuthoritiesMapper implements GrantedAuthoritiesMapper {
public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
Set<MyAuthority> roles = EnumSet.noneOf(MyAuthority.class);
for (GrantedAuthority a: authorities) {
if ("MY ADMIN GROUP".equals(a.getAuthority())) {
roles.add(MyAuthority.ROLE_ADMIN);
} else if ("MY USER GROUP".equals(a.getAuthority())) {
roles.add(MyAuthority.ROLE_USER);
}
}
return roles;
}
}