如何在 Spring Boot 中为 Spring LDAP 身份验证设置覆盖 BindAuthenticator handleBindException

Posted

技术标签:

【中文标题】如何在 Spring Boot 中为 Spring LDAP 身份验证设置覆盖 BindAuthenticator handleBindException【英文标题】:How to Over ride BindAuthenticator handleBindException for Spring LDAP Authentication setup in Spring Boot 【发布时间】:2017-07-06 23:57:53 【问题描述】:

用于 Spring Boot 中的 Spring 安全设置。 LDAP 身份验证提供程序默认配置为使用 BindAuthenticator 类。

这个类包含方法

/**
* Allows subclasses to inspect the exception thrown by an attempt to bind         with a
* particular DN. The default implementation just reports the failure to     the debug
* logger.
*/
protected void handleBindException(String userDn, String username,     Throwable cause) 
if (logger.isDebugEnabled()) 
logger.debug("Failed to bind as " + userDn + ": " + cause);


此方法用于处理身份验证相关的异常,例如无效凭据。

我想覆盖此方法,以便我可以处理此问题并根据 LDAP 返回的错误代码返回正确的错误消息。如密码无效或帐户被锁定。

当前的 LDAP 实现总是返回“错误的凭据”,它不能正确说明我的凭据为何无效。我想报道这些案例

    帐户被锁定的位置 密码已过期,所以我可以重定向以更改密码 帐户因密码重试次数无效而被锁定

请帮忙

【问题讨论】:

应该...你真的想把它还给你的最终用户吗?从安全角度来看,您不想公开该信息。如果一个帐户被锁定,黑客现在知道它有一个有效的用户名。同样是你告诉他密​​码错误或者用户名不存在。 @Denium 我正在为内部应用程序构建此应用程序,只有员工可以访问 Intranet。所以这是我的产品负责人的期望:) 从安全的角度来看,这并不重要。谁说所有用户都愿意,那么心怀不满的员工呢。我可以想象您可能希望在日志中包含这些信息,但您希望对外界尽可能通用 是的。但由于许多原因,要么记录或提高对我公司内部用户的可见性。应该有一种方法来扩展它。目前在安全模式的 Spring Boot 配置中,这似乎是不可能的。 还有其他可能的用例,例如过期密码。凭证有效的地方。并且帐户已锁定,凭据再次有效。我无法捕捉这些案例。 【参考方案1】:

我通过定义 LDAP 上下文而不是使用 Spring Boot LDAPAuthenticationProviderConfigurer 解决了这个问题。

然后创建 FilterBasedLdapUserSearch 并用我的 ConnectBindAuthenticator 覆盖 BindAuthentication。

我为 Spring Boot 配置创建了一个单独的 LDAPConfiguration 类,并将所有这些自定义对象注册为 Bean。

从上面的对象中,我通过将自定义对象传递给构造函数来创建 LDAPAuthenticationProvider

配置如下

 @Bean
 public DefaultSpringSecurityContextSource contextSource() 
     DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(env.getProperty("ldap.url"));
     contextSource.setBase(env.getProperty("ldap.base"));
     contextSource.setUserDn(env.getProperty("ldap.managerDn"));
     contextSource.setPassword(env.getProperty("ldap.managerPassword"));
     return contextSource;
 

 @Bean
 public ConnectBindAuthenticator bindAuthenticator() 
     ConnectBindAuthenticator connectBindAuthenticator = new ConnectBindAuthenticator(contextSource());
     connectBindAuthenticator.setUserSearch(ldapUserSearch());
     connectBindAuthenticator.setUserDnPatterns(new String[]env.getProperty("ldap.managerDn"));
     return connectBindAuthenticator;
 

 @Bean
 public LdapUserSearch ldapUserSearch() 
     return new FilterBasedLdapUserSearch("", env.getProperty("ldap.userSearchFilter"), contextSource());
 

【讨论】:

嗨。你能解释一下你班上的 env 是什么吗?【参考方案2】:

您必须更改您的 spring 安全配置以添加您的 BindAuthenticator 扩展:

CustomBindAuthenticator.java

public class CustomBindAuthenticator extends BindAuthenticator 

    public CustomBindAuthenticator(BaseLdapPathContextSource contextSource) 
        super(contextSource);
    

    @Override
    protected void handleBindException(String userDn, String username, Throwable cause) 
        // TODO: Include here the logic of your custom BindAuthenticator
        if (somethingHappens()) 
            throw new MyCustomException("Custom error message");
        

        super.handleBindException(userDn, username, cause);
    

spring-security.xml

<beans:bean id="contextSource"
    class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
    <beans:constructor-arg value="LDAP_URL" />
    <beans:property name="userDn" value="USER_DN" />
    <beans:property name="password" value="PASSWORD" />
</beans:bean>

<beans:bean id="userSearch"
    class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <beans:constructor-arg index="0" value="USER_SEARCH_BASE" />
    <beans:constructor-arg index="1" value="USER_SEARCH_FILTER" />
    <beans:constructor-arg index="2" ref="contextSource" />
</beans:bean>

<beans:bean id="ldapAuthProvider"
    class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
    <beans:constructor-arg>
        <beans:bean class="com.your.project.CustomBindAuthenticator">
            <beans:constructor-arg ref="contextSource" />
            <beans:property name="userSearch" ref="userSearch" />
        </beans:bean>
    </beans:constructor-arg>
</beans:bean>

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="ldapAuthProvider" />
</security:authentication-manager>

希望对你有帮助。

【讨论】:

以上是关于如何在 Spring Boot 中为 Spring LDAP 身份验证设置覆盖 BindAuthenticator handleBindException的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot / Spring Data 中为 Amazon RDS Mysql 启用 SSL?

如何在 Spring-Boot 项目中为电话号码身份验证创建 REST API?

如何在 Spring Boot 中为 prometheus 制作自己的指标

如何在 Spring Boot 中为所有控制器指定前缀?

如何在 Spring Boot 中为 Camel 配置 Jackson ObjectMapper

我应该如何在 Gradle 中为 Spring Boot 应用程序设置主类?