在 Spring Boot 的 LDAP 身份验证中使用 sAMAccountName 而不是 userPrincipalName

Use sAMAccountName instead of userPrincipalName in LDAP auth in Spring Boot

所以我使用下面的代码在我的 spring 启动应用程序中连接到我们的 LDAP 服务器,我可以使用 userPrincipalName -> (LastName.FirstName@enterprise.com), 但我想改用分配的 sAMAccountName (ID00001).

我通过以下方式弄乱了 setSearchFilter:provider.setSearchFilter("(sAMAccountName ={0})")

但它不起作用。 (我的凭据很差)

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/myapplication")
            .authorizeRequests()
            .anyRequest().fullyAuthenticated()
            .and()
            .httpBasic();
    }

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

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
    }
    @Bean
    public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("", "ldap://test.enterprise.com","dc=ORG1, dc=ORG2");
        provider.setConvertSubErrorCodesToExceptions(true);
        provider.setUseAuthenticationRequestCredentials(true);
        provider.setSearchFilter("(sAMAccountName={0})"); // THIS DOES NOT WORK
        provider.setSearchFilter("(userPrincipalName={0})"); // THIS WORKS
        return provider;
    }
}

编辑:好的,原来我使用了错误的字段,还有另一个字段:sAMAccountName 具有与我应该使用的相同的值,更新了标题和问题内容。

编辑:

好的,我试过了:

provider.setSearchFilter("(&(objectClass=user)(cn={0}))");
provider.setSearchFilter("(&(objectClass=user)(sAMAccountName={0}))");
provider.setSearchFilter("(&(objectClass=user)(cn={1}))");
provider.setSearchFilter("(&(objectClass=user)(sAMAccountName={1}))");

还是一样的错误,

凭据错误,AcceptSecurityContextError,52e v2580

我设法解决了我的问题,但我没有使用 spring ldap 依赖项,而是创建了一个实现 AuthenticationProvider 的自定义身份验证提供程序,并使用以下代码连接到 ldap 并验证凭据:

将其自动连接到 WebSecurityConfig class。


@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
   
   
   @Autowired
   private UserDetails userDetails;
   
    @Override
    public Authentication authenticate(Authentication auth) throws 
    AuthenticationException {
        String user = authentication.getName();
        String pass = authentication.getCredentials.ToString();

        try {
            if (isRegistrered(user,pass) {
                return new UsernamePasswordAuthenticationToken(user,pass, new 
                ArrayList<>());
            } else {
                return null;
            }
        } catch (Exception e) {
          e.printStackTrace();
        }


    }

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

    private isRegisterd(String user, String pass) {
        boolean result = false;
        try {
            // Set up the environment for creating the initial context
            Hashtable<String, String> env = new Hashtable<String, String>();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, "ldap://ldap_server:389");
            // 
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            env.put(Context.SECURITY_PRINCIPAL, "DOMAIN\USER"); 
            env.put(Context.SECURITY_CREDENTIALS, "PASSWORD");

            // Create the initial context

            DirContext ctx = new InitialDirContext(env);

            if(ctx != null) {
                ctx.close();
            }

            return result;
        } catch (Exception e) {           
            return result;
        }
    }
    
    
    private void retrieveUserDetails(DirContext ctx, String username) throws NamingException {
        String userSearchBase = "dc=TEST,dc=SAMPLE";
        String userSearchFilter = String.format("sAMAccountName=%s", username);
        
        //any attributes that you want
        String[] attributes = { "sAMAccountName", "department" };
        SearchControls controls = new SearchControls();
        controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        controls.setReturningAttributes(attributes);
        SearchResult result = null;
        NamingEnumeration<?> users = ctx.search(userSearchBase, userSearchFilter, controls);
        
        while(users.hasmore()) {
            result = (SearchResult) users.next();
            Attributes attr = result.getAttribtutes();
            String sAMAccountName = attr.get("sAMAccountName").get(0).toString();
            String department = attr.get("department").get(0).toString();
            
            //assign to autowired object to be accessed anywhere
            this.userDetails.setAccountName(sAMAccountName);
            this.userDetails.setDepartment(department);     
        }       
    }
}