如何在 Spring Security 中阻止 LDAP 用户帐户而不锁定 LDAP 用户?

Posted

技术标签:

【中文标题】如何在 Spring Security 中阻止 LDAP 用户帐户而不锁定 LDAP 用户?【英文标题】:How to block LDAP user account in spring security without locking the LDAP user? 【发布时间】:2011-08-31 15:20:13 【问题描述】:

我是 Spring Security 的新手。在我的应用程序中,身份验证是通过Ldap 完成的。经过 Ldap 身份验证后,我想在登录时处理失败和成功事件。我想跟踪数据库中的登录计数以获取锁定功能。 任何机构都知道如何实现这一目标?

【问题讨论】:

【参考方案1】:

身份验证由 LDAP 完成,但您希望在登录后锁定 ldap 用户。

如果您使用 spring 2.5,您可以自定义实现 InitializingBean 并检查主体是否是 LDAP 用户:

public abstract class EventListener implements InitializingBean 

Log log = LogFactory.getLog(this.getClass());

EventDispatcher eventDispatcher;

// Spring will call this method after auto-
// wiring is complete.
public void afterPropertiesSet() throws Exception 
    // let us register this instance with
    // event dispatcher
    eventDispatcher.registerListener(this);


/**
 * Implementation of this method checks whether the given event can be
 * handled in this class. This method will be called by the event
 * dispatcher.
 * 
 * @param event
 *            the event to handle
 * @return true if the implementing subclass can handle the event
 */
public abstract boolean canHandle(Object event);

/**
 * This method is executed by the event dispatcher with the event object.
 * 
 * @param event
 *            the event to handle
 */
public abstract void handle(Object event);

public void setEventDispatcher(EventDispatcher eventDispatcher) 
    this.eventDispatcher = eventDispatcher;


接下来在你的 loginFailureEventListener 上实现这个自定义句柄(在你的 xml 中映射这个监听器)

        public class LoginSuccessEventlistener extends EventListener   

    @Override  
    public boolean canHandle(Object event)   
        return event instanceof AuthenticationFailureBadCredentialsEvent;
      

    @Override  
    public void handle(Object event) 
AuthenticationFailureBadCredentialsEvent loginFailureEvent = (AuthenticationFailureBadCredentialsEvent) event;
        Object name = loginFailureEvent.getAuthentication().getPrincipal();

        if(principal instanceof org.springframework.security.userdetails.ldap.LdapUserDetailsImpl)
            out.("LDAPUser: " + user.getUsername() + " failed login");
//do you thing here
        
        

在 XML 中绑定:

<b:bean id="loginFailureEventListener" class="com.foo.bar.support.event.LoginFailureEventListener">
    <b:property name="eventDispatcher" ref="eventDispatcher"/>
</b:bean>

编辑: 您可以扩展 AuthenticationProcessingFilter 并覆盖 onUnsuccessfulAuthentication 方法:

public class CustomAuthenticationProcessingFilter extends AuthenticationProcessingFilter 
    private LoginDao loginDao;

    @Override
    protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException 
        super.onSuccessfulAuthentication(request, response, authResult);    
        request.getSession().setAttribute("wrong", -1); 
    

    protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException 
        super.onUnsuccessfulAuthentication(request, response, authException);
        String username = (String) authException.getAuthentication().getPrincipal();
        if(username.length() > 0)
            Login login = loginDao.read(username);
            if(login != null)
                request.getSession().setAttribute("wrong", login.getFailedLoginAttempts());
                request.getSession().setAttribute("attempts", Login.MAX_FAILED_LOGIN_ATTEMPTS);
            else
                request.getSession().setAttribute("wrong", 100);
            
        else
            request.getSession().setAttribute("wrong", -1);
        
    

    public void setLoginDao(LoginDao loginDao) 
        this.loginDao = loginDao;
    

在 XML 中合并:

<!-- Custom AuthenticationProcessingFilter with Callbacks -->
<authentication-manager alias="authenticationManagerAlias"/>
<b:bean id="authenticationProcessingFilter" name="authenticationProcessingFilter" class="com.foo.bat.support.event.CustomAuthenticationProcessingFilter"> 
    <b:property name="authenticationManager" ref="authenticationManagerAlias"/>
    <b:property name="authenticationFailureUrl" value="/login.do"/>
    <b:property name="filterProcessesUrl" value="/j_spring_security_check"/>
    <b:property name="defaultTargetUrl" value="/index.html"/>
    <!-- loginDao is a HibernateDao that reads logins an write wrong attempts to DB -->
    <b:property name="loginDao"><b:ref bean="loginDao"/></b:property>
    <custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />          
</b:bean>

现在您可以将此过滤器放入您的 filterChainProxy 中

在这里寻找灵感 http://www.harinair.com/2010/02/spring-acegi-security-account-lockout/

【讨论】:

@Michel:感谢您的建议。我想在数据库中使用 loginCounter 来跟踪登录尝试。一旦用户尝试进行身份验证,就会增加计数器。用户成功验证后将计数器重置为 0。那么在AuthenticationFailureBadCredentials 事件之后,如何将页面重定向到带有锁定帐户消息的登录页面? @amit31 我认为您需要查看自定义AuthenticationProcessingFilter 并覆盖函数onUnsuccessfulAuthentication 在这里您是否有一个request 对象,您可以在其中将一些属性放入(request.getSession().setAttribute("locked",true)。在一个简单的 JSP 中,您可以读取此属性并显示一些消息。如果您需要示例,请告诉我... @Michel:抱歉回复晚了。我对这一切都不熟悉。您能否提供示例,以便我更好地理解它。 @amit31 在我的回答中添加一个例子 @Michel:我不想锁定 ldap 用户。我想使用数据库锁定用户。在我们的应用程序中,身份验证是通过 ldap 完成的。在 ldap 之后,它从表中检索 userdetails 数据。所以在 ldap 身份验证失败或成功后,我正在检查数据库中的锁定计数器。如果 logincounter > 5 那么我想在登录页面上将消息显示为锁定的用户帐户。那么我应该在我的代码中在哪里添加“AuthenticationProcessingFilter”?【参考方案2】:

什么锁定功能?您是否知道 LDAP 密码策略扩展,它为您管理各种类似的东西?例如多次登录失败后锁定、密码过期/锁定/强制重置、密码质量策略、...

【讨论】:

@EJP,感谢您的建议,基本上我想使用数据库锁定帐户。我不想通过 ldap 锁定帐户。我的方法是可以使用数据库中的计数器跟踪登录尝试。一旦用户尝试进行身份验证,就增加计数器。用户成功验证后将计数器重置为 0。所以最初使用 ldap 检查用户和密码。通过 ldap 完成身份验证(失败或成功)后,我想在数据库中设置计数器并在五个失败项目锁定用户帐户后。那么在 ldap 身份验证完成后,我该如何处理锁定功能? @amit31 为什么要自己做? LDAP 将完成所有这些,而无需您编写一行代码。 @EJP 我认为他不想锁定整个 LDAP 用户,而只是锁定他的应用程序。这可能是通过 LDAP(通过阻止某些请求?)还是通过阻止 LDAP 用户的某些角色(组)来完成? @michel 没有证据证明这个猜想,这将是糟糕的安全实践。 @michel: @EJB : 是否可以在 ldap 身份验证之前添加一些过滤器?所以最初它会过滤并检查 loginitems 是否大于 5。如果登录项大于 5 则不进入 ldap 身份验证,如果登录项小于 5 则进入 Ldap 身份验证。

以上是关于如何在 Spring Security 中阻止 LDAP 用户帐户而不锁定 LDAP 用户?的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止 Spring Security 创建新会话?

Spring boot + spring security - 如何阻止应用层上的CORS请求?

在 Struts 2 中上传被 Spring Security 阻止的文件

Spring-security 阻止匿名用户从 MongoDB 中提取数据

如何在 Spring Web App 中临时禁用 Spring Security

如何在 Spring Security 过滤器中授权 CORS