blob: 3597a524addcdda2a57d3984aed25e215daa402e [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><link rel="stylesheet" href="../jacoco-resources/report.css" type="text/css"/><link rel="shortcut icon" href="../jacoco-resources/report.gif" type="image/gif"/><title>FormAuthenticationFilter.java</title><link rel="stylesheet" href="../jacoco-resources/prettify.css" type="text/css"/><script type="text/javascript" src="../jacoco-resources/prettify.js"></script></head><body onload="window['PR_TAB_WIDTH']=4;prettyPrint()"><div class="breadcrumb" id="breadcrumb"><span class="info"><a href="../jacoco-sessions.html" class="el_session">Sessions</a></span><a href="../index.html" class="el_report">Apache Shiro :: Web</a> &gt; <a href="index.source.html" class="el_package">org.apache.shiro.web.filter.authc</a> &gt; <span class="el_source">FormAuthenticationFilter.java</span></div><h1>FormAuthenticationFilter.java</h1><pre class="source lang-java linenums">/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* &quot;License&quot;); 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
* &quot;AS IS&quot; 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.apache.shiro.web.filter.authc;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* Requires the requesting user to be authenticated for the request to continue, and if they are not, forces the user
* to login via by redirecting them to the {@link #setLoginUrl(String) loginUrl} you configure.
* &lt;p/&gt;
* &lt;p&gt;This filter constructs a {@link UsernamePasswordToken UsernamePasswordToken} with the values found in
* {@link #setUsernameParam(String) username}, {@link #setPasswordParam(String) password},
* and {@link #setRememberMeParam(String) rememberMe} request parameters. It then calls
* {@link org.apache.shiro.subject.Subject#login(org.apache.shiro.authc.AuthenticationToken) Subject.login(usernamePasswordToken)},
* effectively automatically performing a login attempt. Note that the login attempt will only occur when the
* {@link #isLoginSubmission(javax.servlet.ServletRequest, javax.servlet.ServletResponse) isLoginSubmission(request,response)}
* is &lt;code&gt;true&lt;/code&gt;, which by default occurs when the request is for the {@link #setLoginUrl(String) loginUrl} and
* is a POST request.
* &lt;p/&gt;
* &lt;p&gt;If the login attempt fails, the resulting &lt;code&gt;AuthenticationException&lt;/code&gt; fully qualified class name will
* be set as a request attribute under the {@link #setFailureKeyAttribute(String) failureKeyAttribute} key. This
* FQCN can be used as an i18n key or lookup mechanism to explain to the user why their login attempt failed
* (e.g. no account, incorrect password, etc).
* &lt;p/&gt;
* &lt;p&gt;If you would prefer to handle the authentication validation and login in your own code, consider using the
* {@link PassThruAuthenticationFilter} instead, which allows requests to the
* {@link #loginUrl} to pass through to your application's code directly.
*
* @see PassThruAuthenticationFilter
* @since 0.9
*/
public class FormAuthenticationFilter extends AuthenticatingFilter {
//TODO - complete JavaDoc
public static final String DEFAULT_ERROR_KEY_ATTRIBUTE_NAME = &quot;shiroLoginFailure&quot;;
public static final String DEFAULT_USERNAME_PARAM = &quot;username&quot;;
public static final String DEFAULT_PASSWORD_PARAM = &quot;password&quot;;
public static final String DEFAULT_REMEMBER_ME_PARAM = &quot;rememberMe&quot;;
<span class="fc" id="L69"> private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter.class);</span>
<span class="fc" id="L71"> private String usernameParam = DEFAULT_USERNAME_PARAM;</span>
<span class="fc" id="L72"> private String passwordParam = DEFAULT_PASSWORD_PARAM;</span>
<span class="fc" id="L73"> private String rememberMeParam = DEFAULT_REMEMBER_ME_PARAM;</span>
<span class="fc" id="L75"> private String failureKeyAttribute = DEFAULT_ERROR_KEY_ATTRIBUTE_NAME;</span>
<span class="fc" id="L77"> public FormAuthenticationFilter() {</span>
<span class="fc" id="L78"> setLoginUrl(DEFAULT_LOGIN_URL);</span>
<span class="fc" id="L79"> }</span>
@Override
public void setLoginUrl(String loginUrl) {
<span class="fc" id="L83"> String previous = getLoginUrl();</span>
<span class="pc bpc" id="L84" title="1 of 2 branches missed."> if (previous != null) {</span>
<span class="fc" id="L85"> this.appliedPaths.remove(previous);</span>
}
<span class="fc" id="L87"> super.setLoginUrl(loginUrl);</span>
<span class="pc bpc" id="L88" title="1 of 2 branches missed."> if (log.isTraceEnabled()) {</span>
<span class="fc" id="L89"> log.trace(&quot;Adding login url to applied paths.&quot;);</span>
}
<span class="fc" id="L91"> this.appliedPaths.put(getLoginUrl(), null);</span>
<span class="fc" id="L92"> }</span>
public String getUsernameParam() {
<span class="nc" id="L95"> return usernameParam;</span>
}
/**
* Sets the request parameter name to look for when acquiring the username. Unless overridden by calling this
* method, the default is &lt;code&gt;username&lt;/code&gt;.
*
* @param usernameParam the name of the request param to check for acquiring the username.
*/
public void setUsernameParam(String usernameParam) {
<span class="nc" id="L105"> this.usernameParam = usernameParam;</span>
<span class="nc" id="L106"> }</span>
public String getPasswordParam() {
<span class="nc" id="L109"> return passwordParam;</span>
}
/**
* Sets the request parameter name to look for when acquiring the password. Unless overridden by calling this
* method, the default is &lt;code&gt;password&lt;/code&gt;.
*
* @param passwordParam the name of the request param to check for acquiring the password.
*/
public void setPasswordParam(String passwordParam) {
<span class="nc" id="L119"> this.passwordParam = passwordParam;</span>
<span class="nc" id="L120"> }</span>
public String getRememberMeParam() {
<span class="nc" id="L123"> return rememberMeParam;</span>
}
/**
* Sets the request parameter name to look for when acquiring the rememberMe boolean value. Unless overridden
* by calling this method, the default is &lt;code&gt;rememberMe&lt;/code&gt;.
* &lt;p/&gt;
* RememberMe will be &lt;code&gt;true&lt;/code&gt; if the parameter value equals any of those supported by
* {@link org.apache.shiro.web.util.WebUtils#isTrue(javax.servlet.ServletRequest, String) WebUtils.isTrue(request,value)}, &lt;code&gt;false&lt;/code&gt;
* otherwise.
*
* @param rememberMeParam the name of the request param to check for acquiring the rememberMe boolean value.
*/
public void setRememberMeParam(String rememberMeParam) {
<span class="nc" id="L137"> this.rememberMeParam = rememberMeParam;</span>
<span class="nc" id="L138"> }</span>
public String getFailureKeyAttribute() {
<span class="nc" id="L141"> return failureKeyAttribute;</span>
}
public void setFailureKeyAttribute(String failureKeyAttribute) {
<span class="nc" id="L145"> this.failureKeyAttribute = failureKeyAttribute;</span>
<span class="nc" id="L146"> }</span>
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
<span class="nc bnc" id="L149" title="All 2 branches missed."> if (isLoginRequest(request, response)) {</span>
<span class="nc bnc" id="L150" title="All 2 branches missed."> if (isLoginSubmission(request, response)) {</span>
<span class="nc bnc" id="L151" title="All 2 branches missed."> if (log.isTraceEnabled()) {</span>
<span class="nc" id="L152"> log.trace(&quot;Login submission detected. Attempting to execute login.&quot;);</span>
}
<span class="nc" id="L154"> return executeLogin(request, response);</span>
} else {
<span class="nc bnc" id="L156" title="All 2 branches missed."> if (log.isTraceEnabled()) {</span>
<span class="nc" id="L157"> log.trace(&quot;Login page view.&quot;);</span>
}
//allow them to see the login page ;)
<span class="nc" id="L160"> return true;</span>
}
} else {
<span class="nc bnc" id="L163" title="All 2 branches missed."> if (log.isTraceEnabled()) {</span>
<span class="nc" id="L164"> log.trace(&quot;Attempting to access a path which requires authentication. Forwarding to the &quot; +</span>
<span class="nc" id="L165"> &quot;Authentication url [&quot; + getLoginUrl() + &quot;]&quot;);</span>
}
<span class="nc" id="L168"> saveRequestAndRedirectToLogin(request, response);</span>
<span class="nc" id="L169"> return false;</span>
}
}
/**
* This default implementation merely returns &lt;code&gt;true&lt;/code&gt; if the request is an HTTP &lt;code&gt;POST&lt;/code&gt;,
* &lt;code&gt;false&lt;/code&gt; otherwise. Can be overridden by subclasses for custom login submission detection behavior.
*
* @param request the incoming ServletRequest
* @param response the outgoing ServletResponse.
* @return &lt;code&gt;true&lt;/code&gt; if the request is an HTTP &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt; otherwise.
*/
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
protected boolean isLoginSubmission(ServletRequest request, ServletResponse response) {
<span class="nc bnc" id="L183" title="All 4 branches missed."> return (request instanceof HttpServletRequest) &amp;&amp; WebUtils.toHttp(request).getMethod().equalsIgnoreCase(POST_METHOD);</span>
}
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
<span class="nc" id="L187"> String username = getUsername(request);</span>
<span class="nc" id="L188"> String password = getPassword(request);</span>
<span class="nc" id="L189"> return createToken(username, password, request, response);</span>
}
protected boolean isRememberMe(ServletRequest request) {
<span class="nc" id="L193"> return WebUtils.isTrue(request, getRememberMeParam());</span>
}
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
ServletRequest request, ServletResponse response) throws Exception {
<span class="nc" id="L198"> issueSuccessRedirect(request, response);</span>
//we handled the success redirect directly, prevent the chain from continuing:
<span class="nc" id="L200"> return false;</span>
}
protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,
ServletRequest request, ServletResponse response) {
<span class="nc bnc" id="L205" title="All 2 branches missed."> if (log.isDebugEnabled()) {</span>
<span class="nc" id="L206"> log.debug( &quot;Authentication exception&quot;, e );</span>
}
<span class="nc" id="L208"> setFailureAttribute(request, e);</span>
//login failed, let request continue back to the login page:
<span class="nc" id="L210"> return true;</span>
}
protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
<span class="nc" id="L214"> String className = ae.getClass().getName();</span>
<span class="nc" id="L215"> request.setAttribute(getFailureKeyAttribute(), className);</span>
<span class="nc" id="L216"> }</span>
protected String getUsername(ServletRequest request) {
<span class="nc" id="L219"> return WebUtils.getCleanParam(request, getUsernameParam());</span>
}
protected String getPassword(ServletRequest request) {
<span class="nc" id="L223"> return WebUtils.getCleanParam(request, getPasswordParam());</span>
}
}
</pre><div class="footer"><span class="right">Created with <a href="http://www.jacoco.org/jacoco">JaCoCo</a> 0.8.3.201901230119</span></div></body></html>