1

使用 Spring Security 3.2 我已经配置了 ActiveDirectoryLdapAuthenticationProvider。我可以使用全名示例 sharon@mydomain.com 进行身份验证,但是当我尝试仅使用用户名“sharon”进行身份验证时,出现以下错误

   2015-12-21_17:07:00.752 DEBUG o.s.s.l.a.a.ActiveDirectoryLdapAuthenticationProvider - authenticate - Processing authentication request for user: sharon
    2015-12-21_17:07:00.793 DEBUG o.s.s.l.SpringSecurityLdapTemplate - searchForSingleEntryInternal - Searching for entry under DN '', base = 'dc=mydomain,dc=com', filter = '(&(objectClass=user)(userPrincipalName={0}))'
    2015-12-21_17:07:00.793 INFO  o.s.s.l.SpringSecurityLdapTemplate - searchForSingleEntryInternal - Ignoring PartialResultException
    2015-12-21_17:07:00.794 DEBUG o.s.s.l.a.LdapAuthenticationProvider - authenticate - Processing authentication request for user: gdcadmin
    2015-12-21_17:07:00.796 DEBUG o.s.s.l.a.BindAuthenticator - bindWithDn - Attempting to bind as cn=gdcadmin,cn=Users,dc=mydomain,dc=com,dc=springframework,dc=org
    2015-12-21_17:07:00.796 DEBUG o.s.s.l.DefaultSpringSecurityContextSource - setupEnvironment - Removing pooling flag for user cn=gdcadmin,cn=Users,dc=mydomain,dc=com,dc=springframework,dc=org
    2015-12-21_17:07:00.858 DEBUG o.a.m.f.codec.ProtocolCodecFilter - messageReceived - Processing a MESSAGE_RECEIVED for session 1
    2015-12-21_17:07:00.859 DEBUG o.a.d.shared.asn1.ber.Asn1Decoder - decode - >>>==========================================
.....
.....
.....
015-12-21_17:07:00.905 DEBUG o.s.s.l.a.BindAuthenticator - handleBindException - Failed to bind as cn=gdcadmin,CN=Users,DC=mydomain,DC=com: org.springframework.ldap.AuthenticationException: [LDAP: error code 49 - cannot bind the principalDn.]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - cannot bind the principalDn.]

根据弹簧安全文件:

例如,名为“Sharon”的用户将能够通过输入用户名 sharon 或完整的 Active Directory userPrincipalName(即 sharon@mydomain.com)进行身份验证

我的配置

@Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
        auth.eraseCredentials(false);
        auth.ldapAuthentication().userDnPatterns("cn={0},CN=Users,DC=mydomain,DC=com");
    }

    @Bean
    public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(env.getProperty("mydomain.com"),
                env.getProperty("ldap://hmidir01.mydomain.com:389/"));
        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);
        provider.setUserDetailsContextMapper(userDetailsContextMapper);
        return provider;
    }

我的配置有什么错误。

4

2 回答 2

1

您可以通过给定的方式实现

1)没有将数据持久化到我们的数据库中

网络安全配置.java

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter  {

    @Bean
    public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(<ldap-domain>,<ldap-url>);
            provider.setConvertSubErrorCodesToExceptions(true);
            provider.setUseAuthenticationRequestCredentials(true);
        return provider;
    }

    @Bean
    public LoggerListener loggerListener() {
        return new LoggerListener();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
            .antMatchers("/admin/**").hasAnyAuthority("ADMIN")
            .antMatchers("/user/**").hasAnyAuthority("ADMIN", "USER")
            .antMatchers("/rest/**", "/css/**", "/fonts/**", "/images/**", "/js/**").permitAll()
            .anyRequest().authenticated()
        .and()
            .formLogin()
            .loginPage("/").failureUrl("/?error").successHandler("/home").permitAll()
            .usernameParameter("emailId").passwordParameter("password")
        .and()
            .logout()
            .logoutUrl("/logout").logoutSuccessUrl("/").permitAll()
        .and()
            .exceptionHandling().accessDeniedPage("/home")
        .and()
            .csrf()
        .and()
            .httpBasic();    
    }
}

2)将数据持久化到我们的数据库中

WebSecurityConfig.java

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter  {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .authorizeRequests()
            .antMatchers("/admin/**").hasAnyAuthority("ADMIN")
            .antMatchers("/user/**").hasAnyAuthority("ADMIN", "USER")
            .antMatchers("/rest/**", "/css/**", "/fonts/**", "/images/**", "/js/**").permitAll()
            .anyRequest().authenticated()
        .and()
            .formLogin()
            .loginPage("/").failureUrl("/?error").successHandler("/home").permitAll()
            .usernameParameter("emailId").passwordParameter("password")
        .and()
            .logout()
            .logoutUrl("/logout").logoutSuccessUrl("/").permitAll()
        .and()
            .exceptionHandling().accessDeniedPage("/home")
        .and()
            .csrf()
        .and()
            .httpBasic();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)throws Exception {
        auth
    .authenticationProvider(activeDirectoryLdapAuthenticationProvider());
    }

    @Bean
    public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(<ldap-domain>(null), <ldap-url>);
        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);
        provider.setUserDetailsContextMapper(userDetailsContextMapper());
        return provider;
    }

    @Bean
    public UserDetailsContextMapper userDetailsContextMapper() {
        return new AttributesLDAPUserDetailsContextMapper();
    }
}

属性LDAPUserDetailsContextMapper.java

    public class AttributesLDAPUserDetailsContextMapper implements UserDetailsContextMapper {


        @Autowired
        private UserService service;

        private InetOrgPersonContextMapper ldapUserDetailsMapper = new InetOrgPersonContextMapper();

        @Override
        public UserDetails mapUserFromContext(DirContextOperations dirContextOperations, String userName, Collection<? extends GrantedAuthority> collection) {

            InetOrgPerson userLdap = (InetOrgPerson) ldapUserDetailsMapper.mapUserFromContext(dirContextOperations, userName, collection);  

            User user = service.findOne(userLdap.getUsername());
            if (user == null) {
                user = new Usere();
                user.setName(StringUtils.defaultString(userLdap.getDisplayName()).trim());
                user.setEmailId(StringUtils.defaultString(userLdap.getUsername()).trim());
                user.setdescription(StringUtils.defaultString(userLdap.getDescription()).trim());
                user.setIsAdmin(false);
                user.setIsEmployee(true);
                service.save(user);
            }
            return new LdapSecuredUser(user);
        }

        @Override
        public void mapUserToContext(UserDetails userDetails, DirContextAdapter dirContextAdapter) {
            ldapUserDetailsMapper.mapUserToContext(userDetails, dirContextAdapter);
        }
    }

LdapSecuredUser.java

public class LdapSecuredUser extends User implements LdapUserDetails {

    private static final long serialVersionUID = -8997460180274787521L;

    public LdapSecuredUser(User user) {
        if (user != null) {
            this.setId(user.getId());
            this.setEmailId(user.getEmailId());
            this.setName(user.getName());
            this.setdescription(user.getDescription());
            this.setIsAdmin(user.getIsAdmin());
            this.setIsEmployee(user.getIsEmployee());
        }
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> authorities = new ArrayList<>(); 
        authorities.add(new SimpleGrantedAuthority("USER"));
        if(super.getIsAdmin())
            authorities.add(new SimpleGrantedAuthority("ADMIN"));   
        return authorities;
    }


    @Override
    public String getUsername() {
        return super.getEmailId();
    }

    @Override
    public String getPassword() {
        return null;
    }

    @Override
    public String getDn() {
        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }

}
于 2016-04-19T06:15:25.367 回答
0

使用spring security 5.2.1:可以使用该setSearchFilter()功能。

LDAP 身份验证过程有两个主要步骤:绑定,它使用域参数(第一个)ActiveDirectoryLdapAuthenticationProvider()来形成这样的用户名:myUser@sub.domain.com 给定凭据:username= myUser; 密码 myPassword。如果这不正确,您将收到错误的凭据错误(AcceptSecurityContext 错误,数据 52e)。

然后下一步是在 ldap 目录中找到您的用户。如果您的用户没有名为 username 的属性 = myUser@sub.domain.com,则 ldap 服务器会给您一个未找到的错误(这将作为异常在您的日志中弹出Ignoring PartialResultExceptionUsernameNotFoundException: User myUser not found in directory.为此,您可以使用 searchFilter 选项。提供的用户名将插入该{1}点。

 @Configuration
 @EnableWebSecurity
 @AllArgsConstructor
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception{
    http.cors().and().csrf().disable().authorizeRequests()
            .anyRequest().fullyAuthenticated().and().httpBasic(); //this will invoke an auth popup in browser
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(activeDirectoryLdapAuthenticationProvider());
    }

    @Bean
    public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
       ActiveDirectoryLdapAuthenticationProvider provider = new 
       ActiveDirectoryLdapAuthenticationProvider("sub.domain.com","ldap://url");
       provider.setSearchFilter("mailNickname={1}"); //here is the trick
       provider.setConvertSubErrorCodesToExceptions(true);
       provider.setUseAuthenticationRequestCredentials(true);

    return provider;
    }
}
于 2020-10-01T16:09:52.587 回答