如何在spring-security 5.7中配置ldap同时保留基本表单登录

jgovgodb  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(206)

我试图将我的webSecurity配置为使用ldap和基本身份验证(jdbc),并使用新的基于组件的安全配置(没有WebSecurityConfigurerAdapter),但我无法让它同时使用这两种方法。
所需的结果是spring首先尝试ldap,如果没有找到(或者只是暂时失败就足够了),尝试使用基本的身份验证登录。
该项目是从较早的Spring-Boot版本迁移而来的,使用WebSecurityConfigurerAdapter时,以下代码起作用:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.authorizeRequests().antMatchers("/services/**").permitAll().anyRequest().authenticated();
        http.httpBasic();
        http.formLogin().permitAll().loginPage("/login").defaultSuccessUrl("/customer/overview", true);
        http.logout().permitAll();

        http.csrf().disable();
        http.headers().frameOptions().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.userDetailsService(userDetails);

        //@formatter:off
        auth.ldapAuthentication()
            .userSearchFilter("(uid={0})")
            .userSearchBase("ou=people")
            .groupSearchFilter("(uniqueMember={0})")
            .groupSearchBase("ou=groups")
            .groupRoleAttribute("cn")
            .rolePrefix("ROLE_")
            .userDetailsContextMapper(customLdapUserDetailsContextMapper())
            .contextSource()
            .url(ldapUrl);
        //@formatter:on
    }

    @Bean
    CustomLdapUserDetailsContextMapper customLdapUserDetailsContextMapper()
    {
        CustomLdapUserDetailsContextMapper mapper = new CustomLdapUserDetailsContextMapper();
        mapper.setCustomUserDetailsService(userDetailsService());

        return mapper;
    }
    //Implementation of custom contextMapper is not relevant for example i believe, basicly it maps some ldap roles, but for testing i don't use roles yet
}

这是我转换到新风格的样子:

@Configuration
public class WebSecurityConfig
{
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager ldapAuthenticationManager) throws Exception
    {

        // @formatter:off
        http.authorizeRequests()
            .mvcMatchers("/services/**").permitAll()
            .mvcMatchers("/resources/**").permitAll()
            .mvcMatchers("/webjars/**").permitAll()
            .anyRequest().authenticated();
        http.httpBasic();
        http.formLogin().permitAll().loginPage("/login").defaultSuccessUrl("/customer/overview", true);
        http.logout().permitAll();

        http.csrf().disable();

        http.authenticationManager(ldapAuthenticationManager); //THIS LINE SEEMS TO BE PROBLEMATIC
        // @formatter:on

        return http.build();
    }

    @Bean
    public AuthenticationManager ldapAuthenticationManager(BaseLdapPathContextSource ldapContextSource, UserDetailsService userDetailsService)
    {
        LdapBindAuthenticationManagerFactory factory = new LdapBindAuthenticationManagerFactory(ldapContextSource);

        UserDetailsServiceLdapAuthoritiesPopulator ldapAuthoritiesPopulator = new UserDetailsServiceLdapAuthoritiesPopulator(userDetailsService);

        factory.setUserSearchFilter("(uid={0})");
        factory.setUserSearchBase("ou=people");
        factory.setLdapAuthoritiesPopulator(ldapAuthoritiesPopulator);

        return factory.createAuthenticationManager();
    }
}

当在上面的新代码中启用http.authenticationManager(ldapAuthenticationManager);行时,ldap登录可以正常工作(甚至可以绑定数据库用户的角色),但基本登录不工作。然而,当禁用该行时,基本登录可以工作,但ldap不工作。
如果您对如何让Spring使用这两种登录方式有任何帮助,我们将不胜感激。

zqdjd7g9

zqdjd7g91#

您可以创建将用于LDAP身份验证的AuthenticationProvider,而不是创建自定义AuthenticationManager
您可以在HttpSecurity上配置提供程序:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, LdapAuthenticator authenticator) throws Exception {
    // ...
    http.authenticationProvider(
            new LdapAuthenticationProvider(authenticator, ldapAuthoritiesPopulator));
    // ...
    return http.build();
}

@Bean
BindAuthenticator authenticator(BaseLdapPathContextSource contextSource) {
    BindAuthenticator authenticator = new BindAuthenticator(contextSource);
    authenticator.setUserSearch(
            new FilterBasedLdapUserSearch("ou=people", "(uid={0})", contextSource));
    return authenticator;
}

相关问题