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

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

【问题讨论】:

    标签: java ldap spring-security


    【解决方案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 身份验证。
    猜你喜欢
    • 1970-01-01
    • 2014-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多