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.DisabledException;
|
||||||
import net.sf.acegisecurity.providers.AuthenticationProvider;
|
import net.sf.acegisecurity.providers.AuthenticationProvider;
|
||||||
import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
|
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.PasswordEncoder;
|
||||||
import net.sf.acegisecurity.providers.encoding.PlaintextPasswordEncoder;
|
import net.sf.acegisecurity.providers.encoding.PlaintextPasswordEncoder;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -56,14 +63,23 @@ import java.util.Date;
|
||||||
* <code>UsernamePasswordAuthenticationToken</code>. This avoids complications
|
* <code>UsernamePasswordAuthenticationToken</code>. This avoids complications
|
||||||
* if the user changes their password during the session.
|
* if the user changes their password during the session.
|
||||||
* </p>
|
* </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
|
* @author Ben Alex
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class DaoAuthenticationProvider implements AuthenticationProvider,
|
public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||||
InitializingBean {
|
InitializingBean, ApplicationContextAware {
|
||||||
//~ Instance fields ========================================================
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
private ApplicationContext ctx;
|
||||||
private AuthenticationDao authenticationDao;
|
private AuthenticationDao authenticationDao;
|
||||||
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
|
private PasswordEncoder passwordEncoder = new PlaintextPasswordEncoder();
|
||||||
private SaltSource saltSource;
|
private SaltSource saltSource;
|
||||||
|
@ -72,6 +88,11 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||||
|
|
||||||
//~ Methods ================================================================
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext)
|
||||||
|
throws BeansException {
|
||||||
|
this.ctx = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
|
public void setAuthenticationDao(AuthenticationDao authenticationDao) {
|
||||||
this.authenticationDao = authenticationDao;
|
this.authenticationDao = authenticationDao;
|
||||||
}
|
}
|
||||||
|
@ -175,6 +196,15 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
|
||||||
throw new AuthenticationServiceException(repositoryProblem
|
throw new AuthenticationServiceException(repositoryProblem
|
||||||
.getMessage(), 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)) {
|
if (!(authentication instanceof DaoAuthenticationToken)) {
|
||||||
// Must validate credentials, as this is not simply a token refresh
|
// 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(),
|
if (!passwordEncoder.isPasswordValid(user.getPassword(),
|
||||||
authentication.getCredentials().toString(), salt)) {
|
authentication.getCredentials().toString(), salt)) {
|
||||||
|
if (this.ctx != null) {
|
||||||
|
ctx.publishEvent(new AuthenticationFailurePasswordEvent(
|
||||||
|
authentication, user));
|
||||||
|
}
|
||||||
|
|
||||||
throw new BadCredentialsException("Bad credentials presented");
|
throw new BadCredentialsException("Bad credentials presented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.isEnabled()) {
|
|
||||||
throw new DisabledException("User is disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
Date expiry = new Date(new Date().getTime()
|
Date expiry = new Date(new Date().getTime()
|
||||||
+ this.getRefreshTokenInterval());
|
+ this.getRefreshTokenInterval());
|
||||||
|
|
||||||
|
if (this.ctx != null) {
|
||||||
|
ctx.publishEvent(new AuthenticationSuccessEvent(authentication, user));
|
||||||
|
}
|
||||||
|
|
||||||
return new DaoAuthenticationToken(this.getKey(), expiry,
|
return new DaoAuthenticationToken(this.getKey(), expiry,
|
||||||
user.getUsername(), user.getPassword(), user.getAuthorities());
|
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>
|
<subtitle>Reference Documentation</subtitle>
|
||||||
|
|
||||||
<releaseinfo>0.5</releaseinfo>
|
<releaseinfo>0.51</releaseinfo>
|
||||||
|
|
||||||
<authorgroup>
|
<authorgroup>
|
||||||
<author>
|
<author>
|
||||||
|
@ -76,7 +76,9 @@
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>An <literal>Authentication</literal> object which holds the
|
<para>An <literal>Authentication</literal> object which holds the
|
||||||
principal, credentials and the authorities granted to 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>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -952,6 +954,63 @@
|
||||||
desired.</para>
|
desired.</para>
|
||||||
</sect2>
|
</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">
|
<sect2 id="security-authentication-provider-in-memory">
|
||||||
<title>In-Memory Authentication</title>
|
<title>In-Memory Authentication</title>
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,9 @@
|
||||||
<property name="key"><value>my_password</value></property>
|
<property name="key"><value>my_password</value></property>
|
||||||
</bean>
|
</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">
|
<bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter">
|
||||||
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
<property name="authenticationManager"><ref bean="authenticationManager"/></property>
|
||||||
<property name="authenticationEntryPoint"><ref bean="basicProcessingFilterEntryPoint"/></property>
|
<property name="authenticationEntryPoint"><ref bean="basicProcessingFilterEntryPoint"/></property>
|
||||||
|
|
Loading…
Reference in New Issue