如何使用Spring Security和ActiveDirectoryLdapAuthenticationProvider的自定义权限填充器?

f45qwnt8  于 2023-08-02  发布在  Spring
关注(0)|答案(2)|浏览(79)

我已经成功地通过LDAP连接到Active Directory进行身份验证,并在ldap.xml中调用了自定义权限填充器:

<bean id="ldapAuthenticationProvider"
        class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <constructor-arg ref="ldapBindAuthenticator"/>
    <constructor-arg ref="ldapAuthoritiesPopulator"/>
</bean>

<bean id="ldapBindAuthenticator"
        class="org.springframework.security.ldap.authentication.BindAuthenticator">
    <constructor-arg ref="ldapServer"/>
    <property name="userSearch" ref="ldapSearch"/>
</bean>

<bean id="ldapSearch"
        class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <constructor-arg value="CN=Users"/>
    <constructor-arg value="(sAMAccountName={0})"/>
    <constructor-arg ref="ldapServer"/>
</bean>

<bean id="ldapAuthoritiesPopulator"
        class="my.project.package.ActiveDirectoryLdapAuthoritiesPopulator"/>

<bean id="ldapServer"
        class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <constructor-arg value="ldap://192.168.0.2/dc=test,dc=server"/>

    <property name="userDn" value="ldap@test.server"/>
    <property name="password" value="ldap"/>
    <property name="baseEnvironmentProperties">
        <map>
            <entry key="java.naming.referral">
                <value>follow</value>
            </entry>
        </map>
    </property>
</bean>

字符串
这很好用,我可以根据用户的组成员身份确定她的授权,但我更愿意通过内置的Active Directory LDAP身份验证提供程序来完成这一点:

<bean id="ldapAuthenticationProvider"
        class="org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider">

        <constructor-arg value="test.server"/>
        <constructor-arg value="ldap://192.168.0.2:389"/>
        <property name="convertSubErrorCodesToExceptions" value="true"/>
</bean>


上面的问题是,我的自定义权限填充器(显然)没有被调用,所以虽然我可以对我的用户进行身份验证(这与上面的工作),但我没有组(我需要确定授权)。
我觉得这是一个简单的问题,但对于我的生活,我无法在这里或其他任何地方找到答案。我是否必须扩展ActiveDirectoryLdapAuthenticationProvider类,并从那里调用我的权限填充器?
(感谢所有的帮助这个网站给了我几年运行;这个网站的有效性可以通过我最近才创建一个帐户来衡量,这是我的第一个问题。提前感谢您的帮助。)

ygya80vv

ygya80vv1#

Spring的ActiveDirectoryLdapAuthenticationProvider类是final,所以我唯一的真实的选择(如果有人愿意的话,我会考虑更好的选择)是fork这个类。我复制并粘贴了它的内容,稍微重构了一下,并删除了final名称。然后,我创建了forked类的一个单独的子类,覆盖了loadUserAuthorities()方法,并添加了自己的代码来构建权限掩码。
然后,我可以编辑我的ldap.xml文件,如下所示:

<bean id="ldapAuthenticationProvider"
            class="my.project.package.OverrideActiveDirectoryLdapAuthenticationProvider">   
        <constructor-arg value="test.server"/>
        <constructor-arg value="ldap://192.168.0.2:389"/>
        <property name="convertSubErrorCodesToExceptions" value="true"/>
</bean>

字符串
对于像我这样的任何其他n00b,子类看起来像这样:

public class OverrideActiveDirectoryLdapAuthenticationProvider extends TestActiveDirectoryLdapAuthenticationProvider {

//my assignments

public OverrideActiveDirectoryLdapAuthenticationProvider(String domain,
        String url) {
    super(domain, url);
}

@Override
protected Collection<? extends GrantedAuthority> loadUserAuthorities(DirContextOperations userData, String username, String password) {
//original code with my own additions
//in my case, I injected code into the for(group : groups) loop
}


效果很好。
非常感谢zagyi的帮助。

dsekswqp

dsekswqp2#

由于类ActiveDirectoryLdapAuthenticationProvider是final的,不能扩展,所以我编写了自己的AuthenticationProvider类,它接受ActiveDirectoryLdapAuthenticationProvider作为参数,并将其用作实际的身份验证。身份验证后,我将现有权限Map到我自己的权限。
AuthenticationProvider类:

public class AuthorityMappingActiveDirectoryLdapAuthenticationProvider implements AuthenticationProvider {

    private final ActiveDirectoryLdapAuthenticationProvider provider;

    private Function<Collection<? extends GrantedAuthority>, Collection<? extends GrantedAuthority>> authorityMapper;

    public AuthorityMappingActiveDirectoryLdapAuthenticationProvider(ActiveDirectoryLdapAuthenticationProvider provider) {
        this(provider, null);
    }

    public AuthorityMappingActiveDirectoryLdapAuthenticationProvider(ActiveDirectoryLdapAuthenticationProvider provider,
        Function<Collection<? extends GrantedAuthority>, Collection<? extends GrantedAuthority>> authorityMapper) {
        this.provider = provider;
        this.authorityMapper = authorityMapper;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Authentication auth = provider.authenticate(authentication);
        if (authorityMapper == null) {
            return auth;
        }
        Collection<? extends GrantedAuthority> authorities = authorityMapper.apply(auth.getAuthorities());
        return UsernamePasswordAuthenticationToken.authenticated(auth.getPrincipal(), auth.getCredentials(), authorities);
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return provider.supports(authentication);
    }
}

字符串
使用情况

@Bean
public AuthenticationProvider ldapAuthenticationProvider() {
    return new AuthorityMappingActiveDirectoryLdapAuthenticationProvider(
        new ActiveDirectoryLdapAuthenticationProvider(domain, ldapUrl, rootDn), authorities -> {
        List<GrantedAuthority> mappedAuthorities = new ArrayList<>();
        mappedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        if (mappedAuthorities.stream()
            .map(a -> a.getAuthority())
            .filter(a -> a.startsWith("SUDO_USERS"))
            .count() > 0) {
            mappedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        }
        return mappedAuthorities;
    });
}

相关问题