我有一个针对ApacheDS配置的正常工作的Spring-LDAP实例。
非常普通的安全上下文:
<authentication-manager alias="authenticationManager">
<ldap-authentication-provider
user-context-mapper-ref="detailsMapper"
user-dn-pattern="uid={0},ou=people" user-search-filter="(uid={0})"
group-search-base="ou=groups" group-search-filter="member={0}">
</ldap-authentication-provider>
</authentication-manager>
当一个帐户被锁定时,我在调试中看到锁被确认:
DEBUG: org.springframework.security.ldap.authentication.BindAuthenticator - Failed to bind as uid=lorin,ou=people: org.springframework.ldap.AuthenticationException: [LDAP: error code 49 - INVALID_CREDENTIALS: Bind failed: account will remain locked till Sun Jun 07 22:17:01 EDT 2015]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - INVALID_CREDENTIALS: Bind failed: account will remain locked till Sun Jun 07 22:17:01 EDT 2015]
DEBUG: org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Login credentials not found
DEBUG: org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Updated SecurityContextHolder to contain null Authentication
DEBUG: org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Delegating to authentication failure handler org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler@521758c5
DEBUG: org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler - No failure URL set, sending 401 Unauthorized error
DEBUG: org.springframework.security.web.context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
DEBUG: org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
但是当异常返回到我的失败处理程序时,异常严格地是BadCredentialsException,除了我配置的消息语句之外什么也没有。
public abstract class AbstractLockDetectingAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
private final static Logger logger = LoggerFactory .getLogger(AbstractLockDetectingAuthenticationFailureHandler.class);
final protected static Locale locale = Locale.getDefault();
@Resource(name="messageSource")
private ReloadableResourceBundleMessageSource messages;
@Override
public void onAuthenticationFailure(final HttpServletRequest request,
final HttpServletResponse response, final AuthenticationException exception)
throws IOException, ServletException {
exception.printStackTrace();
super.onAuthenticationFailure(request, response, exception);
}
我如何报告一个锁定的帐户与一个坏的密码,而不必自定义一个类,然后把自己扔进配置地狱为一个消息?
(是的,我知道报告锁定或坏密码是不好的形式,因为它泄露了安全性…坚持顾客)
你可能想用以下代码重写BindAuthenticator内部的"handleBindException"方法来抛出特定的异常:
protected void handleBindException(String userDn, String username, Throwable cause) {
super.handleBindException(userDn, username, cause);
//handle account locked
if (cause.getMessage().contains("account was permanently locked"))
{
throw new LockedException(messages.getMessage(
"LdapAuthenticationProvider.locked", "User account is locked"), cause);
}
//second example: handle password lifetime reached
if (cause.getMessage().contains("password end time reached"))
{
throw new AccountExpiredException(messages.getMessage(
"LdapAuthenticationProvider.expired", "User account has expired"),
cause);
}
}
如何覆盖BindAuthenticator主要取决于你的spring版本,如果你使用spring-boot。你的代码看起来像是在使用香草spring。
由于定义您自己的authenticationprovider而不是使用xml ldap-authentication-provider-Tag bean可能非常麻烦(因为所有的子bean都需要手动定义),因此我建议在初始化的某个地方调用LdapAuthenticationProvider.setAuthenticator()来覆盖Authenticator。