Spring Security对接Active Directory正确凭据登录无日志失败问题
问题描述
我是Spring Security初学者,目前正在尝试对接Active Directory,普通用户登录场景下遇到两个异常现象:
- 使用
username@domain.com格式账号搭配正确密码登录时,无任何认证相关调试日志输出,直接重定向到/login?error登录失败页面; - 使用相同账号搭配随机错误密码登录时,可正常返回预期错误信息:
[nio-8080-exec-4] ctiveDirectoryLdapAuthenticationProvider : Authentication for username@domain.com failed:javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090439, comment: AcceptSecurityContext error, data 52e, v4563 ]
已知错误码52e代表用户名存在、密码错误,符合密码错误场景的预期校验逻辑。
核心疑问:为何使用正确的用户名密码组合登录时无任何相关报错日志、直接登录失败?
现有配置
当前认证配置代码如下,已尝试注释中列出的两种searchFilter配置,均未改变上述异常表现:
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { ActiveDirectoryLdapAuthenticationProvider adProvider = new ActiveDirectoryLdapAuthenticationProvider(null, "ldap://10.100.2.11:389"); adProvider.setConvertSubErrorCodesToExceptions(true); adProvider.setUseAuthenticationRequestCredentials(true); //adProvider.setSearchFilter("(&(objectClass=user)(sAMAccountName={0}))"); // adProvider.setSearchFilter("(|" + // "(&(objectClass=user)(userPrincipalName={0}))" + // "(&(objectClass=user)(samAccountName={1}))" + // ")"); auth.authenticationProvider(adProvider); auth.eraseCredentials(false); }
使用正确凭据登录时输出的调试日志如下:
2022-07-08 10:56:14.066 DEBUG 4416 --- [nio-8080-exec-7] o.s.security.web.FilterChainProxy : Securing POST /login 2022-07-08 10:56:14.067 DEBUG 4416 --- [nio-8080-exec-7] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext 2022-07-08 10:56:14.196 DEBUG 4416 --- [nio-8080-exec-7] o.s.s.web.DefaultRedirectStrategy : Redirecting to /login?error 2022-07-08 10:56:14.197 DEBUG 4416 --- [nio-8080-exec-7] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext 2022-07-08 10:56:14.197 DEBUG 4416 --- [nio-8080-exec-7] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext 2022-07-08 10:56:14.197 DEBUG 4416 --- [nio-8080-exec-7] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request 2022-07-08 10:56:14.202 DEBUG 4416 --- [nio-8080-exec-8] o.s.security.web.FilterChainProxy : Securing GET /login?error 2022-07-08 10:56:14.203 DEBUG 4416 --- [nio-8080-exec-8] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext 2022-07-08 10:56:14.203 DEBUG 4416 --- [nio-8080-exec-8] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext 2022-07-08 10:56:14.203 DEBUG 4416 --- [nio-8080-exec-8] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext 2022-07-08 10:56:14.204 DEBUG 4416 --- [nio-8080-exec-8] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
根因分析
问题核心出在ActiveDirectoryLdapAuthenticationProvider构造函数的第一个参数传了null:
- 错误密码场景下,认证流程在第一步AD账号绑定阶段就直接失败,抛出认证异常并打印日志,根本不会走到后续逻辑,所以能看到明确的LDAP 49错误日志。
- 正确密码场景下,AD账号绑定可以正常通过,但后续需要搜索用户属性、加载用户权限时,由于构造时传入的domain参数为
null,Provider无法自动拼接出正确的用户搜索根DN(正常传入域名如domain.com时,会自动生成DC=domain,DC=com作为搜索根),默认会从AD目录的根路径开始搜索。普通AD账号默认没有权限读取AD根目录信息,会触发搜索失败,该异常发生在绑定成功后的用户加载环节,默认DEBUG日志级别下不会打印具体错误信息,最终直接判定认证失败跳转错误页,表现为无相关报错日志直接登录失败。 - 之前尝试的自定义
searchFilter不生效有两个原因:一是搜索根路径错误的问题没有解决,二是ActiveDirectoryLdapAuthenticationProvider的搜索过滤器仅支持{0}作为用户名占位符,配置中出现的{1}占位符是无效参数。
解决方案
- 核心修复:将构造函数的第一个参数从
null替换为实际的AD域名,和登录账号@后缀保持一致即可,示例:
ActiveDirectoryLdapAuthenticationProvider adProvider = new ActiveDirectoryLdapAuthenticationProvider( "domain.com", // 替换为实际AD域名 "ldap://10.100.2.11:389" );
- 如果AD用户不在域默认根路径下,可额外调用
setSearchBase()方法指定用户搜索的起始DN,例如用户都存放在OU=员工,DC=domain,DC=com路径下时,添加配置:
adProvider.setSearchBase("OU=员工,DC=domain,DC=com");
- 非必要不需要自定义
searchFilter,默认过滤器已经支持username@domain.com格式的账号登录,如果确实需要自定义,仅保留{0}作为用户名占位符即可。 - 如果调整配置后仍有问题,可以将
org.springframework.security.ldap包的日志级别调整为TRACE,即可看到绑定成功后用户搜索环节的具体报错信息,方便进一步定位。
内容的提问来源于stack exchange,提问作者Manning
相关产品推荐
相关产品推荐

