Java Spring Security for Active Directory Searchs by';userPrincipalName';——有没有办法改变这一点?
我仍在学习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类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- 找不到经过身份验证的用户的
@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();
}
}
所以问题就在这里(至少我认为)。。。
在我们的广告服务器中,我们有
cn,name,sAMAccountName和uid作为我们登录时使用的用户名,在我上面的示例中是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}))"
以下是我执行的单个步骤:
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});
}
...
}
@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类