【发布时间】:2011-08-31 15:20:13
【问题描述】:
我是 Spring Security 的新手。在我的应用程序中,身份验证是通过Ldap 完成的。经过 Ldap 身份验证后,我想在登录时处理失败和成功事件。我想跟踪数据库中的登录计数以获取锁定功能。
任何机构都知道如何实现这一目标?
【问题讨论】:
标签: java ldap spring-security
我是 Spring Security 的新手。在我的应用程序中,身份验证是通过Ldap 完成的。经过 Ldap 身份验证后,我想在登录时处理失败和成功事件。我想跟踪数据库中的登录计数以获取锁定功能。
任何机构都知道如何实现这一目标?
【问题讨论】:
标签: java ldap spring-security
身份验证由 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/
【讨论】:
AuthenticationFailureBadCredentials 事件之后,如何将页面重定向到带有锁定帐户消息的登录页面?
AuthenticationProcessingFilter 并覆盖函数onUnsuccessfulAuthentication 在这里您是否有一个request 对象,您可以在其中将一些属性放入(request.getSession().setAttribute("locked",true)。在一个简单的 JSP 中,您可以读取此属性并显示一些消息。如果您需要示例,请告诉我...
什么锁定功能?您是否知道 LDAP 密码策略扩展,它为您管理各种类似的东西?例如多次登录失败后锁定、密码过期/锁定/强制重置、密码质量策略、...
【讨论】: