blob: abe4cc2c2d39d9526e09fbac874678ed9c3c6406 [file] [log] [blame]
<a name="Guice-IntegratingApacheShirointoGuicebasedApplication"></a>
Integrating Apache Shiro into Guice based Application
=====================================================
Shiro [Guice](https://github.com/google/guice) 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.
<a name="Guice-Overview"></a>
Overview
--------
shiro-guice provides three Guice modules that can be included in your application.
* ShiroModule
* Provides basic integration for setting up the `SecurityManager`, any `Realms`, and any other Shiro configuration.
* This module is used by extending it and adding your own custom configuration.
* ShiroWebModule
* Extension of `ShiroModule` that sets up the web environment and also allows for filter chain configuration. This uses the [Guice Servlet Module](https://github.com/google/guice/wiki/ServletModule) to configure the filters, and so requires that to be setup.
* Like the `ShiroModule`, this module is used by extending it and adding your own custom configuration.
* ShiroAopModule
* Uses [Guice AOP](https://github.com/google/guice/wiki/AOP) to implement the Shiro AOP annotations. This module is primarily concerned with adapting Shiro `AnnotationMethodInterceptors` to the Guice method interceptor model.
* This module is typically used by simply installing it. However, if you have your own `AnnotationMethodInterceptors` written for Shiro, they can be easily incorporated by extending it.
<a name="Guice-GettingStarted"></a>
Getting Started
---------------
The most simple configuration is to extend `ShiroModule` to install your own `Realm`.
``` java
class MyShiroModule extends ShiroModule {
protected void configureShiro() {
try {
bindRealm().toConstructor(IniRealm.class.getConstructor(Ini.class));
} catch (NoSuchMethodException e) {
addError(e);
}
}
@Provides
Ini loadShiroIni() {
return Ini.fromResourcePath("classpath:shiro.ini");
}
}
```
In this case, user and role configuration would go in the `shiro.ini` file.
#warning('shiro.ini usage in Guice', 'It is important to note that, in this above configuration, only the `users` and `roles` sections from the ini file are used.')
Then, the module is used to create a Guice injector, and the injector is used to obtain a `SecurityManager`. The following example serves the same purpose as the first three lines in the [Quickstart](10-minute-tutorial.html#10MinuteTutorial-Quickstart.java) example.
``` java
Injector injector = Guice.createInjector(new MyShiroModule());
SecurityManager securityManager = injector.getInstance(SecurityManager.class);
SecurityUtils.setSecurityManager(securityManager);
```
<a name="Guice-AOP"></a>
AOP
---
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 `ShiroAopModule`.
To use it, simply instantiate and install the module alongside your application module and your `ShiroModule`.
``` java
Injector injector = Guice.createInjector(new MyShiroModule(), new ShiroAopModule(), new MyApplicationModule());
```
If you have written custom interceptors that conform to Shiro's api, you may find it useful to extend the `ShiroAopModule`.
``` java
class MyShiroAopModule extends ShiroAopModule {
protected void configureInterceptors(AnnotationResolver resolver)
{
bindShiroInterceptor(new MyCustomAnnotationMethodInterceptor(resolver));
}
}
```
<a name="Guice-Web"></a>
Web
---
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.
``` java
class MyShiroWebModule extends ShiroWebModule {
MyShiroWebModule(ServletContext sc) {
super(sc);
}
protected void configureShiroWeb() {
try {
bindRealm().toConstructor(IniRealm.class.getConstructor(Ini.class));
} catch (NoSuchMethodException e) {
addError(e);
}
addFilterChain("/public/**", ANON);
addFilterChain("/stuff/allowed/**", AUTHC_BASIC, config(PERMS, "yes"));
addFilterChain("/stuff/forbidden/**", AUTHC_BASIC, config(PERMS, "no"));
addFilterChain("/**", AUTHC_BASIC);
}
@Provides
Ini loadShiroIni() {
return Ini.fromResourcePath("classpath:shiro.ini");
}
}
```
In the previous code, we have bound an `IniRealm` and setup four filter chains. These chains would be equivalent to the following ini configuration.
``` ini
[urls]
/public/** = anon
/stuff/allowed/** = authcBasic, perms["yes"]
/stuff/forbidden/** = authcBasic, perms["no"]
/** = authcBasic
```
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
``` java
Key customFilter = Key.get(MyCustomFilter.class);
addFilterChain("/custom/**", customFilter);
```
We still have to tell guice-servlets about our Shiro filter. Since the `ShiroWebModule` is private, and guice-servlets does not give us a way to expose a filter mapping, we have to bind it manually.
``` java
ShiroWebModule.guiceFilterModule()
```
Or, from within an application module,
``` java
ShiroWebModule.bindGuiceFilter(binder())
```
<a name="Guice-Properties"></a>
Properties
----------
A number of Shiro classes expose configuration parameters via setter methods. shiro-guice will inject these if it finds a binding for `@Named("shiro.{propName}")`. For instance, to set the session timeout, you could do the following.
``` java
bindConstant().annotatedWith(Names.named("shiro.globalSessionTimeout")).to(30000L);
```
If this paradigm doesn't work for you, you may also consider using a provider to instantiate the object and invoking the setters directly.
<a name="Guice-InjectionofShiroObjects"></a>
Injection of Shiro Objects
--------------------------
shiro-guice uses a Guice `TypeListener` to perform injection on native Shiro classes (any class in a subdirectory of `org.apache.shiro` but not `org.apache.shiro.guice`). However, Guice only considers explicitly bound types as candidates for `TypeListeners`, so if you have a Shiro object that you want injected, you have to declare it explicitly. For instance, to set the `CredentialsMatcher` for a realm, we would need to add the following bindings:
``` java
bind(CredentialsMatcher.class).to(HashedCredentialsMatcher.class);
bind(HashedCredentialsMatcher.class);
bindConstant().annotatedWith(Names.named("shiro.hashAlgorithmName")).to(Md5Hash.ALGORITHM_NAME);
```
#lendAHandDoc()
<input type="hidden" id="ghEditPage" value="guice.md.vtl"></input>