View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.shiro.web.filter.authc;
20  
21  import org.apache.shiro.SecurityUtils;
22  import org.apache.shiro.session.SessionException;
23  import org.apache.shiro.subject.Subject;
24  import org.apache.shiro.web.servlet.AdviceFilter;
25  import org.apache.shiro.web.util.WebUtils;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  import javax.servlet.ServletRequest;
30  import javax.servlet.ServletResponse;
31  
32  /**
33   * Simple Filter that, upon receiving a request, will immediately log-out the currently executing
34   * {@link #getSubject(javax.servlet.ServletRequest, javax.servlet.ServletResponse) subject}
35   * and then redirect them to a configured {@link #getRedirectUrl() redirectUrl}.
36   *
37   * @since 1.2
38   */
39  public class LogoutFilter extends AdviceFilter {
40      
41      private static final Logger log = LoggerFactory.getLogger(LogoutFilter.class);
42  
43      /**
44       * The default redirect URL to where the user will be redirected after logout.  The value is {@code "/"}, Shiro's
45       * representation of the web application's context root.
46       */
47      public static final String DEFAULT_REDIRECT_URL = "/";
48  
49      /**
50       * The URL to where the user will be redirected after logout.
51       */
52      private String redirectUrl = DEFAULT_REDIRECT_URL;
53  
54      /**
55       * Acquires the currently executing {@link #getSubject(javax.servlet.ServletRequest, javax.servlet.ServletResponse) subject},
56       * a potentially Subject or request-specific
57       * {@link #getRedirectUrl(javax.servlet.ServletRequest, javax.servlet.ServletResponse, org.apache.shiro.subject.Subject) redirectUrl},
58       * and redirects the end-user to that redirect url.
59       *
60       * @param request  the incoming ServletRequest
61       * @param response the outgoing ServletResponse
62       * @return {@code false} always as typically no further interaction should be done after user logout.
63       * @throws Exception if there is any error.
64       */
65      @Override
66      protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
67          Subject subject = getSubject(request, response);
68          String redirectUrl = getRedirectUrl(request, response, subject);
69          //try/catch added for SHIRO-298:
70          try {
71              subject.logout();
72          } catch (SessionException ise) {
73              log.debug("Encountered session exception during logout.  This can generally safely be ignored.", ise);
74          }
75          issueRedirect(request, response, redirectUrl);
76          return false;
77      }
78  
79      /**
80       * Returns the currently executing {@link Subject}.  This implementation merely defaults to calling
81       * {@code SecurityUtils.}{@link org.apache.shiro.SecurityUtils#getSubject() getSubject()}, but can be overridden
82       * by subclasses for different retrieval strategies.
83       *
84       * @param request  the incoming Servlet request
85       * @param response the outgoing Servlet response
86       * @return the currently executing {@link Subject}.
87       */
88      protected Subject getSubject(ServletRequest request, ServletResponse response) {
89          return SecurityUtils.getSubject();
90      }
91  
92      /**
93       * Issues an HTTP redirect to the specified URL after subject logout.  This implementation simply calls
94       * {@code WebUtils.}{@link WebUtils#issueRedirect(javax.servlet.ServletRequest, javax.servlet.ServletResponse, String) issueRedirect(request,response,redirectUrl)}.
95       *
96       * @param request  the incoming Servlet request
97       * @param response the outgoing Servlet response
98       * @param redirectUrl the URL to where the browser will be redirected immediately after Subject logout.
99       * @throws Exception if there is any error.
100      */
101     protected void issueRedirect(ServletRequest request, ServletResponse response, String redirectUrl) throws Exception {
102         WebUtils.issueRedirect(request, response, redirectUrl);
103     }
104 
105     /**
106      * Returns the redirect URL to send the user after logout.  This default implementation ignores the arguments and
107      * returns the static configured {@link #getRedirectUrl() redirectUrl} property, but this method may be overridden
108      * by subclasses to dynamically construct the URL based on the request or subject if necessary.
109      * <p/>
110      * Note: the Subject is <em>not</em> yet logged out at the time this method is invoked.  You may access the Subject's
111      * session if one is available and if necessary.
112      * <p/>
113      * Tip: if you need to access the Subject's session, consider using the
114      * {@code Subject.}{@link Subject#getSession(boolean) getSession(false)} method to ensure a new session isn't created unnecessarily.
115      * If a session would be created, it will be immediately stopped after logout, not providing any value and
116      * unnecessarily taxing session infrastructure/resources.
117      *
118      * @param request the incoming Servlet request
119      * @param response the outgoing ServletResponse
120      * @param subject the not-yet-logged-out currently executing Subject
121      * @return the redirect URL to send the user after logout.
122      */
123     protected String getRedirectUrl(ServletRequest request, ServletResponse response, Subject subject) {
124         return getRedirectUrl();
125     }
126 
127     /**
128      * Returns the URL to where the user will be redirected after logout.  Default is the web application's context
129      * root, i.e. {@code "/"}
130      *
131      * @return the URL to where the user will be redirected after logout.
132      */
133     public String getRedirectUrl() {
134         return redirectUrl;
135     }
136 
137     /**
138      * Sets the URL to where the user will be redirected after logout.  Default is the web application's context
139      * root, i.e. {@code "/"}
140      *
141      * @param redirectUrl the url to where the user will be redirected after logout
142      */
143     public void setRedirectUrl(String redirectUrl) {
144         this.redirectUrl = redirectUrl;
145     }
146 }