4

I develop a rest api with Jersey and want to use Google Guice for Dependency Injection and Apache Shiro as a security framwork.

For Authentication i created a custom Realm to which I have to inject an custom Authenticator which is connected to the EntityManager.

However the dependency is not injected into the Realm. I guess that shiro.ini (in which I have to define the used realm) is not managed by guice.

How can I inject dependencies into Apache Shiro, especially into the used Realm?

My web.xml only has a filter mapped to guice

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
    <listener-class>GuiceServletConfig</listener-class>
</listener>
</web-app>

My GuiceServletConfig configures all dependencies including the CustomRealm

public class GuiceServletConfig extends GuiceServletContextListener {

@Override
protected Injector getInjector() {
    return Guice.createInjector(new DbModule(), new JerseyServletModule() {

        @Override
        protected void configureServlets() {
            // ...
            // CustomRealm is only used when i use it as an eager singleton
            bind(CustomRealm.class).asEagerSingleton();
            bind(org.apache.shiro.web.servlet.IniShiroFilter.class).in(Singleton.class);
            filter("/*").through(org.apache.shiro.web.servlet.IniShiroFilter.class);
            serve("/api/*").with(GuiceContainer.class);
        }
    });
}
}

The shiro ini only defines the realm

[main]
myRealm = CustomRealm
[users] # for testing
root = secret,admin
[roles] # for testing
admin = *
[urls]
/api/** = authcBasic

1 Answers1

5

Apache Shiro's INI configuration is great for many use cases, but if you have the full power of an IoC framework like Spring or Guice, it is usually better to configure all of Shiro within the IoC mechanism directly. Shiro's Spring integration serves as a good example for this: http://shiro.apache.org/spring.html It is recommended to do something nearly identical for Guice environments.

If you don't want to do this and would rather stay with INI, Shiro has a RealmFactory concept.

You can create a RealmFactory implementation that communicates with your Guice environment and 'pulls' your Guice-configured Realm(s). Then you define your RealmFactory implementation in the Shiro INI:

[main]
...
guiceRealmFactory = com.foo.bar.shiro.GuiceRealmFactory
...

Note however that Shiro's INI only supports acquiring Realm instances from outside of INI via the RealmFactory - all other referenced objects must be be defined in INI. You might want to open a Shiro Jira issue to ask for more general Factory support beyond just realms.

Ultimately, because Guice is more powerful than INI, it is recommended to configure everything in Shiro in Guice if possible (SecurityManager, realms, the ShiroFilter, etc)

Alex
  • 488
  • 1
  • 3
  • 12
  • i'm glad to skip the ini and use plain di. i was not able to use the spring guide to setup guice (i am not that familiar with guice/spring). what do i have to insert into my GuiceServletConfig to use my own Realm? –  Feb 01 '11 at 10:35