From e52f3eacb10b3fb3d9311f4cbd852ee45c290b60 Mon Sep 17 00:00:00 2001 From: Ben Alex Date: Mon, 21 Feb 2005 00:09:49 +0000 Subject: [PATCH] Use WebAuthenticationDetails for Authentication.getDetails() by default. --- .../dao/DaoAuthenticationProvider.java | 6 +- .../ui/WebAuthenticationDetails.java | 96 +++++++++++++++++++ .../ui/basicauth/BasicProcessingFilter.java | 5 +- .../ui/cas/CasProcessingFilter.java | 5 +- .../AuthenticationProcessingFilter.java | 33 ++++++- .../org/acegisecurity/MockHttpSession.java | 4 +- .../AuthenticationProcessingFilterTests.java | 6 +- doc/xdocs/changes.xml | 2 + 8 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 core/src/main/java/org/acegisecurity/ui/WebAuthenticationDetails.java diff --git a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java b/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java index c4b5802a2f..bb03b6e3cb 100644 --- a/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java +++ b/core/src/main/java/org/acegisecurity/providers/dao/DaoAuthenticationProvider.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 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. @@ -345,9 +345,7 @@ public class DaoAuthenticationProvider implements AuthenticationProvider, * Creates a successful {@link Authentication} object. * *

- * Protected so subclasses can override. This might be required if multiple - * credentials need to be placed into a custom Authentication - * object, such as a password as well as a ZIP code. + * Protected so subclasses can override. *

* *

diff --git a/core/src/main/java/org/acegisecurity/ui/WebAuthenticationDetails.java b/core/src/main/java/org/acegisecurity/ui/WebAuthenticationDetails.java new file mode 100644 index 0000000000..75b2cfcc45 --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ui/WebAuthenticationDetails.java @@ -0,0 +1,96 @@ +/* Copyright 2004, 2005 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.ui; + +import java.io.Serializable; + +import javax.servlet.http.HttpServletRequest; + + +/** + * A holder of selected HTTP details related to a web authentication request. + * + * @author Ben Alex + * @version $Id$ + */ +public class WebAuthenticationDetails implements Serializable { + //~ Instance fields ======================================================== + + private String remoteAddress; + private String sessionId; + + //~ Constructors =========================================================== + + /** + * Constructor. + * + *

+ * NB: This constructor will cause a HttpSession to be created + * (this is considered reasonable as all Acegi Security authentication + * requests rely on HttpSession to store the + * Authentication between requests + *

+ * + * @param request that the authentication request was received from + */ + public WebAuthenticationDetails(HttpServletRequest request) { + this.remoteAddress = request.getRemoteAddr(); + this.sessionId = request.getSession().getId(); + doPopulateAdditionalInformation(request); + } + + protected WebAuthenticationDetails() { + throw new IllegalArgumentException("Cannot use default constructor"); + } + + //~ Methods ================================================================ + + /** + * Indicates the TCP/IP address the authentication request was received + * from. + * + * @return the address + */ + public String getRemoteAddress() { + return remoteAddress; + } + + /** + * Indicates the HttpSession id the authentication request was + * received from. + * + * @return the session ID + */ + public String getSessionId() { + return sessionId; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(super.toString() + ": "); + sb.append("RemoteIpAddress: " + this.getRemoteAddress() + "; "); + sb.append("SessionId: " + this.getSessionId()); + + return sb.toString(); + } + + /** + * Provided so that subclasses can populate additional information. + * + * @param request that the authentication request was received from + */ + protected void doPopulateAdditionalInformation(HttpServletRequest request) {} +} 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 d9ff62e1bb..aef5e66e5f 100644 --- a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java +++ b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 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. @@ -20,6 +20,7 @@ import net.sf.acegisecurity.AuthenticationException; import net.sf.acegisecurity.AuthenticationManager; import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; +import net.sf.acegisecurity.ui.WebAuthenticationDetails; import net.sf.acegisecurity.ui.webapp.HttpSessionIntegrationFilter; import org.apache.commons.codec.binary.Base64; @@ -168,7 +169,7 @@ public class BasicProcessingFilter implements Filter, InitializingBean { UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); - authRequest.setDetails(httpRequest.getRemoteAddr()); + authRequest.setDetails(new WebAuthenticationDetails(httpRequest)); Authentication authResult; diff --git a/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilter.java index 68009b9ae7..ba2ffc6c20 100644 --- a/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilter.java +++ b/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilter.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 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. @@ -19,6 +19,7 @@ import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.AuthenticationException; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.ui.AbstractProcessingFilter; +import net.sf.acegisecurity.ui.WebAuthenticationDetails; import javax.servlet.FilterConfig; import javax.servlet.ServletException; @@ -103,7 +104,7 @@ public class CasProcessingFilter extends AbstractProcessingFilter { UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); - authRequest.setDetails(request.getRemoteAddr()); + authRequest.setDetails(new WebAuthenticationDetails(request)); return this.getAuthenticationManager().authenticate(authRequest); } diff --git a/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java b/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java index 899166fd39..3357c18871 100644 --- a/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java +++ b/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilter.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 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. @@ -19,6 +19,7 @@ import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.AuthenticationException; import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken; import net.sf.acegisecurity.ui.AbstractProcessingFilter; +import net.sf.acegisecurity.ui.WebAuthenticationDetails; import javax.servlet.FilterConfig; import javax.servlet.ServletException; @@ -66,7 +67,7 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { public Authentication attemptAuthentication(HttpServletRequest request) throws AuthenticationException { String username = request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY); - String password = request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY); + String password = obtainPassword(request); if (username == null) { username = ""; @@ -93,8 +94,8 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { /** * Provided so that subclasses may configure what is put into the - * authentication request's details property. Default implementation - * simply sets the IP address of the servlet request. + * authentication request's details property. The default implementation + * simply constructs {@link WebAuthenticationDetails}. * * @param request that an authentication request is being created for * @param authRequest the authentication request object that should have @@ -102,6 +103,28 @@ public class AuthenticationProcessingFilter extends AbstractProcessingFilter { */ protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { - authRequest.setDetails(request.getRemoteAddr()); + authRequest.setDetails(new WebAuthenticationDetails(request)); + } + + /** + * Enables subclasses to override the composition of the password, such as + * by including additional values and a separator. + * + *

+ * This might be used for example if a postcode/zipcode was required in + * addition to the password. A delimiter such as a pipe (|) should be used + * to separate the password and extended value(s). The + * AuthenticationDao will need to generate the expected + * password in a corresponding manner. + *

+ * + * @param request so that request attributes can be retrieved + * + * @return the password that will be presented in the + * Authentication request token to the + * AuthenticationManager + */ + protected String obtainPassword(HttpServletRequest request) { + return request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY); } } diff --git a/core/src/test/java/org/acegisecurity/MockHttpSession.java b/core/src/test/java/org/acegisecurity/MockHttpSession.java index 057a6e0fff..797869857d 100644 --- a/core/src/test/java/org/acegisecurity/MockHttpSession.java +++ b/core/src/test/java/org/acegisecurity/MockHttpSession.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 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. @@ -55,7 +55,7 @@ public class MockHttpSession implements HttpSession { } public String getId() { - throw new UnsupportedOperationException("mock method not implemented"); + return "3984594856968"; } public long getLastAccessedTime() { diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java index 97408fdbdb..e5499a9590 100644 --- a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java +++ b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterTests.java @@ -1,4 +1,4 @@ -/* Copyright 2004 Acegi Technology Pty Limited +/* Copyright 2004, 2005 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. @@ -21,6 +21,7 @@ import net.sf.acegisecurity.Authentication; import net.sf.acegisecurity.MockAuthenticationManager; import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpSession; +import net.sf.acegisecurity.ui.WebAuthenticationDetails; /** @@ -72,7 +73,8 @@ public class AuthenticationProcessingFilterTests extends TestCase { Authentication result = filter.attemptAuthentication(request); assertTrue(result != null); - assertEquals("127.0.0.1", result.getDetails()); + assertEquals("127.0.0.1", + ((WebAuthenticationDetails) result.getDetails()).getRemoteAddress()); } public void testNullPasswordHandledGracefully() throws Exception { diff --git a/doc/xdocs/changes.xml b/doc/xdocs/changes.xml index 096a6058b9..d3e918f409 100644 --- a/doc/xdocs/changes.xml +++ b/doc/xdocs/changes.xml @@ -43,6 +43,8 @@ FilterChainProxy added to significantly simplify web.xml configuration of Acegi Security FilterToBeanProxy now addresses lifecycle mismatch (IoC container vs servlet container) issue Additional debug-level logging + AuthenticationProcessingFilter now provides hook for extra credentials (eg postcodes) + New WebAuthenticationDetails class now used by processing filters for Authentication.setDetails() Major CVS repository restructure to support Maven and eliminate libraries