| <?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>ShiroFilterFactoryBean.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 :: Support :: Spring</a> > <a href="index.source.html" class="el_package">org.apache.shiro.spring.web</a> > <span class="el_source">ShiroFilterFactoryBean.java</span></div><h1>ShiroFilterFactoryBean.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 |
| * "License"); 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 |
| * "AS IS" 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.spring.web; |
| |
| import org.apache.shiro.config.Ini; |
| import org.apache.shiro.mgt.SecurityManager; |
| import org.apache.shiro.util.CollectionUtils; |
| import org.apache.shiro.util.Nameable; |
| import org.apache.shiro.util.StringUtils; |
| import org.apache.shiro.web.config.IniFilterChainResolverFactory; |
| import org.apache.shiro.web.filter.AccessControlFilter; |
| import org.apache.shiro.web.filter.authc.AuthenticationFilter; |
| import org.apache.shiro.web.filter.authz.AuthorizationFilter; |
| import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager; |
| import org.apache.shiro.web.filter.mgt.FilterChainManager; |
| import org.apache.shiro.web.filter.mgt.FilterChainResolver; |
| import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver; |
| import org.apache.shiro.web.mgt.WebSecurityManager; |
| import org.apache.shiro.web.servlet.AbstractShiroFilter; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| import org.springframework.beans.BeansException; |
| import org.springframework.beans.factory.BeanInitializationException; |
| import org.springframework.beans.factory.FactoryBean; |
| import org.springframework.beans.factory.config.BeanPostProcessor; |
| |
| import javax.servlet.Filter; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| |
| /** |
| * {@link org.springframework.beans.factory.FactoryBean FactoryBean} to be used in Spring-based web applications for |
| * defining the master Shiro Filter. |
| * <h4>Usage</h4> |
| * Declare a DelegatingFilterProxy in {@code web.xml}, matching the filter name to the bean id: |
| * <pre> |
| * &lt;filter&gt; |
| * &lt;filter-name&gt;<b>shiroFilter</b>&lt;/filter-name&gt; |
| * &lt;filter-class&gt;org.springframework.web.filter.DelegatingFilterProxy&lt;filter-class&gt; |
| * &lt;init-param&gt; |
| * &lt;param-name&gt;targetFilterLifecycle&lt;/param-name&gt; |
| * &lt;param-value&gt;true&lt;/param-value&gt; |
| * &lt;/init-param&gt; |
| * &lt;/filter&gt; |
| * </pre> |
| * Then, in your spring XML file that defines your web ApplicationContext: |
| * <pre> |
| * &lt;bean id="<b>shiroFilter</b>" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"&gt; |
| * &lt;property name="securityManager" ref="securityManager"/&gt; |
| * &lt;!-- other properties as necessary ... --&gt; |
| * &lt;/bean&gt; |
| * </pre> |
| * <h4>Filter Auto-Discovery</h4> |
| * While there is a {@link #setFilters(java.util.Map) filters} property that allows you to assign a filter beans |
| * to the 'pool' of filters available when defining {@link #setFilterChainDefinitions(String) filter chains}, it is |
| * optional. |
| * <p/> |
| * This implementation is also a {@link BeanPostProcessor} and will acquire |
| * any {@link javax.servlet.Filter Filter} beans defined independently in your Spring application context. Upon |
| * discovery, they will be automatically added to the {@link #setFilters(java.util.Map) map} keyed by the bean ID. |
| * That ID can then be used in the filter chain definitions, for example: |
| * |
| * <pre> |
| * &lt;bean id="<b>myCustomFilter</b>" class="com.class.that.implements.javax.servlet.Filter"/&gt; |
| * ... |
| * &lt;bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"&gt; |
| * ... |
| * &lt;property name="filterChainDefinitions"&gt; |
| * &lt;value&gt; |
| * /some/path/** = authc, <b>myCustomFilter</b> |
| * &lt;/value&gt; |
| * &lt;/property&gt; |
| * &lt;/bean&gt; |
| * </pre> |
| * <h4>Global Property Values</h4> |
| * Most Shiro servlet Filter implementations exist for defining custom Filter |
| * {@link #setFilterChainDefinitions(String) chain definitions}. Most implementations subclass one of the |
| * {@link AccessControlFilter}, {@link AuthenticationFilter}, {@link AuthorizationFilter} classes to simplify things, |
| * and each of these 3 classes has configurable properties that are application-specific. |
| * <p/> |
| * A dilemma arises where, if you want to for example set the application's 'loginUrl' for any Filter, you don't want |
| * to have to manually specify that value for <em>each</em> filter instance definied. |
| * <p/> |
| * To prevent configuration duplication, this implementation provides the following properties to allow you |
| * to set relevant values in only one place: |
| * <ul> |
| * <li>{@link #setLoginUrl(String)}</li> |
| * <li>{@link #setSuccessUrl(String)}</li> |
| * <li>{@link #setUnauthorizedUrl(String)}</li> |
| * </ul> |
| * |
| * Then at startup, any values specified via these 3 properties will be applied to all configured |
| * Filter instances so you don't have to specify them individually on each filter instance. To ensure your own custom |
| * filters benefit from this convenience, your filter implementation should subclass one of the 3 mentioned |
| * earlier. |
| * |
| * @see org.springframework.web.filter.DelegatingFilterProxy DelegatingFilterProxy |
| * @since 1.0 |
| */ |
| public class ShiroFilterFactoryBean implements FactoryBean, BeanPostProcessor { |
| |
| <span class="fc" id="L118"> private static transient final Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.class);</span> |
| |
| private SecurityManager securityManager; |
| |
| private Map<String, Filter> filters; |
| |
| private Map<String, String> filterChainDefinitionMap; //urlPathExpression_to_comma-delimited-filter-chain-definition |
| |
| private String loginUrl; |
| private String successUrl; |
| private String unauthorizedUrl; |
| |
| private AbstractShiroFilter instance; |
| |
| <span class="fc" id="L132"> public ShiroFilterFactoryBean() {</span> |
| <span class="fc" id="L133"> this.filters = new LinkedHashMap<String, Filter>();</span> |
| <span class="fc" id="L134"> this.filterChainDefinitionMap = new LinkedHashMap<String, String>(); //order matters!</span> |
| <span class="fc" id="L135"> }</span> |
| |
| /** |
| * Sets the application {@code SecurityManager} instance to be used by the constructed Shiro Filter. This is a |
| * required property - failure to set it will throw an initialization exception. |
| * |
| * @return the application {@code SecurityManager} instance to be used by the constructed Shiro Filter. |
| */ |
| public SecurityManager getSecurityManager() { |
| <span class="fc" id="L144"> return securityManager;</span> |
| } |
| |
| /** |
| * Sets the application {@code SecurityManager} instance to be used by the constructed Shiro Filter. This is a |
| * required property - failure to set it will throw an initialization exception. |
| * |
| * @param securityManager the application {@code SecurityManager} instance to be used by the constructed Shiro Filter. |
| */ |
| public void setSecurityManager(SecurityManager securityManager) { |
| <span class="fc" id="L154"> this.securityManager = securityManager;</span> |
| <span class="fc" id="L155"> }</span> |
| |
| /** |
| * Returns the application's login URL to be assigned to all acquired Filters that subclass |
| * {@link AccessControlFilter} or {@code null} if no value should be assigned globally. The default value |
| * is {@code null}. |
| * |
| * @return the application's login URL to be assigned to all acquired Filters that subclass |
| * {@link AccessControlFilter} or {@code null} if no value should be assigned globally. |
| * @see #setLoginUrl |
| */ |
| public String getLoginUrl() { |
| <span class="fc" id="L167"> return loginUrl;</span> |
| } |
| |
| /** |
| * Sets the application's login URL to be assigned to all acquired Filters that subclass |
| * {@link AccessControlFilter}. This is a convenience mechanism: for all configured {@link #setFilters filters}, |
| * as well for any default ones ({@code authc}, {@code user}, etc), this value will be passed on to each Filter |
| * via the {@link AccessControlFilter#setLoginUrl(String)} method<b>*</b>. This eliminates the need to |
| * configure the 'loginUrl' property manually on each filter instance, and instead that can be configured once |
| * via this attribute. |
| * <p/> |
| * <b>*</b>If a filter already has already been explicitly configured with a value, it will |
| * <em>not</em> receive this value. Individual filter configuration overrides this global convenience property. |
| * |
| * @param loginUrl the application's login URL to apply to as a convenience to all discovered |
| * {@link AccessControlFilter} instances. |
| * @see AccessControlFilter#setLoginUrl(String) |
| */ |
| public void setLoginUrl(String loginUrl) { |
| <span class="nc" id="L186"> this.loginUrl = loginUrl;</span> |
| <span class="nc" id="L187"> }</span> |
| |
| /** |
| * Returns the application's after-login success URL to be assigned to all acquired Filters that subclass |
| * {@link AuthenticationFilter} or {@code null} if no value should be assigned globally. The default value |
| * is {@code null}. |
| * |
| * @return the application's after-login success URL to be assigned to all acquired Filters that subclass |
| * {@link AuthenticationFilter} or {@code null} if no value should be assigned globally. |
| * @see #setSuccessUrl |
| */ |
| public String getSuccessUrl() { |
| <span class="fc" id="L199"> return successUrl;</span> |
| } |
| |
| /** |
| * Sets the application's after-login success URL to be assigned to all acquired Filters that subclass |
| * {@link AuthenticationFilter}. This is a convenience mechanism: for all configured {@link #setFilters filters}, |
| * as well for any default ones ({@code authc}, {@code user}, etc), this value will be passed on to each Filter |
| * via the {@link AuthenticationFilter#setSuccessUrl(String)} method<b>*</b>. This eliminates the need to |
| * configure the 'successUrl' property manually on each filter instance, and instead that can be configured once |
| * via this attribute. |
| * <p/> |
| * <b>*</b>If a filter already has already been explicitly configured with a value, it will |
| * <em>not</em> receive this value. Individual filter configuration overrides this global convenience property. |
| * |
| * @param successUrl the application's after-login success URL to apply to as a convenience to all discovered |
| * {@link AccessControlFilter} instances. |
| * @see AuthenticationFilter#setSuccessUrl(String) |
| */ |
| public void setSuccessUrl(String successUrl) { |
| <span class="nc" id="L218"> this.successUrl = successUrl;</span> |
| <span class="nc" id="L219"> }</span> |
| |
| /** |
| * Returns the application's after-login success URL to be assigned to all acquired Filters that subclass |
| * {@link AuthenticationFilter} or {@code null} if no value should be assigned globally. The default value |
| * is {@code null}. |
| * |
| * @return the application's after-login success URL to be assigned to all acquired Filters that subclass |
| * {@link AuthenticationFilter} or {@code null} if no value should be assigned globally. |
| * @see #setSuccessUrl |
| */ |
| public String getUnauthorizedUrl() { |
| <span class="fc" id="L231"> return unauthorizedUrl;</span> |
| } |
| |
| /** |
| * Sets the application's 'unauthorized' URL to be assigned to all acquired Filters that subclass |
| * {@link AuthorizationFilter}. This is a convenience mechanism: for all configured {@link #setFilters filters}, |
| * as well for any default ones ({@code roles}, {@code perms}, etc), this value will be passed on to each Filter |
| * via the {@link AuthorizationFilter#setUnauthorizedUrl(String)} method<b>*</b>. This eliminates the need to |
| * configure the 'unauthorizedUrl' property manually on each filter instance, and instead that can be configured once |
| * via this attribute. |
| * <p/> |
| * <b>*</b>If a filter already has already been explicitly configured with a value, it will |
| * <em>not</em> receive this value. Individual filter configuration overrides this global convenience property. |
| * |
| * @param unauthorizedUrl the application's 'unauthorized' URL to apply to as a convenience to all discovered |
| * {@link AuthorizationFilter} instances. |
| * @see AuthorizationFilter#setUnauthorizedUrl(String) |
| */ |
| public void setUnauthorizedUrl(String unauthorizedUrl) { |
| <span class="nc" id="L250"> this.unauthorizedUrl = unauthorizedUrl;</span> |
| <span class="nc" id="L251"> }</span> |
| |
| /** |
| * Returns the filterName-to-Filter map of filters available for reference when defining filter chain definitions. |
| * All filter chain definitions will reference filters by the names in this map (i.e. the keys). |
| * |
| * @return the filterName-to-Filter map of filters available for reference when defining filter chain definitions. |
| */ |
| public Map<String, Filter> getFilters() { |
| <span class="fc" id="L260"> return filters;</span> |
| } |
| |
| /** |
| * Sets the filterName-to-Filter map of filters available for reference when creating |
| * {@link #setFilterChainDefinitionMap(java.util.Map) filter chain definitions}. |
| * <p/> |
| * <b>Note:</b> This property is optional: this {@code FactoryBean} implementation will discover all beans in the |
| * web application context that implement the {@link Filter} interface and automatically add them to this filter |
| * map under their bean name. |
| * <p/> |
| * For example, just defining this bean in a web Spring XML application context: |
| * <pre> |
| * &lt;bean id=&quot;myFilter&quot; class=&quot;com.class.that.implements.javax.servlet.Filter&quot;&gt; |
| * ... |
| * &lt;/bean&gt;</pre> |
| * Will automatically place that bean into this Filters map under the key '<b>myFilter</b>'. |
| * |
| * @param filters the optional filterName-to-Filter map of filters available for reference when creating |
| * {@link #setFilterChainDefinitionMap (java.util.Map) filter chain definitions}. |
| */ |
| public void setFilters(Map<String, Filter> filters) { |
| <span class="nc" id="L282"> this.filters = filters;</span> |
| <span class="nc" id="L283"> }</span> |
| |
| /** |
| * Returns the chainName-to-chainDefinition map of chain definitions to use for creating filter chains intercepted |
| * by the Shiro Filter. Each map entry should conform to the format defined by the |
| * {@link FilterChainManager#createChain(String, String)} JavaDoc, where the map key is the chain name (e.g. URL |
| * path expression) and the map value is the comma-delimited string chain definition. |
| * |
| * @return he chainName-to-chainDefinition map of chain definitions to use for creating filter chains intercepted |
| * by the Shiro Filter. |
| */ |
| public Map<String, String> getFilterChainDefinitionMap() { |
| <span class="fc" id="L295"> return filterChainDefinitionMap;</span> |
| } |
| |
| /** |
| * Sets the chainName-to-chainDefinition map of chain definitions to use for creating filter chains intercepted |
| * by the Shiro Filter. Each map entry should conform to the format defined by the |
| * {@link FilterChainManager#createChain(String, String)} JavaDoc, where the map key is the chain name (e.g. URL |
| * path expression) and the map value is the comma-delimited string chain definition. |
| * |
| * @param filterChainDefinitionMap the chainName-to-chainDefinition map of chain definitions to use for creating |
| * filter chains intercepted by the Shiro Filter. |
| */ |
| public void setFilterChainDefinitionMap(Map<String, String> filterChainDefinitionMap) { |
| <span class="fc" id="L308"> this.filterChainDefinitionMap = filterChainDefinitionMap;</span> |
| <span class="fc" id="L309"> }</span> |
| |
| /** |
| * A convenience method that sets the {@link #setFilterChainDefinitionMap(java.util.Map) filterChainDefinitionMap} |
| * property by accepting a {@link java.util.Properties Properties}-compatible string (multi-line key/value pairs). |
| * Each key/value pair must conform to the format defined by the |
| * {@link FilterChainManager#createChain(String,String)} JavaDoc - each property key is an ant URL |
| * path expression and the value is the comma-delimited chain definition. |
| * |
| * @param definitions a {@link java.util.Properties Properties}-compatible string (multi-line key/value pairs) |
| * where each key/value pair represents a single urlPathExpression-commaDelimitedChainDefinition. |
| */ |
| public void setFilterChainDefinitions(String definitions) { |
| <span class="fc" id="L322"> Ini ini = new Ini();</span> |
| <span class="fc" id="L323"> ini.load(definitions);</span> |
| //did they explicitly state a 'urls' section? Not necessary, but just in case: |
| <span class="fc" id="L325"> Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);</span> |
| <span class="pc bpc" id="L326" title="1 of 2 branches missed."> if (CollectionUtils.isEmpty(section)) {</span> |
| //no urls section. Since this _is_ a urls chain definition property, just assume the |
| //default section contains only the definitions: |
| <span class="fc" id="L329"> section = ini.getSection(Ini.DEFAULT_SECTION_NAME);</span> |
| } |
| <span class="fc" id="L331"> setFilterChainDefinitionMap(section);</span> |
| <span class="fc" id="L332"> }</span> |
| |
| /** |
| * Lazily creates and returns a {@link AbstractShiroFilter} concrete instance via the |
| * {@link #createInstance} method. |
| * |
| * @return the application's Shiro Filter instance used to filter incoming web requests. |
| * @throws Exception if there is a problem creating the {@code Filter} instance. |
| */ |
| public Object getObject() throws Exception { |
| <span class="pc bpc" id="L342" title="1 of 2 branches missed."> if (instance == null) {</span> |
| <span class="fc" id="L343"> instance = createInstance();</span> |
| } |
| <span class="fc" id="L345"> return instance;</span> |
| } |
| |
| /** |
| * Returns <code>{@link org.apache.shiro.web.servlet.AbstractShiroFilter}.class</code> |
| * |
| * @return <code>{@link org.apache.shiro.web.servlet.AbstractShiroFilter}.class</code> |
| */ |
| public Class getObjectType() { |
| <span class="fc" id="L354"> return SpringShiroFilter.class;</span> |
| } |
| |
| /** |
| * Returns {@code true} always. There is almost always only ever 1 Shiro {@code Filter} per web application. |
| * |
| * @return {@code true} always. There is almost always only ever 1 Shiro {@code Filter} per web application. |
| */ |
| public boolean isSingleton() { |
| <span class="fc" id="L363"> return true;</span> |
| } |
| |
| protected FilterChainManager createFilterChainManager() { |
| |
| <span class="fc" id="L368"> DefaultFilterChainManager manager = new DefaultFilterChainManager();</span> |
| <span class="fc" id="L369"> Map<String, Filter> defaultFilters = manager.getFilters();</span> |
| //apply global settings if necessary: |
| <span class="fc bfc" id="L371" title="All 2 branches covered."> for (Filter filter : defaultFilters.values()) {</span> |
| <span class="fc" id="L372"> applyGlobalPropertiesIfNecessary(filter);</span> |
| <span class="fc" id="L373"> }</span> |
| |
| //Apply the acquired and/or configured filters: |
| <span class="fc" id="L376"> Map<String, Filter> filters = getFilters();</span> |
| <span class="pc bpc" id="L377" title="1 of 2 branches missed."> if (!CollectionUtils.isEmpty(filters)) {</span> |
| <span class="fc bfc" id="L378" title="All 2 branches covered."> for (Map.Entry<String, Filter> entry : filters.entrySet()) {</span> |
| <span class="fc" id="L379"> String name = entry.getKey();</span> |
| <span class="fc" id="L380"> Filter filter = entry.getValue();</span> |
| <span class="fc" id="L381"> applyGlobalPropertiesIfNecessary(filter);</span> |
| <span class="pc bpc" id="L382" title="1 of 2 branches missed."> if (filter instanceof Nameable) {</span> |
| <span class="nc" id="L383"> ((Nameable) filter).setName(name);</span> |
| } |
| //'init' argument is false, since Spring-configured filters should be initialized |
| //in Spring (i.e. 'init-method=blah') or implement InitializingBean: |
| <span class="fc" id="L387"> manager.addFilter(name, filter, false);</span> |
| <span class="fc" id="L388"> }</span> |
| } |
| |
| //build up the chains: |
| <span class="fc" id="L392"> Map<String, String> chains = getFilterChainDefinitionMap();</span> |
| <span class="pc bpc" id="L393" title="1 of 2 branches missed."> if (!CollectionUtils.isEmpty(chains)) {</span> |
| <span class="fc bfc" id="L394" title="All 2 branches covered."> for (Map.Entry<String, String> entry : chains.entrySet()) {</span> |
| <span class="fc" id="L395"> String url = entry.getKey();</span> |
| <span class="fc" id="L396"> String chainDefinition = entry.getValue();</span> |
| <span class="fc" id="L397"> manager.createChain(url, chainDefinition);</span> |
| <span class="fc" id="L398"> }</span> |
| } |
| |
| <span class="fc" id="L401"> return manager;</span> |
| } |
| |
| /** |
| * This implementation: |
| * <ol> |
| * <li>Ensures the required {@link #setSecurityManager(org.apache.shiro.mgt.SecurityManager) securityManager} |
| * property has been set</li> |
| * <li>{@link #createFilterChainManager() Creates} a {@link FilterChainManager} instance that reflects the |
| * configured {@link #setFilters(java.util.Map) filters} and |
| * {@link #setFilterChainDefinitionMap(java.util.Map) filter chain definitions}</li> |
| * <li>Wraps the FilterChainManager with a suitable |
| * {@link org.apache.shiro.web.filter.mgt.FilterChainResolver FilterChainResolver} since the Shiro Filter |
| * implementations do not know of {@code FilterChainManager}s</li> |
| * <li>Sets both the {@code SecurityManager} and {@code FilterChainResolver} instances on a new Shiro Filter |
| * instance and returns that filter instance.</li> |
| * </ol> |
| * |
| * @return a new Shiro Filter reflecting any configured filters and filter chain definitions. |
| * @throws Exception if there is a problem creating the AbstractShiroFilter instance. |
| */ |
| protected AbstractShiroFilter createInstance() throws Exception { |
| |
| <span class="fc" id="L424"> log.debug("Creating Shiro Filter instance.");</span> |
| |
| <span class="fc" id="L426"> SecurityManager securityManager = getSecurityManager();</span> |
| <span class="pc bpc" id="L427" title="1 of 2 branches missed."> if (securityManager == null) {</span> |
| <span class="nc" id="L428"> String msg = "SecurityManager property must be set.";</span> |
| <span class="nc" id="L429"> throw new BeanInitializationException(msg);</span> |
| } |
| |
| <span class="pc bpc" id="L432" title="1 of 2 branches missed."> if (!(securityManager instanceof WebSecurityManager)) {</span> |
| <span class="nc" id="L433"> String msg = "The security manager does not implement the WebSecurityManager interface.";</span> |
| <span class="nc" id="L434"> throw new BeanInitializationException(msg);</span> |
| } |
| |
| <span class="fc" id="L437"> FilterChainManager manager = createFilterChainManager();</span> |
| |
| //Expose the constructed FilterChainManager by first wrapping it in a |
| // FilterChainResolver implementation. The AbstractShiroFilter implementations |
| // do not know about FilterChainManagers - only resolvers: |
| <span class="fc" id="L442"> PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();</span> |
| <span class="fc" id="L443"> chainResolver.setFilterChainManager(manager);</span> |
| |
| //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built |
| //FilterChainResolver. It doesn't matter that the instance is an anonymous inner class |
| //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts |
| //injection of the SecurityManager and FilterChainResolver: |
| <span class="fc" id="L449"> return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);</span> |
| } |
| |
| private void applyLoginUrlIfNecessary(Filter filter) { |
| <span class="fc" id="L453"> String loginUrl = getLoginUrl();</span> |
| <span class="pc bpc" id="L454" title="3 of 4 branches missed."> if (StringUtils.hasText(loginUrl) && (filter instanceof AccessControlFilter)) {</span> |
| <span class="nc" id="L455"> AccessControlFilter acFilter = (AccessControlFilter) filter;</span> |
| //only apply the login url if they haven't explicitly configured one already: |
| <span class="nc" id="L457"> String existingLoginUrl = acFilter.getLoginUrl();</span> |
| <span class="nc bnc" id="L458" title="All 2 branches missed."> if (AccessControlFilter.DEFAULT_LOGIN_URL.equals(existingLoginUrl)) {</span> |
| <span class="nc" id="L459"> acFilter.setLoginUrl(loginUrl);</span> |
| } |
| } |
| <span class="fc" id="L462"> }</span> |
| |
| private void applySuccessUrlIfNecessary(Filter filter) { |
| <span class="fc" id="L465"> String successUrl = getSuccessUrl();</span> |
| <span class="pc bpc" id="L466" title="3 of 4 branches missed."> if (StringUtils.hasText(successUrl) && (filter instanceof AuthenticationFilter)) {</span> |
| <span class="nc" id="L467"> AuthenticationFilter authcFilter = (AuthenticationFilter) filter;</span> |
| //only apply the successUrl if they haven't explicitly configured one already: |
| <span class="nc" id="L469"> String existingSuccessUrl = authcFilter.getSuccessUrl();</span> |
| <span class="nc bnc" id="L470" title="All 2 branches missed."> if (AuthenticationFilter.DEFAULT_SUCCESS_URL.equals(existingSuccessUrl)) {</span> |
| <span class="nc" id="L471"> authcFilter.setSuccessUrl(successUrl);</span> |
| } |
| } |
| <span class="fc" id="L474"> }</span> |
| |
| private void applyUnauthorizedUrlIfNecessary(Filter filter) { |
| <span class="fc" id="L477"> String unauthorizedUrl = getUnauthorizedUrl();</span> |
| <span class="pc bpc" id="L478" title="3 of 4 branches missed."> if (StringUtils.hasText(unauthorizedUrl) && (filter instanceof AuthorizationFilter)) {</span> |
| <span class="nc" id="L479"> AuthorizationFilter authzFilter = (AuthorizationFilter) filter;</span> |
| //only apply the unauthorizedUrl if they haven't explicitly configured one already: |
| <span class="nc" id="L481"> String existingUnauthorizedUrl = authzFilter.getUnauthorizedUrl();</span> |
| <span class="nc bnc" id="L482" title="All 2 branches missed."> if (existingUnauthorizedUrl == null) {</span> |
| <span class="nc" id="L483"> authzFilter.setUnauthorizedUrl(unauthorizedUrl);</span> |
| } |
| } |
| <span class="fc" id="L486"> }</span> |
| |
| private void applyGlobalPropertiesIfNecessary(Filter filter) { |
| <span class="fc" id="L489"> applyLoginUrlIfNecessary(filter);</span> |
| <span class="fc" id="L490"> applySuccessUrlIfNecessary(filter);</span> |
| <span class="fc" id="L491"> applyUnauthorizedUrlIfNecessary(filter);</span> |
| <span class="fc" id="L492"> }</span> |
| |
| /** |
| * Inspects a bean, and if it implements the {@link Filter} interface, automatically adds that filter |
| * instance to the internal {@link #setFilters(java.util.Map) filters map} that will be referenced |
| * later during filter chain construction. |
| */ |
| public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { |
| <span class="pc bpc" id="L500" title="1 of 2 branches missed."> if (bean instanceof Filter) {</span> |
| <span class="fc" id="L501"> log.debug("Found filter chain candidate filter '{}'", beanName);</span> |
| <span class="fc" id="L502"> Filter filter = (Filter) bean;</span> |
| <span class="fc" id="L503"> applyGlobalPropertiesIfNecessary(filter);</span> |
| <span class="fc" id="L504"> getFilters().put(beanName, filter);</span> |
| <span class="fc" id="L505"> } else {</span> |
| <span class="nc" id="L506"> log.trace("Ignoring non-Filter bean '{}'", beanName);</span> |
| } |
| <span class="fc" id="L508"> return bean;</span> |
| } |
| |
| /** |
| * Does nothing - only exists to satisfy the BeanPostProcessor interface and immediately returns the |
| * {@code bean} argument. |
| */ |
| public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { |
| <span class="fc" id="L516"> return bean;</span> |
| } |
| |
| /** |
| * Ordinarily the {@code AbstractShiroFilter} must be subclassed to additionally perform configuration |
| * and initialization behavior. Because this {@code FactoryBean} implementation manually builds the |
| * {@link AbstractShiroFilter}'s |
| * {@link AbstractShiroFilter#setSecurityManager(org.apache.shiro.web.mgt.WebSecurityManager) securityManager} and |
| * {@link AbstractShiroFilter#setFilterChainResolver(org.apache.shiro.web.filter.mgt.FilterChainResolver) filterChainResolver} |
| * properties, the only thing left to do is set those properties explicitly. We do that in a simple |
| * concrete subclass in the constructor. |
| */ |
| private static final class SpringShiroFilter extends AbstractShiroFilter { |
| |
| protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) { |
| <span class="fc" id="L531"> super();</span> |
| <span class="pc bpc" id="L532" title="1 of 2 branches missed."> if (webSecurityManager == null) {</span> |
| <span class="nc" id="L533"> throw new IllegalArgumentException("WebSecurityManager property cannot be null.");</span> |
| } |
| <span class="fc" id="L535"> setSecurityManager(webSecurityManager);</span> |
| <span class="pc bpc" id="L536" title="1 of 2 branches missed."> if (resolver != null) {</span> |
| <span class="fc" id="L537"> setFilterChainResolver(resolver);</span> |
| } |
| <span class="fc" id="L539"> }</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> |