Search code examples
guiceshiroguice-servlet

Configuring Apache Shiro with Google Guice Servlet


I'm starting to use Guice/Shiro instead of Spring/Spring Security. I have looked examples from Shiro site, and all configuration examples are made as INI-file examples. Is it possible to configure Shiro in plain Java, as Guice Servlets are meant to be configured?


Solution

  • Yes it is possible, but requires some glue code if you want Guice to create your Realms.

    1. Bind Realm implementation:
        bind(Realm.class).to(MyRealm.class).in(Singleton.class);
    
    1. Bind WebSecurityManager:
        @Provides @Singleton WebSecurityManager securityManager(Realm realm) {
          DefaultWebSecurityManager sm = new DefaultWebSecurityManager();
          sm.setRealm(realm);
          return sm;
        }
    
    1. Subclass one of Shiro filters so you can use Guice provided WebSecurityManager:
        public class SecurityFilter extends IniShiroFilter {
    
          static class SecurityManagerFactory extends WebIniSecurityManagerFactory {
    
            private final WebSecurityManager securityManager;
    
            public SecurityManagerFactory(WebSecurityManager securityManager) {
              this.securityManager = securityManager;
            }
    
            public SecurityManagerFactory(WebSecurityManager securityManager, Ini ini) {
              super(ini);
              this.securityManager = securityManager;
            }
    
            @Override
            protected SecurityManager createDefaultInstance() {
              return securityManager;
            }
          }
    
          private final Provider<WebSecurityManager> securityManager;
    
          @Inject
          SecurityFilter(Provider<WebSecurityManager> securityManager) {
            super();
            this.securityManager = securityManager;
          }
    
    
          protected Map<String, ?> applySecurityManager(Ini ini) {
            SecurityManagerFactory factory;
            if (ini == null || ini.isEmpty()) {
              factory = new SecurityManagerFactory(securityManager.get());
            } else {
              factory = new SecurityManagerFactory(securityManager.get(), ini);
            }
            setSecurityManager((WebSecurityManager) factory.getInstance());
            return factory.getBeans();
          }
        }
    
    1. Configure your filter:
        Joiner lines = Joiner.on("\n");
        Map<String, String> config = ImmutableMap.of("config", lines.join(
            "; here you can provide additional ini",
            "[roles]",
            "admin = *",
            "[urls]",
            "/secure/** = authcBasic"
        ));
        filter("/*").through(SecurityFilter.class, config);