Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring Security for Active Directory Searchs by';userPrincipalName';——有没有办法改变这一点?_Java_Spring_Spring Mvc_Spring Security_Active Directory - Fatal编程技术网

Java Spring Security for Active Directory Searchs by';userPrincipalName';——有没有办法改变这一点?

Java Spring Security for Active Directory Searchs by';userPrincipalName';——有没有办法改变这一点?,java,spring,spring-mvc,spring-security,active-directory,Java,Spring,Spring Mvc,Spring Security,Active Directory,我仍在学习LDAP/Active Directory,如果我的术语有误,请更正:) 在我们的JavaWeb应用程序中,我尝试使用SpringSecurityLDAP来保护它。我设法让Spring Security与内存中的身份验证一起工作,但我们需要将其与AD服务器绑定 我将用com.test来掩盖我们的实际域 以下是我尝试从应用程序登录时收到的错误 13:39:55701错误ActiveDirectoryLdapAuthenticationProvider:133- 找不到经过身份验证的用户的

我仍在学习LDAP/Active Directory,如果我的术语有误,请更正:)

在我们的JavaWeb应用程序中,我尝试使用SpringSecurityLDAP来保护它。我设法让Spring Security与内存中的身份验证一起工作,但我们需要将其与AD服务器绑定

我将用com.test来掩盖我们的实际域

以下是我尝试从应用程序登录时收到的错误

13:39:55701错误ActiveDirectoryLdapAuthenticationProvider:133- 找不到经过身份验证的用户的目录项:johnsmit javax.naming.NameNotFoundException:[LDAP:错误代码32-0000208D: NameErr:DSID-0310020A,问题2001(无对象),数据0,最佳匹配 of:'CN=Users,DC=ad,DC=test,DC=com'

我在Spring中使用基于类的配置 这是我的SecurityConfiguration类

@Configuration
@EnableWebMvcSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
          provider = new ActiveDirectoryLdapAuthenticationProvider("ad.test.com", "ldap://servername.ad.test.com:389/cn=Users,dc=ad,dc=test,dc=com");

        provider.setUseAuthenticationRequestCredentials(true);


        return provider;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
                authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin().failureUrl("/login?error")
                .loginPage("/login")
                .permitAll()
                .and()
                .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login")
                .permitAll()
                .and()
                .httpBasic();

    }
}
所以问题就在这里(至少我认为)。。。 在我们的广告服务器中,我们有 cnnamesAMAccountNameuid作为我们登录时使用的用户名,在我上面的示例中是johnsmit

我们的userPrincipalName(在我们的广告服务器中)是我们的电子邮件地址。smith@test.com.

我查看了这个类,它说它使用了userPrincipalName。查看代码,它显示它使用的是userPrincipalName。我检查了Spring Security的较新版本,它还没有正式上市,但它是一样的

一定有什么办法,我可以搜索的用户名为“johnsmit”而不是“john”的广告。smith@test.com“

如果搜索筛选器为
String searchFilter=“(&(objectClass=user)(sAMAccountName={0}));
这将是一个理想的情况,但我不知道这是否可以覆盖任何地方,我找不到任何文档?

我想我会用这个Jira票据回答我自己的问题


看起来它根本没有被合并。不过,这张票证中的补丁将是我需要的答案。

三年后,我也在努力解决这个问题。因为有人建议将userPrincipalName更改为Office365的邮件地址(请参阅),我想其他人也可能有这个问题,所以这是我的修复方法

有一个关于github的讨论正在讨论这个问题:

用户gkibilov的回答解决了我的问题。其想法是更改ActiveDirectoryLdapAuthenticationProvider类中的“searchForUser”方法,以便不仅仅传递bindprincipal(=USERNAME@DOMAIN)还有用户名

之后,可以使用以下searchFilter查找sAMAccountName而不是userPrincipalName:

"(&(objectClass=user)(sAMAccountName={1}))"
以下是我执行的单个步骤:

  • 复制ActiveDirectoryAuthenticationException类的源 创建一个新类并将其重命名(即“MyActiveDirectoryAuthenticationException”):

  • 复制ActiveDirectoryLdapAuthenticationProvider的源 类,并将其重命名(即 “MyActiveDirectoryLdapAuthenticationProvider”):

  • 将MyActiveDirectoryLdapAuthenticationProvider中的ActiveDirectoryAuthenticationException类与新的异常类(MyActiveDirectoryAuthenticationException)交换

  • 将MyActiveDirectoryAuthenticationException类中的方法更改为同时传递用户名:

    private DirContextOperations searchForUser(DirContext context, String username)
        throws NamingException {
         SearchControls searchControls = new SearchControls();
         searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    
         String bindPrincipal = createBindPrincipal(username);
         String searchRoot = rootDn != null ? rootDn
                 : searchRootFromPrincipal(bindPrincipal);
    
         try {
             return SpringSecurityLdapTemplate.searchForSingleEntryInternal(context,
                searchControls, searchRoot, searchFilter,
                new Object[] { bindPrincipal, username});
         }
         ...
    }
    
  • 更改searchFilter以查找sAMAccountName属性。在您的情况下,bean应如下所示:

    @Bean
    public MyActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
        provider = new MyActiveDirectoryLdapAuthenticationProvider("ad.test.com", "ldap://servername.ad.test.com:389/cn=Users,dc=ad,dc=test,dc=com");
        provider.setSearchFilter("(&(objectClass=user)(sAMAccountName={1}))");
        provider.setUseAuthenticationRequestCredentials(true);
        return provider;
    }
    

  • 我必须承认,复制一个类并不是最好的解决方案,但因为原始类是“最终的”我找不到更好的方法来解决这个问题。

    因为我发现这对解决我自己的问题非常有帮助,我想补充一点,建议的更改似乎已经被折叠到Spring Security 5.0.8.RELEASE/Spring Boot 2.0.5中

    ActiveDirectoryLdapAuthenticationProvider.setSearchFilter(字符串)
    的JavaDoc读取:

    用于搜索正在验证的用户的LDAP筛选器字符串。出现的
    {0}
    将替换为
    username@domain
    。出现的
    {1}
    仅替换为用户名

    默认设置为:
    (&(objectClass=user)(userPrincipalName={0}))

    因此,在SpringSecurity5.0.8.RELEASE中,可以使用建议的搜索过滤器更改,而无需复制任何SpringSecurity类