spring-security Spring Security 5.7.2 -外部LDAP服务器-抛出BadCredentialsException

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

使用案例:

我将Sping Boot 升级到版本2.7.2,将Spring Security升级到版本5.7.2
我在SecurityConfiguration配置类中配置了外部LDAP服务器(通过LdapPasswordComparisonAuthenticationManagerFactory类)。

问题:

“错误凭证例外:在Sping Boot 应用程序启动期间抛出“凭据错误”。

zu0ti5jz

zu0ti5jz1#

解决方案(对我有效):

  • pom.xml文件 *
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
  <version>2.7.2</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-data</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.ldap</groupId>
  <artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-ldap</artifactId>
</dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-ldap</artifactId>
</dependency>
  • 安全配置.java*
package com.example.app.config;

// imports

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration
{

    private final Logger log = LoggerFactory.getLogger(SecurityConfiguration.class);

    private final TokenProvider tokenProvider;

    private final CorsFilter corsFilter;

    private final LdapConfiguration ldapConfiguration;

    private final SecurityProblemSupport securityProblemSupport;

    public SecurityConfiguration(
        TokenProvider tokenProvider,
        CorsFilter corsFilter,
        LdapConfiguration ldapConfiguration,
        SecurityProblemSupport securityProblemSupport
    ) {
        this.tokenProvider = tokenProvider;
        this.corsFilter = corsFilter;
        this.ldapConfiguration = ldapConfiguration;
        this.securityProblemSupport = securityProblemSupport;
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring()
            .antMatchers(HttpMethod.OPTIONS, "/**")
//            ...
            .antMatchers("/content/**");
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
            .exceptionHandling()
            .authenticationEntryPoint(securityProblemSupport)
            .and()
            .csrf()
            .disable()
            .headers()
            .frameOptions()
            .disable()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
//            .antMatchers(HttpMethod.GET,"...")
//            .permitAll()
//            ...
            .and()
            .apply(securityConfigurerAdapter());

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(BaseLdapPathContextSource contextSource, LdapAuthoritiesPopulator authorities) throws AuthenticationException {
        LdapPasswordComparisonAuthenticationManagerFactory factory =
            new LdapPasswordComparisonAuthenticationManagerFactory(contextSource, new LdapShaPasswordEncoder());

        factory.setUserDnPatterns(ldapConfiguration.getUserDnPatterns());
        factory.setPasswordAttribute(ldapConfiguration.getPasswordAttribute());
        factory.setUserDetailsContextMapper(userDetailsContextMapper());
        factory.setLdapAuthoritiesPopulator(authorities);
        factory.setContextSource(contextSource);

        return factory.createAuthenticationManager();
    }

    @Bean
    LdapAuthoritiesPopulator ldapAuthoritiesPopulator() {
        String groupSearchBase = ldapConfiguration.getGroupSearchBase();

        DefaultLdapAuthoritiesPopulator authorities =
            new NestedLdapAuthoritiesPopulator(contextSource(), groupSearchBase);
        authorities.setGroupSearchFilter(ldapConfiguration.getGroupSearchFilter());

        return authorities;
    }

    @Bean
    @ConditionalOnMissingBean
    public ContextSource contextSource() {
        LdapContextSource source = new DefaultSpringSecurityContextSource(ldapConfiguration.getUrl());
        source.setUserDn(ldapConfiguration.getManagerDn());
        source.setPassword(ldapConfiguration.getManagerPw());

        return source;
    }

    @Bean
    public UserDetailsContextMapper userDetailsContextMapper() {
        return new LdapUserDetailsMapper()
        {
            @Override
            public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
//                ...
            }
        };
    }

    private JWTConfigurer securityConfigurerAdapter() {
        return new JWTConfigurer(tokenProvider);
    }

}
  • 应用程序集成.yml*
...
spring:
  ldap:
    urls: ldaps://external-ldapserver-uri.com:636
    base: ou=ExtranetUser,dc=domain,dc=com
    username: cn=admin,dc=domain,dc=com
    password: <password>

...

ldap:
  url: ldaps://external-ldapserver-uri.com:636
  urlPath: dc=domain,dc=com
  passwordAttribute: userPassword
  groupSearchFilter: member={0}
  groupSearchBase: ou=ExtranetUser
  userDnPatterns: cn={0},ou=ExtranetUser
  managerDn: cn=admin,dc=domain,dc=com
  managerPw: <password>

相关问题