diff --git a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java
index fe1a55d00d..41aab01b39 100644
--- a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java
+++ b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java
@@ -12,6 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package net.sf.acegisecurity.ui.basicauth;
import net.sf.acegisecurity.Authentication;
@@ -45,13 +46,13 @@ import javax.servlet.http.HttpServletResponse;
/**
* Processes a HTTP request's BASIC authorization headers, putting the result
* into the SecurityContextHolder
.
- *
+ *
*
* For a detailed background on what this filter is designed to process, refer * to RFC 1945, Section * 11.1. Any realm name presented in the HTTP request is ignored. *
- * + * *
* In summary, this filter is responsible for processing any request that has a
* HTTP request header of Authorization
with an authentication
@@ -60,28 +61,28 @@ import javax.servlet.http.HttpServletResponse;
* "Aladdin" with password "open sesame" the following header would be
* presented:
*
* Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
.
*
* This filter can be used to provide BASIC authentication services to both * remoting protocol clients (such as Hessian and SOAP) as well as standard * user agents (such as Internet Explorer and Netscape). *
- * + * *
* If authentication is successful, the resulting {@link Authentication} object
* will be placed into the SecurityContextHolder
.
*
* If authentication fails, an {@link AuthenticationEntryPoint} implementation * is called. Usually this should be {@link BasicProcessingFilterEntryPoint}, * which will prompt the user to authenticate again via BASIC authentication. *
- * + * ** Basic authentication is an attractive protocol because it is simple and * widely deployed. However, it still transmits a password in clear text and @@ -90,7 +91,7 @@ import javax.servlet.http.HttpServletResponse; * authentication wherever possible. See {@link * net.sf.acegisecurity.ui.digestauth.DigestProcessingFilter}. *
- * + * *
* Do not use this class directly. Instead configure
* web.xml
to use the {@link
@@ -101,10 +102,17 @@ import javax.servlet.http.HttpServletResponse;
* @version $Id$
*/
public class BasicProcessingFilter implements Filter, InitializingBean {
+ //~ Static fields/initializers =============================================
+
private static final Log logger = LogFactory.getLog(BasicProcessingFilter.class);
+
+ //~ Instance fields ========================================================
+
private AuthenticationEntryPoint authenticationEntryPoint;
private AuthenticationManager authenticationManager;
+ //~ Methods ================================================================
+
public void setAuthenticationEntryPoint(
AuthenticationEntryPoint authenticationEntryPoint) {
this.authenticationEntryPoint = authenticationEntryPoint;
@@ -130,8 +138,7 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
"An AuthenticationEntryPoint is required");
}
- public void destroy() {
- }
+ public void destroy() {}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
@@ -165,40 +172,47 @@ public class BasicProcessingFilter implements Filter, InitializingBean {
password = token.substring(delim + 1);
}
- UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
- password);
- authRequest.setDetails(new WebAuthenticationDetails(httpRequest,
- false));
+ // Only reauthenticate if username doesn't match ContextHolder and user isn't authenticated (see SEC-53)
+ Authentication existingAuth = SecurityContextHolder.getContext()
+ .getAuthentication();
- Authentication authResult;
+ if ((existingAuth == null)
+ || !existingAuth.getName().equals(username)
+ || !existingAuth.isAuthenticated()) {
+ UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username,
+ password);
+ authRequest.setDetails(new WebAuthenticationDetails(
+ httpRequest, false));
- try {
- authResult = authenticationManager.authenticate(authRequest);
- } catch (AuthenticationException failed) {
- // Authentication failed
- if (logger.isDebugEnabled()) {
- logger.debug("Authentication request for user: " +
- username + " failed: " + failed.toString());
+ Authentication authResult;
+
+ try {
+ authResult = authenticationManager.authenticate(authRequest);
+ } catch (AuthenticationException failed) {
+ // Authentication failed
+ if (logger.isDebugEnabled()) {
+ logger.debug("Authentication request for user: "
+ + username + " failed: " + failed.toString());
+ }
+
+ SecurityContextHolder.getContext().setAuthentication(null);
+ authenticationEntryPoint.commence(request, response, failed);
+
+ return;
}
- SecurityContextHolder.getContext().setAuthentication(null);
- authenticationEntryPoint.commence(request, response, failed);
+ // Authentication success
+ if (logger.isDebugEnabled()) {
+ logger.debug("Authentication success: "
+ + authResult.toString());
+ }
- return;
+ SecurityContextHolder.getContext().setAuthentication(authResult);
}
-
- // Authentication success
- if (logger.isDebugEnabled()) {
- logger.debug("Authentication success: " +
- authResult.toString());
- }
-
- SecurityContextHolder.getContext().setAuthentication(authResult);
}
chain.doFilter(request, response);
}
- public void init(FilterConfig arg0) throws ServletException {
- }
+ public void init(FilterConfig arg0) throws ServletException {}
}
diff --git a/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java
index 0a82f855a3..b27af1846c 100644
--- a/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java
+++ b/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterTests.java
@@ -183,6 +183,7 @@ public class BasicProcessingFilterTests extends TestCase {
MockHttpServletResponse response = new MockHttpServletResponse();
// Test
+ assertNull(SecurityContextHolder.getContext().getAuthentication());
executeFilterInContainerSimulator(config, filter, request, response,
chain);
@@ -280,7 +281,7 @@ public class BasicProcessingFilterTests extends TestCase {
// NOW PERFORM FAILED AUTHENTICATION
// Setup our HTTP request
- token = "marissa:WRONG_PASSWORD";
+ token = "otherUser:WRONG_PASSWORD";
request = new MockHttpServletRequest();
request.addHeader("Authorization",
"Basic " + new String(Base64.encodeBase64(token.getBytes())));