blob: 2fcdf6d2b9c4827720e7302932a8b1db4ad1e69b [file] [log] [blame]
<h1><a name="Guice-IntegratingApacheShirointoGuicebasedApplication"></a>Integrating Apache Shiro into Guice based Application</h1>
<p>Shiro <a class="external-link" href="http://code.google.com/p/google-guice/" rel="nofollow">Guice</a> integration was added in Shiro 1.2. This page covers the ways to integrate Shiro into Guice-based applications using standard Guice conventions and mechanisms. Prior to reading this integration document, you should be a least somewhat familiar with Guice.</p>
<h2><a name="Guice-Overview"></a>Overview</h2>
<p>shiro-guice provides three Guice modules that can be included in your application.</p>
<ul><li>ShiroModule
<ul><li>Provides basic integration for setting up the <tt>SecurityManager</tt>, any <tt>Realms</tt>, and any other Shiro configuration.</li><li>This module is used by extending it and adding your own custom configuration.</li></ul>
</li></ul>
<ul><li>ShiroWebModule
<ul><li>Extension of <tt>ShiroModule</tt> that sets up the web environment and also allows for filter chain configuration. This uses the <a class="external-link" href="http://code.google.com/p/google-guice/wiki/ServletModule" rel="nofollow">Guice Servlet Module</a> to configure the filters, and so requires that to be setup.</li><li>Like the <tt>ShiroModule</tt>, this module is used by extending it and adding your own custom configuration.</li></ul>
</li></ul>
<ul><li>ShiroAopModule
<ul><li>Uses <a class="external-link" href="http://code.google.com/p/google-guice/wiki/AOP" rel="nofollow">Guice AOP</a> to implement the Shiro AOP annotations. This module is primarily concerned with adapting Shiro <tt>AnnotationMethodInterceptors</tt> to the Guice method interceptor model.</li><li>This module is typically used by simply installing it. However, if you have your own <tt>AnnotationMethodInterceptors</tt> written for Shiro, they can be easily incorporated by extending it.</li></ul>
</li></ul>
<h2><a name="Guice-GettingStarted"></a>Getting Started</h2>
<p>The most simple configuration is to extend <tt>ShiroModule</tt> to install your own <tt>Realm</tt>. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
class MyShiroModule <span class="code-keyword">extends</span> ShiroModule {
<span class="code-keyword">protected</span> void configureShiro() {
<span class="code-keyword">try</span> {
bindRealm().toConstructor(IniRealm.class.getConstructor(Ini.class));
} <span class="code-keyword">catch</span> (NoSuchMethodException e) {
addError(e);
}
}
@Provides
Ini loadShiroIni() {
<span class="code-keyword">return</span> Ini.fromResourcePath(<span class="code-quote">"classpath:shiro.ini"</span>);
}
}
</pre>
</div></div>
<p>In this case, user and role configuration would go in the <tt>shiro.ini</tt> file.</p>
<div class="panelMacro"><table class="noteMacro"><colgroup span="1"><col span="1" width="24"><col span="1"></colgroup><tr><td colspan="1" rowspan="1" valign="top"><img align="middle" src="https://cwiki.apache.org/confluence/images/icons/emoticons/warning.gif" width="16" height="16" alt="" border="0"></td><td colspan="1" rowspan="1"><b>shiro.ini usage in Guice</b><br clear="none">It is important to note that, in this above configuration, only the <tt>users</tt> and <tt>roles</tt> sections from the ini file are used.</td></tr></table></div>
<p>Then, the module is used to create a Guice injector, and the injector is used to obtain a <tt>SecurityManager</tt>. The following example serves the same purpose as the first three lines in the <a class="external-link" href="10-minute-tutorial.html#10MinuteTutorial-Quickstart.java">Quickstart</a> example.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Injector injector = Guice.createInjector(<span class="code-keyword">new</span> MyShiroModule());
<span class="code-object">SecurityManager</span> securityManager = injector.getInstance(<span class="code-object">SecurityManager</span>.class);
SecurityUtils.setSecurityManager(securityManager);
</pre>
</div></div>
<h2><a name="Guice-AOP"></a>AOP</h2>
<p>Shiro includes several annotations and method interceptors useful for performing authorization via AOP. It also provides a simple API for writing Shiro-specific method interceptors. shiro-guice supports this with the <tt>ShiroAopModule</tt>.</p>
<p>To use it, simply instantiate and install the module alongside your application module and your <tt>ShiroModule</tt>. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Injector injector = Guice.createInjector(<span class="code-keyword">new</span> MyShiroModule(), <span class="code-keyword">new</span> ShiroAopModule(), <span class="code-keyword">new</span> MyApplicationModule());
</pre>
</div></div>
<p>If you have written custom interceptors that conform to Shiro's api, you may find it useful to extend the <tt>ShiroAopModule</tt>. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
class MyShiroAopModule <span class="code-keyword">extends</span> ShiroAopModule {
<span class="code-keyword">protected</span> void configureInterceptors(AnnotationResolver resolver)
{
bindShiroInterceptor(<span class="code-keyword">new</span> MyCustomAnnotationMethodInterceptor(resolver));
}
}
</pre>
</div></div>
<h2><a name="Guice-Web"></a>Web</h2>
<p>shiro-guice's web integration is designed to integrate Shiro and its filter paradigm with Guice's servlet module. If you are using Shiro in a web environment, and using Guice's servlet module, then you should extend ShiroWebModule rather than ShiroModule. Your web.xml should be setup exactly as Guice's servlet module recommends.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
class MyShiroWebModule <span class="code-keyword">extends</span> ShiroWebModule {
MyShiroWebModule(ServletContext sc) {
<span class="code-keyword">super</span>(sc);
}
<span class="code-keyword">protected</span> void configureShiroWeb() {
<span class="code-keyword">try</span> {
bindRealm().toConstructor(IniRealm.class.getConstructor(Ini.class));
} <span class="code-keyword">catch</span> (NoSuchMethodException e) {
addError(e);
}
addFilterChain(<span class="code-quote">"/<span class="code-keyword">public</span>/**"</span>, ANON);
addFilterChain(<span class="code-quote">"/stuff/allowed/**"</span>, AUTHC_BASIC, config(PERMS, <span class="code-quote">"yes"</span>));
addFilterChain(<span class="code-quote">"/stuff/forbidden/**"</span>, AUTHC_BASIC, config(PERMS, <span class="code-quote">"no"</span>));
addFilterChain(<span class="code-quote">"/**"</span>, AUTHC_BASIC);
}
@Provides
Ini loadShiroIni() {
<span class="code-keyword">return</span> Ini.fromResourcePath(<span class="code-quote">"classpath:shiro.ini"</span>);
}
}
</pre>
</div></div>
<p>In the previous code, we have bound an <tt>IniRealm</tt> and setup four filter chains. These chains would be equivalent to the following ini configuration. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
[urls]
/<span class="code-keyword">public</span>/** = anon
/stuff/allowed/** = authcBasic, perms[<span class="code-quote">"yes"</span>]
/stuff/forbidden/** = authcBasic, perms[<span class="code-quote">"no"</span>]
/** = authcBasic
</pre>
</div></div>
<p>In shiro-guice, the filter names are Guice keys. All of the default Shiro filters are available as constants, but you are not limited to those. In order to use a custom filter in a filter chain, you would do </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
Key customFilter = Key.get(MyCustomFilter.class);
addFilterChain(<span class="code-quote">"/custom/**"</span>, customFilter);
</pre>
</div></div>
<p>We still have to tell guice-servlets about our Shiro filter. Since the <tt>ShiroWebModule</tt> is private, and guice-servlets does not give us a way to expose a filter mapping, we have to bind it manually. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
ShiroWebModule.guiceFilterModule()
</pre>
</div></div>
<p>Or, from within an application module, </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
ShiroWebModule.bindGuiceFilter(binder())
</pre>
</div></div>
<h2><a name="Guice-Properties"></a>Properties</h2>
<p>A number of Shiro classes expose configuration parameters via setter methods. shiro-guice will inject these if it finds a binding for <tt>@Named("shiro.{propName}")</tt>. For instance, to set the session timeout, you could do the following. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
bindConstant().annotatedWith(Names.named(<span class="code-quote">"shiro.globalSessionTimeout"</span>)).to(30000L);
</pre>
</div></div>
<p>If this paradigm doesn't work for you, you may also consider using a provider to instantiate the object and invoking the setters directly.</p>
<h2><a name="Guice-InjectionofShiroObjects"></a>Injection of Shiro Objects</h2>
<p>shiro-guice uses a Guice <tt>TypeListener</tt> to perform injection on native Shiro classes (any class in a subdirectory of <tt>org.apache.shiro</tt> but not <tt>org.apache.shiro.guice</tt>). However, Guice only considers explicitly bound types as candidates for <tt>TypeListeners</tt>, so if you have a Shiro object that you want injected, you have to declare it explicitly. For instance, to set the <tt>CredentialsMatcher</tt> for a realm, we would need to add the following bindings:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
bind(CredentialsMatcher.class).to(HashedCredentialsMatcher.class);
bind(HashedCredentialsMatcher.class);
bindConstant().annotatedWith(Names.named(<span class="code-quote">"shiro.hashAlgorithmName"</span>)).to(Md5Hash.ALGORITHM_NAME);
</pre>
</div></div>
<h2><a name="Guice-Lendahandwithdocumentation"></a>Lend a hand with documentation </h2>
<p>While we hope this documentation helps you with the work you're doing with Apache Shiro, the community is improving and expanding the documentation all the time. If you'd like to help the Shiro project, please consider corrected, expanding, or adding documentation where you see a need. Every little bit of help you provide expands the community and in turn improves Shiro. </p>
<p>The easiest way to contribute your documentation is to send it to the <a class="external-link" href="http://shiro-user.582556.n2.nabble.com/" rel="nofollow">User Forum</a> or the <a href="mailing-lists.html" title="Mailing Lists">User Mailing List</a>.</p>