Coverage Report - org.apache.shiro.web.filter.authc.FormAuthenticationFilter
 
Classes in this File Line Coverage Branch Coverage Complexity
FormAuthenticationFilter
28%
16/56
10%
2/20
1.579
 
 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.authc.AuthenticationException;
 22  
 import org.apache.shiro.authc.AuthenticationToken;
 23  
 import org.apache.shiro.authc.UsernamePasswordToken;
 24  
 import org.apache.shiro.subject.Subject;
 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  
 import javax.servlet.http.HttpServletRequest;
 32  
 
 33  
 
 34  
 /**
 35  
  * Requires the requesting user to be authenticated for the request to continue, and if they are not, forces the user
 36  
  * to login via by redirecting them to the {@link #setLoginUrl(String) loginUrl} you configure.
 37  
  * <p/>
 38  
  * <p>This filter constructs a {@link UsernamePasswordToken UsernamePasswordToken} with the values found in
 39  
  * {@link #setUsernameParam(String) username}, {@link #setPasswordParam(String) password},
 40  
  * and {@link #setRememberMeParam(String) rememberMe} request parameters.  It then calls
 41  
  * {@link org.apache.shiro.subject.Subject#login(org.apache.shiro.authc.AuthenticationToken) Subject.login(usernamePasswordToken)},
 42  
  * effectively automatically performing a login attempt.  Note that the login attempt will only occur when the
 43  
  * {@link #isLoginSubmission(javax.servlet.ServletRequest, javax.servlet.ServletResponse) isLoginSubmission(request,response)}
 44  
  * is <code>true</code>, which by default occurs when the request is for the {@link #setLoginUrl(String) loginUrl} and
 45  
  * is a POST request.
 46  
  * <p/>
 47  
  * <p>If the login attempt fails, the resulting <code>AuthenticationException</code> fully qualified class name will
 48  
  * be set as a request attribute under the {@link #setFailureKeyAttribute(String) failureKeyAttribute} key.  This
 49  
  * FQCN can be used as an i18n key or lookup mechanism to explain to the user why their login attempt failed
 50  
  * (e.g. no account, incorrect password, etc).
 51  
  * <p/>
 52  
  * <p>If you would prefer to handle the authentication validation and login in your own code, consider using the
 53  
  * {@link PassThruAuthenticationFilter} instead, which allows requests to the
 54  
  * {@link #loginUrl} to pass through to your application's code directly.
 55  
  *
 56  
  * @see PassThruAuthenticationFilter
 57  
  * @since 0.9
 58  
  */
 59  
 public class FormAuthenticationFilter extends AuthenticatingFilter {
 60  
 
 61  
     //TODO - complete JavaDoc
 62  
 
 63  
     public static final String DEFAULT_ERROR_KEY_ATTRIBUTE_NAME = "shiroLoginFailure";
 64  
 
 65  
     public static final String DEFAULT_USERNAME_PARAM = "username";
 66  
     public static final String DEFAULT_PASSWORD_PARAM = "password";
 67  
     public static final String DEFAULT_REMEMBER_ME_PARAM = "rememberMe";
 68  
 
 69  1
     private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter.class);
 70  
 
 71  50
     private String usernameParam = DEFAULT_USERNAME_PARAM;
 72  50
     private String passwordParam = DEFAULT_PASSWORD_PARAM;
 73  50
     private String rememberMeParam = DEFAULT_REMEMBER_ME_PARAM;
 74  
 
 75  50
     private String failureKeyAttribute = DEFAULT_ERROR_KEY_ATTRIBUTE_NAME;
 76  
 
 77  50
     public FormAuthenticationFilter() {
 78  50
         setLoginUrl(DEFAULT_LOGIN_URL);
 79  50
     }
 80  
 
 81  
     @Override
 82  
     public void setLoginUrl(String loginUrl) {
 83  51
         String previous = getLoginUrl();
 84  51
         if (previous != null) {
 85  51
             this.appliedPaths.remove(previous);
 86  
         }
 87  51
         super.setLoginUrl(loginUrl);
 88  51
         if (log.isTraceEnabled()) {
 89  51
             log.trace("Adding login url to applied paths.");
 90  
         }
 91  51
         this.appliedPaths.put(getLoginUrl(), null);
 92  51
     }
 93  
 
 94  
     public String getUsernameParam() {
 95  0
         return usernameParam;
 96  
     }
 97  
 
 98  
     /**
 99  
      * Sets the request parameter name to look for when acquiring the username.  Unless overridden by calling this
 100  
      * method, the default is <code>username</code>.
 101  
      *
 102  
      * @param usernameParam the name of the request param to check for acquiring the username.
 103  
      */
 104  
     public void setUsernameParam(String usernameParam) {
 105  0
         this.usernameParam = usernameParam;
 106  0
     }
 107  
 
 108  
     public String getPasswordParam() {
 109  0
         return passwordParam;
 110  
     }
 111  
 
 112  
     /**
 113  
      * Sets the request parameter name to look for when acquiring the password.  Unless overridden by calling this
 114  
      * method, the default is <code>password</code>.
 115  
      *
 116  
      * @param passwordParam the name of the request param to check for acquiring the password.
 117  
      */
 118  
     public void setPasswordParam(String passwordParam) {
 119  0
         this.passwordParam = passwordParam;
 120  0
     }
 121  
 
 122  
     public String getRememberMeParam() {
 123  0
         return rememberMeParam;
 124  
     }
 125  
 
 126  
     /**
 127  
      * Sets the request parameter name to look for when acquiring the rememberMe boolean value.  Unless overridden
 128  
      * by calling this method, the default is <code>rememberMe</code>.
 129  
      * <p/>
 130  
      * RememberMe will be <code>true</code> if the parameter value equals any of those supported by
 131  
      * {@link org.apache.shiro.web.util.WebUtils#isTrue(javax.servlet.ServletRequest, String) WebUtils.isTrue(request,value)}, <code>false</code>
 132  
      * otherwise.
 133  
      *
 134  
      * @param rememberMeParam the name of the request param to check for acquiring the rememberMe boolean value.
 135  
      */
 136  
     public void setRememberMeParam(String rememberMeParam) {
 137  0
         this.rememberMeParam = rememberMeParam;
 138  0
     }
 139  
 
 140  
     public String getFailureKeyAttribute() {
 141  0
         return failureKeyAttribute;
 142  
     }
 143  
 
 144  
     public void setFailureKeyAttribute(String failureKeyAttribute) {
 145  0
         this.failureKeyAttribute = failureKeyAttribute;
 146  0
     }
 147  
 
 148  
     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
 149  0
         if (isLoginRequest(request, response)) {
 150  0
             if (isLoginSubmission(request, response)) {
 151  0
                 if (log.isTraceEnabled()) {
 152  0
                     log.trace("Login submission detected.  Attempting to execute login.");
 153  
                 }
 154  0
                 return executeLogin(request, response);
 155  
             } else {
 156  0
                 if (log.isTraceEnabled()) {
 157  0
                     log.trace("Login page view.");
 158  
                 }
 159  
                 //allow them to see the login page ;)
 160  0
                 return true;
 161  
             }
 162  
         } else {
 163  0
             if (log.isTraceEnabled()) {
 164  0
                 log.trace("Attempting to access a path which requires authentication.  Forwarding to the " +
 165  
                         "Authentication url [" + getLoginUrl() + "]");
 166  
             }
 167  
 
 168  0
             saveRequestAndRedirectToLogin(request, response);
 169  0
             return false;
 170  
         }
 171  
     }
 172  
 
 173  
     /**
 174  
      * This default implementation merely returns <code>true</code> if the request is an HTTP <code>POST</code>,
 175  
      * <code>false</code> otherwise. Can be overridden by subclasses for custom login submission detection behavior.
 176  
      *
 177  
      * @param request  the incoming ServletRequest
 178  
      * @param response the outgoing ServletResponse.
 179  
      * @return <code>true</code> if the request is an HTTP <code>POST</code>, <code>false</code> otherwise.
 180  
      */
 181  
     @SuppressWarnings({"UnusedDeclaration"})
 182  
     protected boolean isLoginSubmission(ServletRequest request, ServletResponse response) {
 183  0
         return (request instanceof HttpServletRequest) && WebUtils.toHttp(request).getMethod().equalsIgnoreCase(POST_METHOD);
 184  
     }
 185  
 
 186  
     protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
 187  0
         String username = getUsername(request);
 188  0
         String password = getPassword(request);
 189  0
         return createToken(username, password, request, response);
 190  
     }
 191  
 
 192  
     protected boolean isRememberMe(ServletRequest request) {
 193  0
         return WebUtils.isTrue(request, getRememberMeParam());
 194  
     }
 195  
 
 196  
     protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
 197  
                                      ServletRequest request, ServletResponse response) throws Exception {
 198  0
         issueSuccessRedirect(request, response);
 199  
         //we handled the success redirect directly, prevent the chain from continuing:
 200  0
         return false;
 201  
     }
 202  
 
 203  
     protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
 204  
                                      ServletRequest request, ServletResponse response) {
 205  0
         if (log.isDebugEnabled()) {
 206  0
             log.debug( "Authentication exception", e );
 207  
         }
 208  0
         setFailureAttribute(request, e);
 209  
         //login failed, let request continue back to the login page:
 210  0
         return true;
 211  
     }
 212  
 
 213  
     protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
 214  0
         String className = ae.getClass().getName();
 215  0
         request.setAttribute(getFailureKeyAttribute(), className);
 216  0
     }
 217  
 
 218  
     protected String getUsername(ServletRequest request) {
 219  0
         return WebUtils.getCleanParam(request, getUsernameParam());
 220  
     }
 221  
 
 222  
     protected String getPassword(ServletRequest request) {
 223  0
         return WebUtils.getCleanParam(request, getPasswordParam());
 224  
     }
 225  
 
 226  
 
 227  
 }