Spring Security LDAP空密码校验问题技术咨询
实现Spring Security LDAP空密码检查功能
你目前是用ActiveDirectoryLdapAuthenticationProvider配置AD LDAP认证,要实现空密码检查,有两种实用的方案可以选:
方案一:前置过滤器提前拦截
在请求进入LDAP认证流程前,通过自定义过滤器先检查密码是否为空,直接阻断无效请求:
import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class EmptyPasswordCheckFilter extends UsernamePasswordAuthenticationFilter { @Override protected String obtainPassword(HttpServletRequest request) { String password = super.obtainPassword(request); if (password == null || password.trim().isEmpty()) { throw new AuthenticationServiceException("密码不能为空"); } return password; } }
接着在Spring Security配置类里替换默认的过滤器:
@Override protected void configure(HttpSecurity http) throws Exception { http .addFilterBefore(new EmptyPasswordCheckFilter(), UsernamePasswordAuthenticationFilter.class) // 保留你原有的其他配置 .authenticationProvider(activeDirectoryLdapAuthenticationProvider()); }
方案二:包装LDAP Provider在认证环节检查
如果想在认证提供者层面处理,可以包装现有的ActiveDirectoryLdapAuthenticationProvider,在调用实际认证逻辑前先做空密码校验:
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; public class EmptyPasswordCheckingLdapProvider implements AuthenticationProvider { private final AuthenticationProvider delegateProvider; public EmptyPasswordCheckingLdapProvider(AuthenticationProvider delegateProvider) { this.delegateProvider = delegateProvider; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String password = (String) authentication.getCredentials(); if (password == null || password.trim().isEmpty()) { throw new BadCredentialsException("密码不能为空"); } return delegateProvider.authenticate(authentication); } @Override public boolean supports(Class<?> authentication) { return delegateProvider.supports(authentication); } }
然后修改你原有的configure(AuthenticationManagerBuilder auth)方法:
@Override public void configure(AuthenticationManagerBuilder auth) throws Exception { String domain = customProperties.getAdDomain(); String url = customProperties.getAdUrl(); ActiveDirectoryLdapAuthenticationProvider ldapProvider = new ActiveDirectoryLdapAuthenticationProvider(domain,url); ldapProvider.setConvertSubErrorCodesToExceptions(true); ldapProvider.setUseAuthenticationRequestCredentials(true); ldapProvider.setUserDetailsContextMapper(userDetailsContextMapper); // 补全你原本的UserDetailsContextMapper配置 // 用自定义Provider包装原有LDAP Provider,添加空密码检查 auth.authenticationProvider(new EmptyPasswordCheckingLdapProvider(ldapProvider)); }
小提示
- 过滤器方案拦截时机更早,能减少后续不必要的流程开销;Provider方案更贴合Spring Security的认证链逻辑,适合需要和其他认证环节联动的场景。
- 抛出的异常可以根据业务需求调整,比如用自定义异常类,方便后续统一处理异常提示信息。
内容的提问来源于stack exchange,提问作者Алексей Мокрев




