From f5741962edd19b3432b2dcd592f8038826e2972c Mon Sep 17 00:00:00 2001 From: Ben Alex Date: Thu, 22 Sep 2005 00:54:27 +0000 Subject: [PATCH] Add createSessionAllowed property, which should be set to false to avoid unnecessary session creation. --- .../web/SecurityEnforcementFilter.java | 74 ++++++++++++------- doc/xdocs/changes.xml | 1 + 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java b/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java index f7e8e696f8..60371b9935 100644 --- a/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java +++ b/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package net.sf.acegisecurity.intercept.web; import net.sf.acegisecurity.AccessDeniedException; @@ -46,19 +45,19 @@ import javax.servlet.http.HttpServletResponse; /** * Wraps requests to the {@link FilterSecurityInterceptor}. - * + * *

* This filter is necessary because it provides the bridge between incoming * requests and the FilterSecurityInterceptor instance. *

- * + * *

* If an {@link AuthenticationException} is detected, the filter will launch * the authenticationEntryPoint. This allows common handling of * authentication failures originating from any subclass of {@link * net.sf.acegisecurity.intercept.AbstractSecurityInterceptor}. *

- * + * *

* If an {@link AccessDeniedException} is detected, the filter will determine * whether or not the user is an anonymous user. If they are an anonymous @@ -71,11 +70,11 @@ import javax.servlet.http.HttpServletResponse; * trace etc). Again, this allows common access denied handling irrespective * of the originating security interceptor. *

- * + * *

* To use this filter, it is necessary to specify the following properties: *

- * + * * - * + * *

* Do not use this class directly. Instead configure * web.xml to use the {@link @@ -105,19 +104,13 @@ import javax.servlet.http.HttpServletResponse; * @version $Id$ */ public class SecurityEnforcementFilter implements Filter, InitializingBean { - //~ Static fields/initializers ============================================= - private static final Log logger = LogFactory.getLog(SecurityEnforcementFilter.class); public static final String ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY = "ACEGI_SECURITY_403_EXCEPTION"; - - //~ Instance fields ======================================================== - private AuthenticationEntryPoint authenticationEntryPoint; private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); private FilterSecurityInterceptor filterSecurityInterceptor; private PortResolver portResolver = new PortResolverImpl(); - - //~ Methods ================================================================ + private boolean createSessionAllowed = true; public void setAuthenticationEntryPoint( AuthenticationEntryPoint authenticationEntryPoint) { @@ -133,6 +126,27 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { this.authenticationTrustResolver = authenticationTrustResolver; } + /** + * If true, indicates that SecurityEnforcementFilter is permitted + * to store the target URL and exception information in the HttpSession (the + * default). In situations where you do not wish to unnecessarily create HttpSessions + * - because the user agent will know the failed URL, such as with BASIC or Digest authentication + * - you may wish to set this property to false. Remember to also set the + * {@link net.sf.acegisecurity.context.HttpSessionContextIntegrationFilter#allowSessionCreation} + * to false if you set this property to false. + * + * @return true if the HttpSession will be used to store information + * about the failed request, false if the HttpSession will not be + * used + */ + public boolean isCreateSessionAllowed() { + return createSessionAllowed; + } + + public void setCreateSessionAllowed(boolean createSessionAllowed) { + this.createSessionAllowed = createSessionAllowed; + } + public AuthenticationTrustResolver getAuthenticationTrustResolver() { return authenticationTrustResolver; } @@ -164,7 +178,8 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { "authenticationTrustResolver must be specified"); } - public void destroy() {} + public void destroy() { + } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { @@ -193,7 +208,7 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { sendStartAuthentication(fi, authentication); } catch (AccessDeniedException accessDenied) { if (authenticationTrustResolver.isAnonymous( - SecurityContextHolder.getContext().getAuthentication())) { + SecurityContextHolder.getContext().getAuthentication())) { if (logger.isDebugEnabled()) { logger.debug("Access is denied (user is anonymous); redirecting to authentication entry point", accessDenied); @@ -219,13 +234,17 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { } } - public void init(FilterConfig filterConfig) throws ServletException {} + public void init(FilterConfig filterConfig) throws ServletException { + } protected void sendAccessDeniedError(FilterInvocation fi, AccessDeniedException accessDenied) throws ServletException, IOException { - ((HttpServletRequest) fi.getRequest()).getSession().setAttribute(ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY, - accessDenied); + if (createSessionAllowed) { + ((HttpServletRequest) fi.getRequest()).getSession().setAttribute(ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY, + accessDenied); + } + ((HttpServletResponse) fi.getResponse()).sendError(HttpServletResponse.SC_FORBIDDEN, accessDenied.getMessage()); // 403 } @@ -245,18 +264,21 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { includePort = false; } - String targetUrl = request.getScheme() + "://" - + request.getServerName() + ((includePort) ? (":" + port) : "") - + request.getContextPath() + fi.getRequestUrl(); + String targetUrl = request.getScheme() + "://" + + request.getServerName() + ((includePort) ? (":" + port) : "") + + request.getContextPath() + fi.getRequestUrl(); if (logger.isDebugEnabled()) { logger.debug( - "Authentication entry point being called; target URL added to Session: " - + targetUrl); + "Authentication entry point being called; target URL added to Session: " + + targetUrl); + } + + if (createSessionAllowed) { + ((HttpServletRequest) request).getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY, + targetUrl); } - ((HttpServletRequest) request).getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY, - targetUrl); authenticationEntryPoint.commence(request, (HttpServletResponse) fi.getResponse(), reason); } diff --git a/doc/xdocs/changes.xml b/doc/xdocs/changes.xml index 18d082e8cd..d66fd60a1d 100644 --- a/doc/xdocs/changes.xml +++ b/doc/xdocs/changes.xml @@ -49,6 +49,7 @@ Form, CAS, X509 and Remember-Me authentication mechanisms now publish an InteractiveAuthenticationSuccessEvent (see http://opensource.atlassian.com/projects/spring/browse/SEC-5) FilterSecurityInterceptor now has an observeOncePerRequest boolean property, allowing multiple fragments of the HTTP request to be individually authorized (see http://opensource.atlassian.com/projects/spring/browse/SEC-14) AnonymousProcessingFilter cleans up the Authentication object, avoiding HttpSession creation overhead + SecurityEnforcementFilter now has a createSessionAllowed property, which should be set to false to avoid unnecessary session creation UserAttributeEditor now removes trailing spaces SecureContextLoginModule now provides ignoreMissingAuthentication property SecureContextLoginModuleTests fixes (see http://opensource.atlassian.com/projects/spring/browse/SEC-36)