diff --git a/core/src/main/java/org/acegisecurity/ui/logout/LogoutFilter.java b/core/src/main/java/org/acegisecurity/ui/logout/LogoutFilter.java new file mode 100644 index 0000000000..3294b337ee --- /dev/null +++ b/core/src/main/java/org/acegisecurity/ui/logout/LogoutFilter.java @@ -0,0 +1,178 @@ +/* Copyright 2004, 2005, 2006 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 org.acegisecurity.ui.logout; + +import org.acegisecurity.Authentication; + +import org.acegisecurity.context.SecurityContextHolder; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.util.Assert; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +/** + * Logs a principal out. + * + *
+ * Polls a series of {@link LogoutHandler}s. The handlers should be specified
+ * in the order they are required. Generally you will want to call logout
+ * handlers TokenBasedRememberMeServices
and
+ * SecurityContextLogoutHandler
(in that order).
+ *
+ * After logout, the URL specified by {@link #logoutSuccessUrl} will be shown. + *
+ * + *
+ * Do not use this class directly. Instead configure
+ * web.xml
to use the {@link
+ * org.acegisecurity.util.FilterToBeanProxy}.
+ *
true
if logout should occur, false
+ * otherwise
+ */
+ protected boolean requiresLogout(HttpServletRequest request,
+ HttpServletResponse response) {
+ String uri = request.getRequestURI();
+ int pathParamIndex = uri.indexOf(';');
+
+ if (pathParamIndex > 0) {
+ // strip everything after the first semi-colon
+ uri = uri.substring(0, pathParamIndex);
+ }
+
+ return uri.endsWith(request.getContextPath() + filterProcessesUrl);
+ }
+
+ /**
+ * Allow subclasses to modify the redirection message.
+ *
+ * @param request the request
+ * @param response the response
+ * @param url the URL to redirect to
+ *
+ * @throws IOException in the event of any failure
+ */
+ protected void sendRedirect(HttpServletRequest request,
+ HttpServletResponse response, String url) throws IOException {
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
+ url = request.getContextPath() + url;
+ }
+
+ response.sendRedirect(response.encodeRedirectURL(url));
+ }
+
+ public void setFilterProcessesUrl(String filterProcessesUrl) {
+ Assert.hasText(filterProcessesUrl, "FilterProcessesUrl required");
+ this.filterProcessesUrl = filterProcessesUrl;
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/ui/logout/LogoutHandler.java b/core/src/main/java/org/acegisecurity/ui/logout/LogoutHandler.java
new file mode 100644
index 0000000000..24c363a850
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/ui/logout/LogoutHandler.java
@@ -0,0 +1,27 @@
+package org.acegisecurity.ui.logout;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.acegisecurity.Authentication;
+
+/**
+ * Indicates a class that is able to participate in logout handling.
+ *
+ *
+ * Called by {@link LogoutFilter}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public interface LogoutHandler {
+
+ /**
+ * Causes a logout to be completed. The method must complete successfully.
+ *
+ * @param request the HTTP request
+ * @param response the HTTP resonse
+ * @param authentication the current principal details
+ */
+ public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication);
+}
diff --git a/core/src/main/java/org/acegisecurity/ui/logout/SecurityContextLogoutHandler.java b/core/src/main/java/org/acegisecurity/ui/logout/SecurityContextLogoutHandler.java
new file mode 100644
index 0000000000..99a5745a40
--- /dev/null
+++ b/core/src/main/java/org/acegisecurity/ui/logout/SecurityContextLogoutHandler.java
@@ -0,0 +1,47 @@
+/* Copyright 2004, 2005, 2006 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 org.acegisecurity.ui.logout;
+
+import org.acegisecurity.Authentication;
+
+import org.acegisecurity.context.SecurityContextHolder;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ * Performs a logout by modifying the {@link
+ * org.acegisecurity.context.SecurityContextHolder}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class SecurityContextLogoutHandler implements LogoutHandler {
+ //~ Methods ================================================================
+
+ /**
+ * Does not use any arguments. They can all be null
.
+ *
+ * @param request not used (can be null
)
+ * @param response not used (can be null
)
+ * @param authentication not used (can be null
)
+ */
+ public void logout(HttpServletRequest request,
+ HttpServletResponse response, Authentication authentication) {
+ SecurityContextHolder.clearContext();
+ }
+}
diff --git a/core/src/main/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServices.java b/core/src/main/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServices.java
index 11b405b020..9a8d08d6e8 100644
--- a/core/src/main/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServices.java
+++ b/core/src/main/java/org/acegisecurity/ui/rememberme/TokenBasedRememberMeServices.java
@@ -21,6 +21,7 @@ import org.acegisecurity.providers.rememberme.RememberMeAuthenticationToken;
import org.acegisecurity.ui.AuthenticationDetailsSource;
import org.acegisecurity.ui.AuthenticationDetailsSourceImpl;
+import org.acegisecurity.ui.logout.LogoutHandler;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
@@ -108,7 +109,7 @@ import javax.servlet.http.HttpServletResponse;
* @version $Id$
*/
public class TokenBasedRememberMeServices implements RememberMeServices,
- InitializingBean {
+ InitializingBean, LogoutHandler {
//~ Static fields/initializers =============================================
public static final String ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY = "ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE";
@@ -340,6 +341,12 @@ public class TokenBasedRememberMeServices implements RememberMeServices,
}
}
+ public void logout(HttpServletRequest request,
+ HttpServletResponse response, Authentication authentication) {
+ cancelCookie(request, response,
+ "Logout of user " + authentication.getName());
+ }
+
protected Cookie makeCancelCookie(HttpServletRequest request) {
Cookie cookie = new Cookie(ACEGI_SECURITY_HASHED_REMEMBER_ME_COOKIE_KEY,
null);
diff --git a/samples/contacts/src/main/webapp/ca/WEB-INF/applicationContext-acegi-security.xml b/samples/contacts/src/main/webapp/ca/WEB-INF/applicationContext-acegi-security.xml
index 6c3eb67a86..f99f5e48fd 100644
--- a/samples/contacts/src/main/webapp/ca/WEB-INF/applicationContext-acegi-security.xml
+++ b/samples/contacts/src/main/webapp/ca/WEB-INF/applicationContext-acegi-security.xml
@@ -21,7 +21,7 @@
+
+
+
+