Shiro集成Guice是在1.2版本里新增的功能。
Shiro提供了三个Guice模块可包含到你的应用系统:
l ShiroModule
为配置SecurityManager, any Realms和其他的Shiro组件提供最基本的集成。
通过扩展此模块来增加你自定义的配置。
l ShiroWebModule
此模块扩展了ShiroModule模块,用来设置web环境和配置过滤器链。使用Guice的Servlet Module来配置这些过滤器,需要在被设置。
与ShiroModule 模块一样,可以通过扩展来增加自定义的配置。
l ShiroAOPModule
使用Guice AOP来实现Shiro AOP的注解。这个模块主要实现了Shiro AnnotationMethodInterceptors来遵循Guice的方法拦截器模式。
你也可以非常容易地注册你自己写的AnnotationMethodInterceptors。
一个非常简单的自定义Realm示例如下:在这个列子里user和role的配置都在shiro.ini文件里。
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"); } } |
然后创建一个Guice注射器,这个注射器被用来获取SecurityManager。
Injector injector = Guice.createInjector(new MyShiroModule()); SecurityManager securityManager = injector.getInstance(SecurityManager.class); SecurityUtils.setSecurityManager(securityManager); |
Shiro包含几个注解和方法拦截器通过AOP来执行授权。它还提供一个简单的API来编写Shiro特定的方法拦截器,shiro-guice支持ShiroAOPModule。要使用它,只需实例化并且安装这个模块到你的应用中。
Injector injector = Guice.createInjector(new MyShiroModule(), new ShiroAopModule(), new MyApplicationModule()); |
你可以扩展ShiroAopModule来编写你自己的拦截器:
class MyShiroAopModule extends ShiroAopModule { protected void configureInterceptors(AnnotationResolver resolver) { bindShiroInterceptor(new MyCustomAnnotationMethodInterceptor(resolver)); } } |
Shiro-guice的web集成设计成将Shiro及它的过滤器范例与Guice的servlet Module的整合。如果你在一个web环境下使用Shiro和Guice’s servlet Module,那么你应该扩展ShiroWebModule而不是ShiroModule。你的web.xml应当和Guice’s servlet Module建议的一样。
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"); } } |
在上面的代码中我们建立了一个IniRealm和4个过滤器,在ini文件中配置如下:
[urls] /public/** = anon /stuff/allowed/** = authcBasic, perms["yes"] /stuff/forbidden/** = authcBasic, perms["no"] /** = authcBasic |
在shiro-guice中过滤器的名字是Guice的主键。所有Shiro自带的过滤器都定义为常量,你也可以自己定义过滤器:
Key customFilter = Key.get(MyCustomFilter.class); addFilterChain("/custom/**", customFilter); |
我们不得不告诉shiro-guice我们自定义的Shiro过滤器。由于ShiroWebModule是私有的,guice-servlets没有提供解析过滤器映射的方法,所以我们必须手动地将其绑定:
ShiroWebModule.guiceFilterModule() |
或
ShiroWebModule.bindGuiceFilter(binder()) |
通过setter方法可以设置很多的Shiro配置参数,shiro-guice将注入这些配置参数通过查找约束符@Named("shiro.{propName}")。例如,要设置会话超时,您可以执行以下操作。
bindConstant().annotatedWith(Names.named("shiro.globalSessionTimeout")).to(30000L); |
Shiro-guice使用TypeListener去注入本地的Shiro类(任何org.apache.shiro目录下的类而不是org.apache.shiro.guice)。然而Guice只显式地绑定TypeListeners类型的,如果你想要注入一个Shiro对象你必须显式地声明它。例如,如果想为一个realm设置CredentialsMatcher,需要添加以下的绑定:
bind(CredentialsMatcher.class).to(HashedCredentialsMatcher.class); bind(HashedCredentialsMatcher.class); bindConstant().annotatedWith(Names.named("shiro.hashAlgorithmName")).to(Md5Hash.ALGORITHM_NAME); |