blob: 55fa94eeb5238f5573083dd639eb6a3c4bd32fda [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>ShiroWebModule.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 :: Guice</a> &gt; <a href="index.source.html" class="el_package">org.apache.shiro.guice.web</a> &gt; <span class="el_source">ShiroWebModule.java</span></div><h1>ShiroWebModule.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.guice.web;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.ServletContext;
import org.apache.shiro.config.ConfigurationException;
import org.apache.shiro.env.Environment;
import org.apache.shiro.guice.ShiroModule;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.web.env.WebEnvironment;
import org.apache.shiro.web.filter.PathMatchingFilter;
import org.apache.shiro.web.filter.authc.AnonymousFilter;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.filter.authc.UserFilter;
import org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.apache.shiro.web.filter.authz.PortFilter;
import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter;
import org.apache.shiro.web.filter.authz.SslFilter;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
import org.apache.shiro.web.filter.session.NoSessionCreationFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.AnnotatedBindingBuilder;
import com.google.inject.name.Names;
import com.google.inject.servlet.ServletModule;
/**
* Sets up Shiro lifecycles within Guice, enables the injecting of Shiro objects, and binds a default
* {@link org.apache.shiro.web.mgt.WebSecurityManager}, {@link org.apache.shiro.mgt.SecurityManager} and {@link org.apache.shiro.session.mgt.SessionManager}. At least one realm must be added by
* using {@link #bindRealm() bindRealm}.
* &lt;p/&gt;
* Also provides for the configuring of filter chains and binds a {@link org.apache.shiro.web.filter.mgt.FilterChainResolver} with that information.
*/
public abstract class ShiroWebModule extends ShiroModule {
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L68"> public static final Key&lt;AnonymousFilter&gt; ANON = Key.get(AnonymousFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L70"> public static final Key&lt;FormAuthenticationFilter&gt; AUTHC = Key.get(FormAuthenticationFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L72"> public static final Key&lt;BasicHttpAuthenticationFilter&gt; AUTHC_BASIC = Key.get(BasicHttpAuthenticationFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L74"> public static final Key&lt;NoSessionCreationFilter&gt; NO_SESSION_CREATION = Key.get(NoSessionCreationFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L76"> public static final Key&lt;LogoutFilter&gt; LOGOUT = Key.get(LogoutFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L78"> public static final Key&lt;PermissionsAuthorizationFilter&gt; PERMS = Key.get(PermissionsAuthorizationFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L80"> public static final Key&lt;PortFilter&gt; PORT = Key.get(PortFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L82"> public static final Key&lt;HttpMethodPermissionFilter&gt; REST = Key.get(HttpMethodPermissionFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L84"> public static final Key&lt;RolesAuthorizationFilter&gt; ROLES = Key.get(RolesAuthorizationFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L86"> public static final Key&lt;SslFilter&gt; SSL = Key.get(SslFilter.class);</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
<span class="fc" id="L88"> public static final Key&lt;UserFilter&gt; USER = Key.get(UserFilter.class);</span>
static final String NAME = &quot;SHIRO&quot;;
/**
* We use a LinkedHashMap here to ensure that iterator order is the same as add order. This is important, as the
* FilterChainResolver uses iterator order when searching for a matching chain.
*/
<span class="fc" id="L97"> private final Map&lt;String, Key&lt;? extends Filter&gt;[]&gt; filterChains = new LinkedHashMap&lt;String, Key&lt;? extends Filter&gt;[]&gt;();</span>
private final ServletContext servletContext;
<span class="fc" id="L100"> public ShiroWebModule(ServletContext servletContext) {</span>
<span class="fc" id="L101"> this.servletContext = servletContext;</span>
<span class="fc" id="L102"> }</span>
public static void bindGuiceFilter(Binder binder) {
<span class="nc" id="L105"> binder.install(guiceFilterModule());</span>
<span class="nc" id="L106"> }</span>
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
public static void bindGuiceFilter(final String pattern, Binder binder) {
<span class="nc" id="L110"> binder.install(guiceFilterModule(pattern));</span>
<span class="nc" id="L111"> }</span>
public static ServletModule guiceFilterModule() {
<span class="nc" id="L114"> return guiceFilterModule(&quot;/*&quot;);</span>
}
public static ServletModule guiceFilterModule(final String pattern) {
<span class="nc" id="L118"> return new ServletModule() {</span>
@Override
protected void configureServlets() {
<span class="nc" id="L121"> filter(pattern).through(GuiceShiroFilter.class);</span>
<span class="nc" id="L122"> }</span>
};
}
@Override
protected final void configureShiro() {
<span class="fc" id="L128"> bindBeanType(TypeLiteral.get(ServletContext.class), Key.get(ServletContext.class, Names.named(NAME)));</span>
<span class="fc" id="L129"> bind(Key.get(ServletContext.class, Names.named(NAME))).toInstance(this.servletContext);</span>
<span class="fc" id="L130"> bindWebSecurityManager(bind(WebSecurityManager.class));</span>
<span class="fc" id="L131"> bindWebEnvironment(bind(WebEnvironment.class));</span>
<span class="fc" id="L132"> bind(GuiceShiroFilter.class).asEagerSingleton();</span>
<span class="fc" id="L133"> expose(GuiceShiroFilter.class);</span>
<span class="fc" id="L135"> this.configureShiroWeb();</span>
<span class="fc" id="L137"> setupFilterChainConfigs();</span>
<span class="fc" id="L139"> bind(FilterChainResolver.class).toProvider(new FilterChainResolverProvider(filterChains));</span>
<span class="fc" id="L140"> }</span>
private void setupFilterChainConfigs() {
<span class="fc" id="L143"> Map&lt;Key&lt;? extends PathMatchingFilter&gt;, Map&lt;String, String&gt;&gt; configs = new HashMap&lt;Key&lt;? extends PathMatchingFilter&gt;, Map&lt;String, String&gt;&gt;();</span>
<span class="fc bfc" id="L145" title="All 2 branches covered."> for (Map.Entry&lt;String, Key&lt;? extends Filter&gt;[]&gt; filterChain : filterChains.entrySet()) {</span>
<span class="fc bfc" id="L146" title="All 2 branches covered."> for (int i = 0; i &lt; filterChain.getValue().length; i++) {</span>
<span class="fc" id="L147"> Key&lt;? extends Filter&gt; key = filterChain.getValue()[i];</span>
<span class="fc bfc" id="L148" title="All 2 branches covered."> if (key instanceof FilterConfigKey) {</span>
<span class="fc" id="L149"> FilterConfigKey&lt;? extends PathMatchingFilter&gt; configKey = (FilterConfigKey&lt;? extends PathMatchingFilter&gt;) key;</span>
<span class="fc" id="L150"> key = configKey.getKey();</span>
<span class="fc" id="L151"> filterChain.getValue()[i] = key;</span>
<span class="pc bpc" id="L152" title="1 of 2 branches missed."> if (!PathMatchingFilter.class.isAssignableFrom(key.getTypeLiteral().getRawType())) {</span>
<span class="nc" id="L153"> throw new ConfigurationException(&quot;Config information requires a PathMatchingFilter - can't apply to &quot; + key.getTypeLiteral().getRawType());</span>
}
<span class="pc bpc" id="L155" title="1 of 2 branches missed."> if (configs.get(castToPathMatching(key)) == null) configs.put(castToPathMatching(key), new HashMap&lt;String, String&gt;());</span>
<span class="fc" id="L156"> configs.get(castToPathMatching(key)).put(filterChain.getKey(), configKey.getConfigValue());</span>
<span class="pc bpc" id="L157" title="1 of 2 branches missed."> } else if (PathMatchingFilter.class.isAssignableFrom(key.getTypeLiteral().getRawType())) {</span>
<span class="pc bpc" id="L158" title="1 of 2 branches missed."> if (configs.get(castToPathMatching(key)) == null) configs.put(castToPathMatching(key), new HashMap&lt;String, String&gt;());</span>
<span class="fc" id="L159"> configs.get(castToPathMatching(key)).put(filterChain.getKey(), &quot;&quot;);</span>
}
}
<span class="fc" id="L162"> }</span>
<span class="fc bfc" id="L163" title="All 2 branches covered."> for (Key&lt;? extends PathMatchingFilter&gt; filterKey : configs.keySet()) {</span>
<span class="fc" id="L164"> bindPathMatchingFilter(filterKey, configs.get(filterKey));</span>
<span class="fc" id="L165"> }</span>
<span class="fc" id="L166"> }</span>
private &lt;T extends PathMatchingFilter&gt; void bindPathMatchingFilter(Key&lt;T&gt; filterKey, Map&lt;String, String&gt; configs) {
<span class="fc" id="L169"> bind(filterKey).toProvider(new PathMatchingFilterProvider&lt;T&gt;(filterKey, configs)).asEagerSingleton();</span>
<span class="fc" id="L170"> }</span>
@SuppressWarnings({&quot;unchecked&quot;})
private Key&lt;? extends PathMatchingFilter&gt; castToPathMatching(Key&lt;? extends Filter&gt; key) {
<span class="fc" id="L174"> return (Key&lt;? extends PathMatchingFilter&gt;) key;</span>
}
protected abstract void configureShiroWeb();
@SuppressWarnings({&quot;unchecked&quot;})
@Override
protected final void bindSecurityManager(AnnotatedBindingBuilder&lt;? super SecurityManager&gt; bind) {
<span class="fc" id="L182"> bind.to(WebSecurityManager.class); // SHIRO-435</span>
<span class="fc" id="L183"> }</span>
/**
* Binds the security manager. Override this method in order to provide your own security manager binding.
* &lt;p/&gt;
* By default, a {@link org.apache.shiro.web.mgt.DefaultWebSecurityManager} is bound as an eager singleton.
*
* @param bind
*/
protected void bindWebSecurityManager(AnnotatedBindingBuilder&lt;? super WebSecurityManager&gt; bind) {
try {
<span class="fc" id="L194"> bind.toConstructor(DefaultWebSecurityManager.class.getConstructor(Collection.class)).asEagerSingleton();</span>
<span class="nc" id="L195"> } catch (NoSuchMethodException e) {</span>
<span class="nc" id="L196"> throw new ConfigurationException(&quot;This really shouldn't happen. Either something has changed in Shiro, or there's a bug in ShiroModule.&quot;, e);</span>
<span class="fc" id="L197"> }</span>
<span class="fc" id="L198"> }</span>
/**
* Binds the session manager. Override this method in order to provide your own session manager binding.
* &lt;p/&gt;
* By default, a {@link org.apache.shiro.web.session.mgt.DefaultWebSessionManager} is bound as an eager singleton.
*
* @param bind
*/
@Override
protected void bindSessionManager(AnnotatedBindingBuilder&lt;SessionManager&gt; bind) {
<span class="fc" id="L209"> bind.to(ServletContainerSessionManager.class).asEagerSingleton();</span>
<span class="fc" id="L210"> }</span>
@Override
protected final void bindEnvironment(AnnotatedBindingBuilder&lt;Environment&gt; bind) {
<span class="fc" id="L214"> bind.to(WebEnvironment.class); // SHIRO-435</span>
<span class="fc" id="L215"> }</span>
protected void bindWebEnvironment(AnnotatedBindingBuilder&lt;? super WebEnvironment&gt; bind) {
<span class="fc" id="L218"> bind.to(WebGuiceEnvironment.class).asEagerSingleton();</span>
<span class="fc" id="L219"> }</span>
/**
* Adds a filter chain to the shiro configuration.
* &lt;p/&gt;
* NOTE: If the provided key is for a subclass of {@link org.apache.shiro.web.filter.PathMatchingFilter}, it will be registered with a proper
* provider.
*
* @param pattern
* @param keys
*/
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
protected final void addFilterChain(String pattern, Key&lt;? extends Filter&gt;... keys) {
<span class="fc" id="L232"> filterChains.put(pattern, keys);</span>
<span class="fc" id="L233"> }</span>
protected static &lt;T extends PathMatchingFilter&gt; Key&lt;T&gt; config(Key&lt;T&gt; baseKey, String configValue) {
<span class="fc" id="L236"> return new FilterConfigKey&lt;T&gt;(baseKey, configValue);</span>
}
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
protected static &lt;T extends PathMatchingFilter&gt; Key&lt;T&gt; config(TypeLiteral&lt;T&gt; typeLiteral, String configValue) {
<span class="nc" id="L241"> return config(Key.get(typeLiteral), configValue);</span>
}
@SuppressWarnings({&quot;UnusedDeclaration&quot;})
protected static &lt;T extends PathMatchingFilter&gt; Key&lt;T&gt; config(Class&lt;T&gt; type, String configValue) {
<span class="nc" id="L246"> return config(Key.get(type), configValue);</span>
}
private static class FilterConfigKey&lt;T extends PathMatchingFilter&gt; extends Key&lt;T&gt; {
private Key&lt;T&gt; key;
private String configValue;
private FilterConfigKey(Key&lt;T&gt; key, String configValue) {
<span class="fc" id="L254"> super();</span>
<span class="fc" id="L255"> this.key = key;</span>
<span class="fc" id="L256"> this.configValue = configValue;</span>
<span class="fc" id="L257"> }</span>
public Key&lt;T&gt; getKey() {
<span class="fc" id="L260"> return key;</span>
}
public String getConfigValue() {
<span class="fc" id="L264"> return configValue;</span>
}
}
}
</pre><div class="footer"><span class="right">Created with <a href="http://www.eclemma.org/jacoco">JaCoCo</a> 0.7.7.201606060606</span></div></body></html>