소스 검색

Additional event when user not found. Contributed by Karel Miarka.

Ben Alex 21 년 전
부모
커밋
da5469fed0

+ 2 - 1
contributors.txt

@@ -30,7 +30,8 @@ contributions to the Acegi Security System for Spring project:
 
 
 * Ray Krueger is a current member of the development team.
 * Ray Krueger is a current member of the development team.
 
 
-* Karel Miarka contributed a fix for EH-CACHE NPEs.
+* Karel Miarka contributed a fix for EH-CACHE NPEs and additional event
+  handling for DaoAuthenticationProvider.
 
 
 * Anyone else I've forgotten (please let me know so I can correct this).
 * Anyone else I've forgotten (please let me know so I can correct this).
 
 

+ 15 - 1
core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java

@@ -20,12 +20,14 @@ import net.sf.acegisecurity.AuthenticationException;
 import net.sf.acegisecurity.AuthenticationServiceException;
 import net.sf.acegisecurity.AuthenticationServiceException;
 import net.sf.acegisecurity.BadCredentialsException;
 import net.sf.acegisecurity.BadCredentialsException;
 import net.sf.acegisecurity.DisabledException;
 import net.sf.acegisecurity.DisabledException;
+import net.sf.acegisecurity.GrantedAuthority;
 import net.sf.acegisecurity.UserDetails;
 import net.sf.acegisecurity.UserDetails;
 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.cache.NullUserCache;
 import net.sf.acegisecurity.providers.dao.cache.NullUserCache;
 import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureDisabledEvent;
 import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureDisabledEvent;
 import net.sf.acegisecurity.providers.dao.event.AuthenticationFailurePasswordEvent;
 import net.sf.acegisecurity.providers.dao.event.AuthenticationFailurePasswordEvent;
+import net.sf.acegisecurity.providers.dao.event.AuthenticationFailureUsernameNotFoundEvent;
 import net.sf.acegisecurity.providers.dao.event.AuthenticationSuccessEvent;
 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;
@@ -190,7 +192,19 @@ public class DaoAuthenticationProvider implements AuthenticationProvider,
 
 
         if (user == null) {
         if (user == null) {
             cacheWasUsed = false;
             cacheWasUsed = false;
-            user = getUserFromBackend(username);
+
+            try {
+                user = getUserFromBackend(username);
+            } catch (BadCredentialsException ex) {
+                if (this.context != null) {
+                    context.publishEvent(new AuthenticationFailureUsernameNotFoundEvent(
+                            authentication,
+                            new User(username, "*****", false,
+                                new GrantedAuthority[0])));
+                }
+
+                throw ex;
+            }
         }
         }
 
 
         if (!user.isEnabled()) {
         if (!user.isEnabled()) {

+ 40 - 0
core/src/main/java/org/acegisecurity/providers/dao/event/AuthenticationFailureUsernameNotFoundEvent.java

@@ -0,0 +1,40 @@
+/* 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.UserDetails;
+
+
+/**
+ * Application event which indicates authentication failure due to nonexistent
+ * username. <code>AuthenticationFailureUsernameNotFoundEvent.getUser()</code>
+ * returns an instance of <code>User</code>, where the username is filled by
+ * the <code>String</code> provided at login attempt. The other properties are
+ * set to non-<code>null</code> values without any meaning.
+ *
+ * @author Karel Miarka
+ */
+public class AuthenticationFailureUsernameNotFoundEvent
+    extends AuthenticationEvent {
+    //~ Constructors ===========================================================
+
+    //  ~ Constructors ===========================================================
+    public AuthenticationFailureUsernameNotFoundEvent(
+        Authentication authentication, UserDetails user) {
+        super(authentication, user);
+    }
+}

+ 13 - 1
core/src/main/java/org/acegisecurity/providers/dao/event/LoggerListener.java

@@ -45,7 +45,8 @@ public class LoggerListener implements ApplicationListener {
             AuthenticationFailurePasswordEvent authEvent = (AuthenticationFailurePasswordEvent) event;
             AuthenticationFailurePasswordEvent authEvent = (AuthenticationFailurePasswordEvent) event;
 
 
             if (logger.isWarnEnabled()) {
             if (logger.isWarnEnabled()) {
-                logger.warn("Authentication failed due to incorrect password for user: "
+                logger.warn(
+                    "Authentication failed due to incorrect password for user: "
                     + authEvent.getUser().getUsername() + "; details: "
                     + authEvent.getUser().getUsername() + "; details: "
                     + authEvent.getAuthentication().getDetails());
                     + authEvent.getAuthentication().getDetails());
             }
             }
@@ -62,6 +63,17 @@ public class LoggerListener implements ApplicationListener {
             }
             }
         }
         }
 
 
+        if (event instanceof AuthenticationFailureUsernameNotFoundEvent) {
+            AuthenticationFailureUsernameNotFoundEvent authEvent = (AuthenticationFailureUsernameNotFoundEvent) event;
+
+            if (logger.isWarnEnabled()) {
+                logger.warn(
+                    "Authentication failed due to nonexistent username: "
+                    + authEvent.getUser().getUsername() + "; details: "
+                    + authEvent.getAuthentication().getDetails());
+            }
+        }
+
         if (event instanceof AuthenticationSuccessEvent) {
         if (event instanceof AuthenticationSuccessEvent) {
             AuthenticationSuccessEvent authEvent = (AuthenticationSuccessEvent) event;
             AuthenticationSuccessEvent authEvent = (AuthenticationSuccessEvent) event;
 
 

+ 14 - 6
docs/reference/src/index.xml

@@ -1018,22 +1018,31 @@
           <listitem>
           <listitem>
             <para><literal>AuthenticationFailureDisabledEvent</literal> is
             <para><literal>AuthenticationFailureDisabledEvent</literal> is
             published when an authentication request is unsuccessful because
             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>
+            the returned <literal>UserDetails</literal> is disabled. This is
+            normally the case when an account is locked.</para>
+          </listitem>
+
+          <listitem>
+            <para><literal>AuthenticationFailureUsernameNotFoundEvent</literal>
+            is published when an authentication request is unsuccessful
+            because the <literal>AuthenticationDao</literal> could not locate
+            the <literal>UserDetails</literal>.</para>
           </listitem>
           </listitem>
 
 
           <listitem>
           <listitem>
             <para><literal>AuthenticationFailurePasswordEvent</literal> is
             <para><literal>AuthenticationFailurePasswordEvent</literal> is
             published when an authentication request is unsuccessful because
             published when an authentication request is unsuccessful because
             the presented password did not match that in the
             the presented password did not match that in the
-            <literal>User</literal>.</para>
+            <literal>UserDetails</literal>.</para>
           </listitem>
           </listitem>
         </itemizedlist>
         </itemizedlist>
 
 
         <para>Each event contains two objects: the
         <para>Each event contains two objects: the
         <literal>Authentication</literal> object that represented the
         <literal>Authentication</literal> object that represented the
         authentication request, and the <literal>UserDetails</literal> object
         authentication request, and the <literal>UserDetails</literal> object
-        that was found in response to the authentication request. The
+        that was found in response to the authentication request (clearly the
+        latter will be a dummy object in the case of
+        <literal>AuthenticationFailureUsernameNotFoundEvent</literal>). The
         <literal>Authentication</literal> interface provides a
         <literal>Authentication</literal> interface provides a
         <literal>getDetails()</literal> method which often includes
         <literal>getDetails()</literal> method which often includes
         information that event consumers may find useful (eg the TCP/IP
         information that event consumers may find useful (eg the TCP/IP
@@ -1150,8 +1159,7 @@
           <title>JaasAuthenticationProvider</title>
           <title>JaasAuthenticationProvider</title>
 
 
           <para>The <literal>JaasAuthenticationProvider</literal> attempts to
           <para>The <literal>JaasAuthenticationProvider</literal> attempts to
-          authenticate a user’s principal and credentials through JAAS.
-          </para>
+          authenticate a user’s principal and credentials through JAAS.</para>
 
 
           <para>Let’s assume we have a JAAS login configuration file,
           <para>Let’s assume we have a JAAS login configuration file,
           <literal>/WEB-INF/login.conf</literal>, with the following
           <literal>/WEB-INF/login.conf</literal>, with the following