From 1949c3b27e8ec5179e7a2337b2500e8f43d25f24 Mon Sep 17 00:00:00 2001 From: Ray Krueger Date: Tue, 15 Feb 2005 03:28:18 +0000 Subject: [PATCH] Added AuthenticationException to the commence method signature of the AutenticationEntryPoint. The best example of this is the BasicProcessingFilterEntryPoint where the authException.getMessage() is used to send back an informative 401, instead of just the error code. Added AccessDeniedException to the sendAccessDeniedError method signature. The accessDeniedException.getMessage() result is used to send an invormative 403 error back to the servletResponse by default. --- .../intercept/web/AuthenticationEntryPoint.java | 10 +++++++--- .../intercept/web/SecurityEnforcementFilter.java | 11 +++++++---- .../ui/basicauth/BasicProcessingFilter.java | 3 +-- .../BasicProcessingFilterEntryPoint.java | 9 ++++++--- .../ui/cas/CasProcessingFilterEntryPoint.java | 4 +++- ...AuthenticationProcessingFilterEntryPoint.java | 4 +++- .../MockAuthenticationEntryPoint.java | 3 ++- .../acegisecurity/MockHttpServletResponse.java | 8 +++++++- .../BasicProcessingFilterEntryPointTests.java | 8 +++++++- .../cas/CasProcessingFilterEntryPointTests.java | 4 ++-- ...nticationProcessingFilterEntryPointTests.java | 16 ++++++++-------- doc/xdocs/changes.xml | 5 +++-- doc/xdocs/upgrade/upgrade-070-100.html | 10 ++++++---- 13 files changed, 62 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/org/acegisecurity/intercept/web/AuthenticationEntryPoint.java b/core/src/main/java/org/acegisecurity/intercept/web/AuthenticationEntryPoint.java index 1f114faaec..b9f59d0638 100644 --- a/core/src/main/java/org/acegisecurity/intercept/web/AuthenticationEntryPoint.java +++ b/core/src/main/java/org/acegisecurity/intercept/web/AuthenticationEntryPoint.java @@ -15,6 +15,8 @@ package net.sf.acegisecurity.intercept.web; +import net.sf.acegisecurity.AuthenticationException; + import java.io.IOException; import javax.servlet.ServletException; @@ -34,14 +36,14 @@ public interface AuthenticationEntryPoint { /** * Commences an authentication scheme. - * + * *

* SecurityEnforcementFilter will populate the * HttpSession attribute named * AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY * with the requested target URL before calling this method. *

- * + * *

* Implementations should modify the headers on the * ServletResponse as necessary to commence the @@ -50,7 +52,9 @@ public interface AuthenticationEntryPoint { * * @param request that resulted in an AuthenticationException * @param response so that the user agent can begin authentication + * @param authException that caused the invocation */ - public void commence(ServletRequest request, ServletResponse response) + public void commence(ServletRequest request, ServletResponse response, + AuthenticationException authException) throws IOException, ServletException; } 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 4bcf31b837..de19a2b6d6 100644 --- a/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java +++ b/core/src/main/java/org/acegisecurity/intercept/web/SecurityEnforcementFilter.java @@ -199,7 +199,7 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { ((HttpServletRequest) request).getSession().setAttribute(AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY, targetUrl); - authenticationEntryPoint.commence(request, response); + authenticationEntryPoint.commence(request, response, authentication); } catch (AccessDeniedException accessDenied) { if (logger.isDebugEnabled()) { logger.debug( @@ -208,7 +208,7 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { ((HttpServletRequest) request).getSession().setAttribute(ACEGI_SECURITY_ACCESS_DENIED_EXCEPTION_KEY, accessDenied); - sendAccessDeniedError(request, response); + sendAccessDeniedError(request, response, accessDenied); } catch (Throwable otherException) { throw new ServletException(otherException); } @@ -221,11 +221,14 @@ public class SecurityEnforcementFilter implements Filter, InitializingBean { * * @param request * @param response + * @param accessDenied * * @throws IOException */ protected void sendAccessDeniedError(ServletRequest request, - ServletResponse response) throws IOException { - ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN); // 403 + ServletResponse response, AccessDeniedException accessDenied) + throws IOException { + ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, + accessDenied.getMessage()); // 403 } } 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 bfc754a26b..d9ff62e1bb 100644 --- a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java +++ b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilter.java @@ -145,7 +145,6 @@ public class BasicProcessingFilter implements Filter, InitializingBean { } HttpServletRequest httpRequest = (HttpServletRequest) request; - HttpServletResponse httpResponse = (HttpServletResponse) response; String header = httpRequest.getHeader("Authorization"); @@ -182,7 +181,7 @@ public class BasicProcessingFilter implements Filter, InitializingBean { + " failed: " + failed.toString()); } - authenticationEntryPoint.commence(request, response); + authenticationEntryPoint.commence(request, response, failed); return; } diff --git a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPoint.java b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPoint.java index f4fd0b8196..285d45efb7 100644 --- a/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPoint.java +++ b/core/src/main/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPoint.java @@ -1,4 +1,4 @@ -/* Copyright 2004, 2005 Acegi Technology Pty Limited +/* 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. @@ -15,6 +15,7 @@ package net.sf.acegisecurity.ui.basicauth; +import net.sf.acegisecurity.AuthenticationException; import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint; import org.springframework.beans.factory.InitializingBean; @@ -65,11 +66,13 @@ public class BasicProcessingFilterEntryPoint implements AuthenticationEntryPoint } } - public void commence(ServletRequest request, ServletResponse response) + public void commence(ServletRequest request, ServletResponse response, + AuthenticationException authException) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\""); - httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); // 401 + httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, + authException.getMessage()); } } diff --git a/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPoint.java b/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPoint.java index 04956b4760..59fd6ff4a7 100644 --- a/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPoint.java +++ b/core/src/main/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPoint.java @@ -15,6 +15,7 @@ package net.sf.acegisecurity.ui.cas; +import net.sf.acegisecurity.AuthenticationException; import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint; import org.springframework.beans.factory.InitializingBean; @@ -88,7 +89,8 @@ public class CasProcessingFilterEntryPoint implements AuthenticationEntryPoint, } } - public void commence(ServletRequest request, ServletResponse response) + public void commence(ServletRequest request, ServletResponse response, + AuthenticationException authenticationException) throws IOException, ServletException { String url; diff --git a/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPoint.java b/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPoint.java index b5d8d9ee09..437060f567 100644 --- a/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPoint.java +++ b/core/src/main/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPoint.java @@ -15,6 +15,7 @@ package net.sf.acegisecurity.ui.webapp; +import net.sf.acegisecurity.AuthenticationException; import net.sf.acegisecurity.intercept.web.AuthenticationEntryPoint; import net.sf.acegisecurity.util.PortMapper; import net.sf.acegisecurity.util.PortMapperImpl; @@ -133,7 +134,8 @@ public class AuthenticationProcessingFilterEntryPoint } } - public void commence(ServletRequest request, ServletResponse response) + public void commence(ServletRequest request, ServletResponse response, + AuthenticationException authException) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; String scheme = request.getScheme(); diff --git a/core/src/test/java/org/acegisecurity/MockAuthenticationEntryPoint.java b/core/src/test/java/org/acegisecurity/MockAuthenticationEntryPoint.java index 8a286d0653..70023ee65d 100644 --- a/core/src/test/java/org/acegisecurity/MockAuthenticationEntryPoint.java +++ b/core/src/test/java/org/acegisecurity/MockAuthenticationEntryPoint.java @@ -49,7 +49,8 @@ public class MockAuthenticationEntryPoint implements AuthenticationEntryPoint { //~ Methods ================================================================ - public void commence(ServletRequest request, ServletResponse response) + public void commence(ServletRequest request, ServletResponse response, + AuthenticationException authenticationException) throws IOException, ServletException { ((HttpServletResponse) response).sendRedirect(((HttpServletRequest) request) .getContextPath() + url); diff --git a/core/src/test/java/org/acegisecurity/MockHttpServletResponse.java b/core/src/test/java/org/acegisecurity/MockHttpServletResponse.java index 890c91e448..5393c85fe5 100644 --- a/core/src/test/java/org/acegisecurity/MockHttpServletResponse.java +++ b/core/src/test/java/org/acegisecurity/MockHttpServletResponse.java @@ -38,6 +38,7 @@ public class MockHttpServletResponse implements HttpServletResponse { //~ Instance fields ======================================================== private Map headersMap = new HashMap(); + private String errorMessage; private String redirect; private int error; @@ -79,6 +80,10 @@ public class MockHttpServletResponse implements HttpServletResponse { return this.error; } + public String getErrorMessage() { + return this.errorMessage; + } + public void setHeader(String arg0, String arg1) { throw new UnsupportedOperationException("mock method not implemented"); } @@ -174,7 +179,8 @@ public class MockHttpServletResponse implements HttpServletResponse { } public void sendError(int arg0, String arg1) throws IOException { - throw new UnsupportedOperationException("mock method not implemented"); + this.error = arg0; + this.errorMessage = arg1; } public void sendError(int arg0) throws IOException { diff --git a/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPointTests.java b/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPointTests.java index 3eb9913f93..3eba0a83cb 100644 --- a/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPointTests.java +++ b/core/src/test/java/org/acegisecurity/ui/basicauth/BasicProcessingFilterEntryPointTests.java @@ -17,6 +17,7 @@ package net.sf.acegisecurity.ui.basicauth; import junit.framework.TestCase; +import net.sf.acegisecurity.DisabledException; import net.sf.acegisecurity.MockHttpServletRequest; import net.sf.acegisecurity.MockHttpServletResponse; @@ -74,8 +75,13 @@ public class BasicProcessingFilterEntryPointTests extends TestCase { MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); - ep.commence(request, response); + + String msg = "These are the jokes kid"; + ep.commence(request, response, new DisabledException(msg)); + assertEquals(401, response.getError()); + assertEquals(msg, response.getErrorMessage()); + assertEquals("Basic realm=\"hello\"", response.getHeader("WWW-Authenticate")); } diff --git a/core/src/test/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPointTests.java b/core/src/test/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPointTests.java index 1cc674e0bc..ac83ac0959 100644 --- a/core/src/test/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPointTests.java +++ b/core/src/test/java/org/acegisecurity/ui/cas/CasProcessingFilterEntryPointTests.java @@ -100,7 +100,7 @@ public class CasProcessingFilterEntryPointTests extends TestCase { MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("https://cas/login?service=" + URLEncoder.encode( @@ -124,7 +124,7 @@ public class CasProcessingFilterEntryPointTests extends TestCase { MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("https://cas/login?renew=true&service=https://mycompany.com/bigWebApp/j_acegi_cas_security_check", response.getRedirect()); } diff --git a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPointTests.java b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPointTests.java index 5b11b8f579..0b0812bb18 100644 --- a/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPointTests.java +++ b/core/src/test/java/org/acegisecurity/ui/webapp/AuthenticationProcessingFilterEntryPointTests.java @@ -117,19 +117,19 @@ public class AuthenticationProcessingFilterEntryPointTests extends TestCase { ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirect()); request.setServerPort(8080); ep.setPortResolver(new MockPortResolver(8080, 8443)); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirect()); // Now test an unusual custom HTTP:HTTPS is handled properly request.setServerPort(8888); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirect()); @@ -146,7 +146,7 @@ public class AuthenticationProcessingFilterEntryPointTests extends TestCase { ep.setPortResolver(new MockPortResolver(8888, 9999)); ep.afterPropertiesSet(); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("https://www.example.com:9999/bigWebApp/hello", response.getRedirect()); } @@ -170,13 +170,13 @@ public class AuthenticationProcessingFilterEntryPointTests extends TestCase { ep.setPortResolver(new MockPortResolver(80, 443)); ep.afterPropertiesSet(); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("https://www.example.com/bigWebApp/hello", response.getRedirect()); request.setServerPort(8443); ep.setPortResolver(new MockPortResolver(8080, 8443)); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("https://www.example.com:8443/bigWebApp/hello", response.getRedirect()); } @@ -199,7 +199,7 @@ public class AuthenticationProcessingFilterEntryPointTests extends TestCase { MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); - ep.commence(request, response); + ep.commence(request, response, null); assertEquals("http://www.example.com/bigWebApp/hello", response.getRedirect()); } @@ -224,7 +224,7 @@ public class AuthenticationProcessingFilterEntryPointTests extends TestCase { MockHttpServletResponse response = new MockHttpServletResponse(); ep.afterPropertiesSet(); - ep.commence(request, response); + ep.commence(request, response, null); // Response doesn't switch to HTTPS, as we didn't know HTTP port 8888 to HTTP port mapping assertEquals("http://www.example.com:8888/bigWebApp/hello", diff --git a/doc/xdocs/changes.xml b/doc/xdocs/changes.xml index a26aa1cbd4..f13dd34002 100644 --- a/doc/xdocs/changes.xml +++ b/doc/xdocs/changes.xml @@ -36,8 +36,9 @@ FilterSecurityInterceptor now only executes once per request (improves performance with SiteMesh) Contacts sample web.xml no longer expect Log4j to be in classpath JaasAuthenticatinProvider now uses System.property "java.security.auth.login.config" - JaasAuthenticationCallbackHandler Authentication is passed to handle method setAuthenticatoin removed - Use static HttpServletResponse.SC_UNAUTHORIZED instead of 401 HTTP response code + JaasAuthenticationCallbackHandler Authentication is passed to handle method setAuthentication removed + Added AuthenticationException to the AutenticationEntryPoint.commence method signature + Added AccessDeniedException to the SecurityEncorcementFilter.sendAccessDeniedError method signature Major CVS repository restructure to support Maven and eliminate libraries diff --git a/doc/xdocs/upgrade/upgrade-070-100.html b/doc/xdocs/upgrade/upgrade-070-100.html index e02a2baddc..4274289125 100644 --- a/doc/xdocs/upgrade/upgrade-070-100.html +++ b/doc/xdocs/upgrade/upgrade-070-100.html @@ -9,12 +9,14 @@ The following should help most casual users of the project update their applications: -