Add event capabilities.
This commit is contained in:
parent
42ccbfbad7
commit
d5c14142d1
|
@ -22,11 +22,18 @@ import net.sf.acegisecurity.BadCredentialsException;
|
|||
import net.sf.acegisecurity.DisabledException;
|
||||
import net.sf.acegisecurity.providers.AuthenticationProvider;
|
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureDisabledEvent;
|
||||
import net.sf.acegisecurity.providers.dao.event.AuthenticationFailurePasswordEvent;
|
||||
import net.sf.acegisecurity.providers.dao.event.AuthenticationSuccessEvent;
|
||||
import net.sf.acegisecurity.providers.encoding.PasswordEncoder;
|
||||
import net.sf.acegisecurity.providers.encoding.PlaintextPasswordEncoder;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import java.util.Date;
|
||||
|
@ -56,14 +63,23 @@ import java.util.Date;
|
|||
* <code>UsernamePasswordAuthenticationToken</code>. This avoids complications
|
||||
* if the user changes their password during the session.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* If an application context is detected (which is automatically the case when
|
||||
* the bean is started within a Spring container), application events will be
|
||||
* published to the context. See {@link
|
||||
* net.sf.acegisecurity.providers.dao.event.AuthenticationEvent} for further
|
||||
* information.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||
InitializingBean {
|
||||
InitializingBean, ApplicationContextAware {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private ApplicationContext ctx;
|
||||
private AuthenticationDao authenticationDao;
|
||||
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
|
||||
private SaltSource saltSource;
|
||||
|
@ -72,6 +88,11 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.ctx = applicationContext;
|
||||
}
|
||||
|
||||
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
|
||||
this.authenticationDao = authenticationDao;
|
||||
}
|
||||
|
@ -175,6 +196,15 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|||
throw new AuthenticationServiceException(repositoryProblem
|
||||
.getMessage(), repositoryProblem);
|
||||
}
|
||||
|
||||
if (!user.isEnabled()) {
|
||||
if (this.ctx != null) {
|
||||
ctx.publishEvent(new AuthenticationFailureDisabledEvent(
|
||||
authentication, user));
|
||||
}
|
||||
|
||||
throw new DisabledException("User is disabled");
|
||||
}
|
||||
|
||||
if (!(authentication instanceof DaoAuthenticationToken)) {
|
||||
// Must validate credentials, as this is not simply a token refresh
|
||||
|
@ -186,17 +216,22 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
|||
|
||||
if (!passwordEncoder.isPasswordValid(user.getPassword(),
|
||||
authentication.getCredentials().toString(), salt)) {
|
||||
if (this.ctx != null) {
|
||||
ctx.publishEvent(new AuthenticationFailurePasswordEvent(
|
||||
authentication, user));
|
||||
}
|
||||
|
||||
throw new BadCredentialsException("Bad credentials presented");
|
||||
}
|
||||
}
|
||||
|
||||
if (!user.isEnabled()) {
|
||||
throw new DisabledException("User is disabled");
|
||||
}
|
||||
|
||||
Date expiry = new Date(new Date().getTime()
|
||||
+ this.getRefreshTokenInterval());
|
||||
|
||||
if (this.ctx != null) {
|
||||
ctx.publishEvent(new AuthenticationSuccessEvent(authentication, user));
|
||||
}
|
||||
|
||||
return new DaoAuthenticationToken(this.getKey(), expiry,
|
||||
user.getUsername(), user.getPassword(), user.getAuthorities());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.providers.dao.event;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.providers.dao.User;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a <code>net.sf.acegisecurity.provider.dao</code> application
|
||||
* event.
|
||||
*
|
||||
* <P>
|
||||
* Subclasses exist for different types of authentication events. All
|
||||
* authentication events relate to a particular {@link User} and are caused by
|
||||
* a particular {@link Authentication} object. This is intended to permit
|
||||
* logging of successful and unsuccessful login attempts, and facilitate the
|
||||
* locking of accounts.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* The <code>ApplicationEvent</code>'s <code>source</code> will be the
|
||||
* <code>Authentication</code> object.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class AuthenticationEvent extends ApplicationEvent {
|
||||
//~ Instance fields ========================================================
|
||||
|
||||
private User user;
|
||||
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public AuthenticationEvent(Authentication authentication, User user) {
|
||||
super(authentication);
|
||||
|
||||
// No need to check authentication isn't null, as done by super
|
||||
if (user == null) {
|
||||
throw new IllegalArgumentException("User is required");
|
||||
}
|
||||
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
/**
|
||||
* Getters for the <code>Authentication</code> request that caused the
|
||||
* event. Also available from <code>super.getSource()</code>.
|
||||
*
|
||||
* @return the authentication request
|
||||
*/
|
||||
public Authentication getAuthentication() {
|
||||
return (Authentication) super.getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the <code>User</code> related to the
|
||||
* <code>Authentication</code> attempt.
|
||||
*
|
||||
* @return the user
|
||||
*/
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.providers.dao.event;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.providers.dao.User;
|
||||
|
||||
|
||||
/**
|
||||
* Application event which indicates authentication failure due to the user's
|
||||
* account being locked.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationFailureDisabledEvent extends AuthenticationEvent {
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public AuthenticationFailureDisabledEvent(Authentication authentication,
|
||||
User user) {
|
||||
super(authentication, user);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.providers.dao.event;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.providers.dao.User;
|
||||
|
||||
|
||||
/**
|
||||
* Application event which indicates authentication failure due to invalid
|
||||
* password.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationFailurePasswordEvent extends AuthenticationEvent {
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public AuthenticationFailurePasswordEvent(Authentication authentication,
|
||||
User user) {
|
||||
super(authentication, user);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.providers.dao.event;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.providers.dao.User;
|
||||
|
||||
|
||||
/**
|
||||
* Application event which indicates successful authentication.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationSuccessEvent extends AuthenticationEvent {
|
||||
//~ Constructors ===========================================================
|
||||
|
||||
public AuthenticationSuccessEvent(Authentication authentication, User user) {
|
||||
super(authentication, user);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.providers.dao.event;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
|
||||
/**
|
||||
* Outputs authentication-related application events to Commons Logging.
|
||||
*
|
||||
* <P>
|
||||
* All authentication failures are logged at the warning level, whilst
|
||||
* authentication successes are logged at the information level.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LoggerListener implements ApplicationListener {
|
||||
//~ Static fields/initializers =============================================
|
||||
|
||||
private static final Log logger = LogFactory.getLog(LoggerListener.class);
|
||||
|
||||
//~ Methods ================================================================
|
||||
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof AuthenticationFailurePasswordEvent) {
|
||||
AuthenticationFailurePasswordEvent authEvent = (AuthenticationFailurePasswordEvent) event;
|
||||
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Authentication failed due to incorrect password for user: "
|
||||
+ authEvent.getUser().getUsername() + "; details: "
|
||||
+ authEvent.getAuthentication().getDetails());
|
||||
}
|
||||
}
|
||||
|
||||
if (event instanceof AuthenticationFailureDisabledEvent) {
|
||||
AuthenticationFailureDisabledEvent authEvent = (AuthenticationFailureDisabledEvent) event;
|
||||
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(
|
||||
"Authentication failed due to account being disabled for user: "
|
||||
+ authEvent.getUser().getUsername() + "; details: "
|
||||
+ authEvent.getAuthentication().getDetails());
|
||||
}
|
||||
}
|
||||
|
||||
if (event instanceof AuthenticationSuccessEvent) {
|
||||
AuthenticationSuccessEvent authEvent = (AuthenticationSuccessEvent) event;
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Authentication success for user: "
|
||||
+ authEvent.getUser().getUsername() + "; details: "
|
||||
+ authEvent.getAuthentication().getDetails());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<body>
|
||||
Enables events to be published to the Spring application context.
|
||||
|
||||
<P>The <code>DaoAuthenticationProvider</code> automatically publishes
|
||||
events to the application context. These events are received by all
|
||||
registered Spring <code>ApplicationListener</code>s.</P>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,105 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.providers.dao.event;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import net.sf.acegisecurity.providers.dao.User;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link AuthenticationEvent} and its subclasses.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AuthenticationEventTests extends TestCase {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(AuthenticationEventTests.class);
|
||||
}
|
||||
|
||||
public void testDisabledEvent() {
|
||||
Authentication auth = getAuthentication();
|
||||
User user = getUser();
|
||||
AuthenticationFailureDisabledEvent event = new AuthenticationFailureDisabledEvent(auth,
|
||||
user);
|
||||
assertEquals(auth, event.getAuthentication());
|
||||
assertEquals(user, event.getUser());
|
||||
}
|
||||
|
||||
public void testPasswordEvent() {
|
||||
Authentication auth = getAuthentication();
|
||||
User user = getUser();
|
||||
AuthenticationFailurePasswordEvent event = new AuthenticationFailurePasswordEvent(auth,
|
||||
user);
|
||||
assertEquals(auth, event.getAuthentication());
|
||||
assertEquals(user, event.getUser());
|
||||
}
|
||||
|
||||
public void testRejectsNullAuthentication() {
|
||||
try {
|
||||
AuthenticationFailureDisabledEvent event = new AuthenticationFailureDisabledEvent(null,
|
||||
getUser());
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testRejectsNullUser() {
|
||||
try {
|
||||
AuthenticationFailureDisabledEvent event = new AuthenticationFailureDisabledEvent(getAuthentication(),
|
||||
null);
|
||||
fail("Should have thrown IllegalArgumentException");
|
||||
} catch (IllegalArgumentException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSuccessEvent() {
|
||||
Authentication auth = getAuthentication();
|
||||
User user = getUser();
|
||||
AuthenticationSuccessEvent event = new AuthenticationSuccessEvent(auth,
|
||||
user);
|
||||
assertEquals(auth, event.getAuthentication());
|
||||
assertEquals(user, event.getUser());
|
||||
}
|
||||
|
||||
private Authentication getAuthentication() {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("Principal",
|
||||
"Credentials");
|
||||
authentication.setDetails("127.0.0.1");
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
private User getUser() {
|
||||
User user = new User("foo", "bar", true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_FOOBAR")});
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/* Copyright 2004 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.sf.acegisecurity.providers.dao.event;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import net.sf.acegisecurity.Authentication;
|
||||
import net.sf.acegisecurity.GrantedAuthority;
|
||||
import net.sf.acegisecurity.GrantedAuthorityImpl;
|
||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
||||
import net.sf.acegisecurity.providers.dao.User;
|
||||
|
||||
|
||||
/**
|
||||
* Tests {@link LoggerListener}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class LoggerListenerTests extends TestCase {
|
||||
//~ Methods ================================================================
|
||||
|
||||
public final void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(LoggerListenerTests.class);
|
||||
}
|
||||
|
||||
public void testLogsDisabledEvents() {
|
||||
AuthenticationFailureDisabledEvent event = new AuthenticationFailureDisabledEvent(getAuthentication(),
|
||||
getUser());
|
||||
LoggerListener listener = new LoggerListener();
|
||||
listener.onApplicationEvent(event);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testLogsPasswordEvents() {
|
||||
AuthenticationFailurePasswordEvent event = new AuthenticationFailurePasswordEvent(getAuthentication(),
|
||||
getUser());
|
||||
LoggerListener listener = new LoggerListener();
|
||||
listener.onApplicationEvent(event);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
public void testLogsSuccessEvents() {
|
||||
AuthenticationSuccessEvent event = new AuthenticationSuccessEvent(getAuthentication(),
|
||||
getUser());
|
||||
LoggerListener listener = new LoggerListener();
|
||||
listener.onApplicationEvent(event);
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
private Authentication getAuthentication() {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken("Principal",
|
||||
"Credentials");
|
||||
authentication.setDetails("127.0.0.1");
|
||||
|
||||
return authentication;
|
||||
}
|
||||
|
||||
private User getUser() {
|
||||
User user = new User("foo", "bar", true,
|
||||
new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_FOOBAR")});
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<subtitle>Reference Documentation</subtitle>
|
||||
|
||||
<releaseinfo>0.5</releaseinfo>
|
||||
<releaseinfo>0.51</releaseinfo>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
|
@ -76,7 +76,9 @@
|
|||
<listitem>
|
||||
<para>An <literal>Authentication</literal> object which holds the
|
||||
principal, credentials and the authorities granted to the
|
||||
principal.</para>
|
||||
principal. The object can also store additional information
|
||||
associated with an authentication request, such as the source
|
||||
TCP/IP address.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
@ -952,6 +954,63 @@
|
|||
desired.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="security-authentication-provider-in-memory">
|
||||
<title>Event Publishing</title>
|
||||
|
||||
<para>The <literal>DaoAuthenticationProvider</literal> automatically
|
||||
obtains the <literal>ApplicationContext</literal> it is running in at
|
||||
startup time. This allows the provider to publish events through the
|
||||
standard Spring event framework. Three types of event messages are
|
||||
published:</para>
|
||||
|
||||
<itemizedlist spacing="compact">
|
||||
<listitem>
|
||||
<para><literal>AuthenticationSuccessEvent</literal> is published
|
||||
when an authentication request is successful.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>AuthenticationFailureDisabledEvent</literal> is
|
||||
published when an authentication request is unsuccessful because
|
||||
the returned <literal>User</literal> is disabled. This is normally
|
||||
the case when an account is locked.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>AuthenticationFailurePasswordEvent</literal> is
|
||||
published when an authentication request is unsuccessful because
|
||||
the presented password did not match that in the
|
||||
<literal>User</literal>.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>Each event contains two objects: the
|
||||
<literal>Authentication</literal> object that represented the
|
||||
authentication request, and the <literal>User</literal> object that
|
||||
was found in response to the authentication request. The
|
||||
<literal>Authentication</literal> interface provides a
|
||||
<literal>getDetails()</literal> method which often includes
|
||||
information that event consumers may find useful (eg the TCP/IP
|
||||
address that the authentication request originated from).</para>
|
||||
|
||||
<para>As per standard Spring event handling, you can receive these
|
||||
events by adding a bean to the application context which implements
|
||||
the <literal>ApplicationListener</literal> interface. Included with
|
||||
Acegi Security is a <literal>LoggerListener</literal> class which
|
||||
receives these events and publishes their details to Commons Logging.
|
||||
Refer to the JavaDocs for <literal>LoggerListener</literal> for
|
||||
details on the logging priorities used for different message
|
||||
types.</para>
|
||||
|
||||
<para>This event publishing system enables you to implement account
|
||||
locking and record authentication event history. This might be of
|
||||
interest to application users, who can be advised of the times and
|
||||
source IP address of all unsuccessful password attempts (and account
|
||||
lockouts) since their last successful login. Such capabilities are
|
||||
simple to implement and greatly improve the security of your
|
||||
application.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="security-authentication-provider-in-memory">
|
||||
<title>In-Memory Authentication</title>
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
<property name="key"><value>my_password</value></property>
|
||||
</bean>
|
||||
|
||||
<!-- Automatically receives AuthenticationEvent messages from DaoAuthenticationProvider -->
|
||||
<bean id="loggerListener" class="net.sf.acegisecurity.providers.dao.event.LoggerListener"/>
|
||||
|
||||
<bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter">
|
||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||
<property name="authenticationEntryPoint"><ref bean="basicProcessingFilterEntryPoint"/></property>
|
||||
|
|
Loading…
Reference in New Issue