Coverage Report - org.apache.shiro.web.filter.AccessControlFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
AccessControlFilter
35%
6/17
0%
0/4
1.091
 
 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;
 20  
 
 21  
 import org.apache.shiro.SecurityUtils;
 22  
 import org.apache.shiro.subject.Subject;
 23  
 import org.apache.shiro.web.util.WebUtils;
 24  
 
 25  
 import javax.servlet.ServletRequest;
 26  
 import javax.servlet.ServletResponse;
 27  
 import java.io.IOException;
 28  
 
 29  
 /**
 30  
  * Superclass for any filter that controls access to a resource and may redirect the user to the login page
 31  
  * if they are not authenticated.  This superclass provides the method
 32  
  * {@link #saveRequestAndRedirectToLogin(javax.servlet.ServletRequest, javax.servlet.ServletResponse)}
 33  
  * which is used by many subclasses as the behavior when a user is unauthenticated.
 34  
  *
 35  
  * @since 0.9
 36  
  */
 37  397
 public abstract class AccessControlFilter extends PathMatchingFilter {
 38  
 
 39  
     /**
 40  
      * Simple default login URL equal to <code>/login.jsp</code>, which can be overridden by calling the
 41  
      * {@link #setLoginUrl(String) setLoginUrl} method.
 42  
      */
 43  
     public static final String DEFAULT_LOGIN_URL = "/login.jsp";
 44  
 
 45  
     /**
 46  
      * Constant representing the HTTP 'GET' request method, equal to <code>GET</code>.
 47  
      */
 48  
     public static final String GET_METHOD = "GET";
 49  
 
 50  
     /**
 51  
      * Constant representing the HTTP 'POST' request method, equal to <code>POST</code>.
 52  
      */
 53  
     public static final String POST_METHOD = "POST";
 54  
 
 55  
     /**
 56  
      * The login url to used to authenticate a user, used when redirecting users if authentication is required.
 57  
      */
 58  397
     private String loginUrl = DEFAULT_LOGIN_URL;
 59  
 
 60  
     /**
 61  
      * Returns the login URL used to authenticate a user.
 62  
      * <p/>
 63  
      * Most Shiro filters use this url
 64  
      * as the location to redirect a user when the filter requires authentication.  Unless overridden, the
 65  
      * {@link #DEFAULT_LOGIN_URL DEFAULT_LOGIN_URL} is assumed, which can be overridden via
 66  
      * {@link #setLoginUrl(String) setLoginUrl}.
 67  
      *
 68  
      * @return the login URL used to authenticate a user, used when redirecting users if authentication is required.
 69  
      */
 70  
     public String getLoginUrl() {
 71  102
         return loginUrl;
 72  
     }
 73  
 
 74  
     /**
 75  
      * Sets the login URL used to authenticate a user.
 76  
      * <p/>
 77  
      * Most Shiro filters use this url as the location to redirect a user when the filter requires
 78  
      * authentication.  Unless overridden, the {@link #DEFAULT_LOGIN_URL DEFAULT_LOGIN_URL} is assumed.
 79  
      *
 80  
      * @param loginUrl the login URL used to authenticate a user, used when redirecting users if authentication is required.
 81  
      */
 82  
     public void setLoginUrl(String loginUrl) {
 83  51
         this.loginUrl = loginUrl;
 84  51
     }
 85  
 
 86  
     /**
 87  
      * Convenience method that acquires the Subject associated with the request.
 88  
      * <p/>
 89  
      * The default implementation simply returns
 90  
      * {@link org.apache.shiro.SecurityUtils#getSubject() SecurityUtils.getSubject()}.
 91  
      *
 92  
      * @param request  the incoming <code>ServletRequest</code>
 93  
      * @param response the outgoing <code>ServletResponse</code>
 94  
      * @return the Subject associated with the request.
 95  
      */
 96  
     protected Subject getSubject(ServletRequest request, ServletResponse response) {
 97  2
         return SecurityUtils.getSubject();
 98  
     }
 99  
 
 100  
     /**
 101  
      * Returns <code>true</code> if the request is allowed to proceed through the filter normally, or <code>false</code>
 102  
      * if the request should be handled by the
 103  
      * {@link #onAccessDenied(ServletRequest,ServletResponse,Object) onAccessDenied(request,response,mappedValue)}
 104  
      * method instead.
 105  
      *
 106  
      * @param request     the incoming <code>ServletRequest</code>
 107  
      * @param response    the outgoing <code>ServletResponse</code>
 108  
      * @param mappedValue the filter-specific config value mapped to this filter in the URL rules mappings.
 109  
      * @return <code>true</code> if the request should proceed through the filter normally, <code>false</code> if the
 110  
      *         request should be processed by this filter's
 111  
      *         {@link #onAccessDenied(ServletRequest,ServletResponse,Object)} method instead.
 112  
      * @throws Exception if an error occurs during processing.
 113  
      */
 114  
     protected abstract boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception;
 115  
 
 116  
     /**
 117  
      * Processes requests where the subject was denied access as determined by the
 118  
      * {@link #isAccessAllowed(javax.servlet.ServletRequest, javax.servlet.ServletResponse, Object) isAccessAllowed}
 119  
      * method, retaining the {@code mappedValue} that was used during configuration.
 120  
      * <p/>
 121  
      * This method immediately delegates to {@link #onAccessDenied(ServletRequest,ServletResponse)} as a
 122  
      * convenience in that most post-denial behavior does not need the mapped config again.
 123  
      *
 124  
      * @param request     the incoming <code>ServletRequest</code>
 125  
      * @param response    the outgoing <code>ServletResponse</code>
 126  
      * @param mappedValue the config specified for the filter in the matching request's filter chain.
 127  
      * @return <code>true</code> if the request should continue to be processed; false if the subclass will
 128  
      *         handle/render the response directly.
 129  
      * @throws Exception if there is an error processing the request.
 130  
      * @since 1.0
 131  
      */
 132  
     protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
 133  0
         return onAccessDenied(request, response);
 134  
     }
 135  
 
 136  
     /**
 137  
      * Processes requests where the subject was denied access as determined by the
 138  
      * {@link #isAccessAllowed(javax.servlet.ServletRequest, javax.servlet.ServletResponse, Object) isAccessAllowed}
 139  
      * method.
 140  
      *
 141  
      * @param request  the incoming <code>ServletRequest</code>
 142  
      * @param response the outgoing <code>ServletResponse</code>
 143  
      * @return <code>true</code> if the request should continue to be processed; false if the subclass will
 144  
      *         handle/render the response directly.
 145  
      * @throws Exception if there is an error processing the request.
 146  
      */
 147  
     protected abstract boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception;
 148  
 
 149  
     /**
 150  
      * Returns <code>true</code> if
 151  
      * {@link #isAccessAllowed(ServletRequest,ServletResponse,Object) isAccessAllowed(Request,Response,Object)},
 152  
      * otherwise returns the result of
 153  
      * {@link #onAccessDenied(ServletRequest,ServletResponse,Object) onAccessDenied(Request,Response,Object)}.
 154  
      *
 155  
      * @return <code>true</code> if
 156  
      *         {@link #isAccessAllowed(javax.servlet.ServletRequest, javax.servlet.ServletResponse, Object) isAccessAllowed},
 157  
      *         otherwise returns the result of
 158  
      *         {@link #onAccessDenied(javax.servlet.ServletRequest, javax.servlet.ServletResponse) onAccessDenied}.
 159  
      * @throws Exception if an error occurs.
 160  
      */
 161  
     public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
 162  0
         return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);
 163  
     }
 164  
 
 165  
     /**
 166  
      * Returns <code>true</code> if the incoming request is a login request, <code>false</code> otherwise.
 167  
      * <p/>
 168  
      * The default implementation merely returns <code>true</code> if the incoming request matches the configured
 169  
      * {@link #getLoginUrl() loginUrl} by calling
 170  
      * <code>{@link #pathsMatch(String, String) pathsMatch(loginUrl, request)}</code>.
 171  
      *
 172  
      * @param request  the incoming <code>ServletRequest</code>
 173  
      * @param response the outgoing <code>ServletResponse</code>
 174  
      * @return <code>true</code> if the incoming request is a login request, <code>false</code> otherwise.
 175  
      */
 176  
     protected boolean isLoginRequest(ServletRequest request, ServletResponse response) {
 177  0
         return pathsMatch(getLoginUrl(), request);
 178  
     }
 179  
 
 180  
     /**
 181  
      * Convenience method for subclasses to use when a login redirect is required.
 182  
      * <p/>
 183  
      * This implementation simply calls {@link #saveRequest(javax.servlet.ServletRequest) saveRequest(request)}
 184  
      * and then {@link #redirectToLogin(javax.servlet.ServletRequest, javax.servlet.ServletResponse) redirectToLogin(request,response)}.
 185  
      *
 186  
      * @param request  the incoming <code>ServletRequest</code>
 187  
      * @param response the outgoing <code>ServletResponse</code>
 188  
      * @throws IOException if an error occurs.
 189  
      */
 190  
     protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
 191  0
         saveRequest(request);
 192  0
         redirectToLogin(request, response);
 193  0
     }
 194  
 
 195  
     /**
 196  
      * Convenience method merely delegates to
 197  
      * {@link WebUtils#saveRequest(javax.servlet.ServletRequest) WebUtils.saveRequest(request)} to save the request
 198  
      * state for reuse later.  This is mostly used to retain user request state when a redirect is issued to
 199  
      * return the user to their originally requested url/resource.
 200  
      * <p/>
 201  
      * If you need to save and then immediately redirect the user to login, consider using
 202  
      * {@link #saveRequestAndRedirectToLogin(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
 203  
      * saveRequestAndRedirectToLogin(request,response)} directly.
 204  
      *
 205  
      * @param request the incoming ServletRequest to save for re-use later (for example, after a redirect).
 206  
      */
 207  
     protected void saveRequest(ServletRequest request) {
 208  0
         WebUtils.saveRequest(request);
 209  0
     }
 210  
 
 211  
     /**
 212  
      * Convenience method for subclasses that merely acquires the {@link #getLoginUrl() getLoginUrl} and redirects
 213  
      * the request to that url.
 214  
      * <p/>
 215  
      * <b>N.B.</b>  If you want to issue a redirect with the intention of allowing the user to then return to their
 216  
      * originally requested URL, don't use this method directly.  Instead you should call
 217  
      * {@link #saveRequestAndRedirectToLogin(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
 218  
      * saveRequestAndRedirectToLogin(request,response)}, which will save the current request state so that it can
 219  
      * be reconstructed and re-used after a successful login.
 220  
      *
 221  
      * @param request  the incoming <code>ServletRequest</code>
 222  
      * @param response the outgoing <code>ServletResponse</code>
 223  
      * @throws IOException if an error occurs.
 224  
      */
 225  
     protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
 226  0
         String loginUrl = getLoginUrl();
 227  0
         WebUtils.issueRedirect(request, response, loginUrl);
 228  0
     }
 229  
 
 230  
 }