blob: 654672707b773ab91995d43d675cafae8f6c1495 [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>PathMatchingFilter.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</a> &gt; <span class="el_source">PathMatchingFilter.java</span></div><h1>PathMatchingFilter.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;
import org.apache.shiro.util.AntPathMatcher;
import org.apache.shiro.util.PatternMatcher;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.servlet.AdviceFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.Filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.apache.shiro.util.StringUtils.split;
/**
* &lt;p&gt;Base class for Filters that will process only specified paths and allow all others to pass through.&lt;/p&gt;
*
* @since 0.9
*/
<span class="fc" id="L42">public abstract class PathMatchingFilter extends AdviceFilter implements PathConfigProcessor {</span>
/**
* Log available to this class only
*/
<span class="fc" id="L47"> private static final Logger log = LoggerFactory.getLogger(PathMatchingFilter.class);</span>
/**
* PatternMatcher used in determining which paths to react to for a given request.
*/
<span class="fc" id="L52"> protected PatternMatcher pathMatcher = new AntPathMatcher();</span>
/**
* A collection of path-to-config entries where the key is a path which this filter should process and
* the value is the (possibly null) configuration element specific to this Filter for that specific path.
* &lt;p/&gt;
* &lt;p&gt;To put it another way, the keys are the paths (urls) that this Filter will process.
* &lt;p&gt;The values are filter-specific data that this Filter should use when processing the corresponding
* key (path). The values can be null if no Filter-specific config was specified for that url.
*/
<span class="fc" id="L62"> protected Map&lt;String, Object&gt; appliedPaths = new LinkedHashMap&lt;String, Object&gt;();</span>
/**
* Splits any comma-delmited values that might be found in the &lt;code&gt;config&lt;/code&gt; argument and sets the resulting
* &lt;code&gt;String[]&lt;/code&gt; array on the &lt;code&gt;appliedPaths&lt;/code&gt; internal Map.
* &lt;p/&gt;
* That is:
* &lt;pre&gt;&lt;code&gt;
* String[] values = null;
* if (config != null) {
* values = split(config);
* }
* &lt;p/&gt;
* this.{@link #appliedPaths appliedPaths}.put(path, values);
* &lt;/code&gt;&lt;/pre&gt;
*
* @param path the application context path to match for executing this filter.
* @param config the specified for &lt;em&gt;this particular filter only&lt;/em&gt; for the given &lt;code&gt;path&lt;/code&gt;
* @return this configured filter.
*/
public Filter processPathConfig(String path, String config) {
<span class="fc" id="L83"> String[] values = null;</span>
<span class="fc bfc" id="L84" title="All 2 branches covered."> if (config != null) {</span>
<span class="fc" id="L85"> values = split(config);</span>
}
<span class="fc" id="L88"> this.appliedPaths.put(path, values);</span>
<span class="fc" id="L89"> return this;</span>
}
/**
* Returns the context path within the application based on the specified &lt;code&gt;request&lt;/code&gt;.
* &lt;p/&gt;
* This implementation merely delegates to
* {@link WebUtils#getPathWithinApplication(javax.servlet.http.HttpServletRequest) WebUtils.getPathWithinApplication(request)},
* but can be overridden by subclasses for custom logic.
*
* @param request the incoming &lt;code&gt;ServletRequest&lt;/code&gt;
* @return the context path within the application.
*/
protected String getPathWithinApplication(ServletRequest request) {
<span class="fc" id="L103"> return WebUtils.getPathWithinApplication(WebUtils.toHttp(request));</span>
}
/**
* Returns &lt;code&gt;true&lt;/code&gt; if the incoming &lt;code&gt;request&lt;/code&gt; matches the specified &lt;code&gt;path&lt;/code&gt; pattern,
* &lt;code&gt;false&lt;/code&gt; otherwise.
* &lt;p/&gt;
* The default implementation acquires the &lt;code&gt;request&lt;/code&gt;'s path within the application and determines
* if that matches:
* &lt;p/&gt;
* &lt;code&gt;String requestURI = {@link #getPathWithinApplication(javax.servlet.ServletRequest) getPathWithinApplication(request)};&lt;br/&gt;
* return {@link #pathsMatch(String, String) pathsMatch(path,requestURI)}&lt;/code&gt;
*
* @param path the configured url pattern to check the incoming request against.
* @param request the incoming ServletRequest
* @return &lt;code&gt;true&lt;/code&gt; if the incoming &lt;code&gt;request&lt;/code&gt; matches the specified &lt;code&gt;path&lt;/code&gt; pattern,
* &lt;code&gt;false&lt;/code&gt; otherwise.
*/
protected boolean pathsMatch(String path, ServletRequest request) {
<span class="fc" id="L122"> String requestURI = getPathWithinApplication(request);</span>
<span class="fc" id="L123"> log.trace(&quot;Attempting to match pattern '{}' with current requestURI '{}'...&quot;, path, requestURI);</span>
<span class="fc" id="L124"> return pathsMatch(path, requestURI);</span>
}
/**
* Returns &lt;code&gt;true&lt;/code&gt; if the &lt;code&gt;path&lt;/code&gt; matches the specified &lt;code&gt;pattern&lt;/code&gt; string,
* &lt;code&gt;false&lt;/code&gt; otherwise.
* &lt;p/&gt;
* Simply delegates to
* &lt;b&gt;&lt;code&gt;this.pathMatcher.{@link PatternMatcher#matches(String, String) matches(pattern,path)}&lt;/code&gt;&lt;/b&gt;,
* but can be overridden by subclasses for custom matching behavior.
*
* @param pattern the pattern to match against
* @param path the value to match with the specified &lt;code&gt;pattern&lt;/code&gt;
* @return &lt;code&gt;true&lt;/code&gt; if the &lt;code&gt;path&lt;/code&gt; matches the specified &lt;code&gt;pattern&lt;/code&gt; string,
* &lt;code&gt;false&lt;/code&gt; otherwise.
*/
protected boolean pathsMatch(String pattern, String path) {
<span class="fc" id="L141"> return pathMatcher.matches(pattern, path);</span>
}
/**
* Implementation that handles path-matching behavior before a request is evaluated. If the path matches and
* the filter
* {@link #isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse, String, Object) isEnabled} for
* that path/config, the request will be allowed through via the result from
* {@link #onPreHandle(javax.servlet.ServletRequest, javax.servlet.ServletResponse, Object) onPreHandle}. If the
* path does not match or the filter is not enabled for that path, this filter will allow passthrough immediately
* to allow the {@code FilterChain} to continue executing.
* &lt;p/&gt;
* In order to retain path-matching functionality, subclasses should not override this method if at all
* possible, and instead override
* {@link #onPreHandle(javax.servlet.ServletRequest, javax.servlet.ServletResponse, Object) onPreHandle} instead.
*
* @param request the incoming ServletRequest
* @param response the outgoing ServletResponse
* @return {@code true} if the filter chain is allowed to continue to execute, {@code false} if a subclass has
* handled the request explicitly.
* @throws Exception if an error occurs
*/
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
<span class="pc bpc" id="L165" title="2 of 4 branches missed."> if (this.appliedPaths == null || this.appliedPaths.isEmpty()) {</span>
<span class="nc bnc" id="L166" title="All 2 branches missed."> if (log.isTraceEnabled()) {</span>
<span class="nc" id="L167"> log.trace(&quot;appliedPaths property is null or empty. This Filter will passthrough immediately.&quot;);</span>
}
<span class="nc" id="L169"> return true;</span>
}
<span class="pc bpc" id="L172" title="1 of 2 branches missed."> for (String path : this.appliedPaths.keySet()) {</span>
// If the path does match, then pass on to the subclass implementation for specific checks
//(first match 'wins'):
<span class="fc bfc" id="L175" title="All 2 branches covered."> if (pathsMatch(path, request)) {</span>
<span class="fc" id="L176"> log.trace(&quot;Current requestURI matches pattern '{}'. Determining filter chain execution...&quot;, path);</span>
<span class="fc" id="L177"> Object config = this.appliedPaths.get(path);</span>
<span class="fc" id="L178"> return isFilterChainContinued(request, response, path, config);</span>
}
<span class="fc" id="L180"> }</span>
//no path matched, allow the request to go through:
<span class="nc" id="L183"> return true;</span>
}
/**
* Simple method to abstract out logic from the preHandle implementation - it was getting a bit unruly.
*
* @since 1.2
*/
@SuppressWarnings({&quot;JavaDoc&quot;})
private boolean isFilterChainContinued(ServletRequest request, ServletResponse response,
String path, Object pathConfig) throws Exception {
<span class="fc bfc" id="L195" title="All 2 branches covered."> if (isEnabled(request, response, path, pathConfig)) { //isEnabled check added in 1.2</span>
<span class="pc bpc" id="L196" title="1 of 2 branches missed."> if (log.isTraceEnabled()) {</span>
<span class="fc" id="L197"> log.trace(&quot;Filter '{}' is enabled for the current request under path '{}' with config [{}]. &quot; +</span>
&quot;Delegating to subclass implementation for 'onPreHandle' check.&quot;,
<span class="fc" id="L199"> new Object[]{getName(), path, pathConfig});</span>
}
//The filter is enabled for this specific request, so delegate to subclass implementations
//so they can decide if the request should continue through the chain or not:
<span class="fc" id="L203"> return onPreHandle(request, response, pathConfig);</span>
}
<span class="pc bpc" id="L206" title="1 of 2 branches missed."> if (log.isTraceEnabled()) {</span>
<span class="fc" id="L207"> log.trace(&quot;Filter '{}' is disabled for the current request under path '{}' with config [{}]. &quot; +</span>
&quot;The next element in the FilterChain will be called immediately.&quot;,
<span class="fc" id="L209"> new Object[]{getName(), path, pathConfig});</span>
}
//This filter is disabled for this specific request,
//return 'true' immediately to indicate that the filter will not process the request
//and let the request/response to continue through the filter chain:
<span class="fc" id="L214"> return true;</span>
}
/**
* This default implementation always returns {@code true} and should be overridden by subclasses for custom
* logic if necessary.
*
* @param request the incoming ServletRequest
* @param response the outgoing ServletResponse
* @param mappedValue the filter-specific config value mapped to this filter in the URL rules mappings.
* @return {@code true} if the request should be able to continue, {@code false} if the filter will
* handle the response directly.
* @throws Exception if an error occurs
* @see #isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse, String, Object)
*/
protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
<span class="nc" id="L230"> return true;</span>
}
/**
* Path-matching version of the parent class's
* {@link #isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse)} method, but additionally allows
* for inspection of any path-specific configuration values corresponding to the specified request. Subclasses
* may wish to inspect this additional mapped configuration to determine if the filter is enabled or not.
* &lt;p/&gt;
* This method's default implementation ignores the {@code path} and {@code mappedValue} arguments and merely
* returns the value from a call to {@link #isEnabled(javax.servlet.ServletRequest, javax.servlet.ServletResponse)}.
* It is expected that subclasses override this method if they need to perform enable/disable logic for a specific
* request based on any path-specific config for the filter instance.
*
* @param request the incoming servlet request
* @param response the outbound servlet response
* @param path the path matched for the incoming servlet request that has been configured with the given {@code mappedValue}.
* @param mappedValue the filter-specific config value mapped to this filter in the URL rules mappings for the given {@code path}.
* @return {@code true} if this filter should filter the specified request, {@code false} if it should let the
* request/response pass through immediately to the next element in the {@code FilterChain}.
* @throws Exception in the case of any error
* @since 1.2
*/
@SuppressWarnings({&quot;UnusedParameters&quot;})
protected boolean isEnabled(ServletRequest request, ServletResponse response, String path, Object mappedValue)
throws Exception {
<span class="nc" id="L256"> return isEnabled(request, response);</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>