今天研究了下shiro注解的使用,碰到了一些问题,因此将问题的解决方案记录下来。
首先需要申明的是,项目环境使用的是 SSH2框架,并且只启动了shiro的注解。
首先看下shiro给的Demo中如何开启对注解的支持:
<!-- 配置这个Bean后,对于在spring配置文件中配置的shiro对象,会自动调用用init()方法和destory()方法。 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 启用shiro注解的支持 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<!-- securityManager的配置这里没有给出 -->
<property name="securityManager" ref="securityManager"/>
</bean>
本以为这样配置好后,就没有什么问题了,谁项目启动后会报错, java.lang.NoSuchMethodException: com.sun.proxy.$Proxy25.test()
想必大家也看出来了,异常为找不到方法,而且这个方法还是代理方法。
仔细想下,我的Action没有实现Action接口,而是继承了ActionSupport类,因此才会触发这个异常,因此,我选择使用动态代理,具体配置如下:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<!-- 使用动态代理 -->
<property name="proxyTargetClass" value="true"></property>
</bean>
修改好配置文件后,重启项目后,项目依然会报错,而且还是
java.lang.NoSuchMethodException: com.sun.proxy.$Proxy25.test()
经过对配置文件的一翻查看,我发现了在hibernate有关的配置中,我配置了事务切面:
<aop:config >
<aop:pointcut id="serviceMethod" expression="execution(* dao.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
</aop:config>
尝试着将hibernate的切面改为使用动态代理:
<aop:config proxy-target-class="true">
<aop:pointcut id="serviceMethod" expression="execution(* dao.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
</aop:config>
重新启动项目,一切看似都没问题,但是调用使用了shiro注解的action后,即使在shiroFilter中配置了unauthorizedUrl属性,结果依然没有按预想的那样跳转到指定url,而是在页面直接显示出了异常信息,如:
Struts has detected an unhandled exception:
Messages: |
|
下面给出我的解决方案:
在struts.xml中配置异常映射,如:
<package abstract="true" name="mine" namespace="/" extends="struts-default">
<global-results>
<!-- 如果用户没有验证,要跳转的页面 -->
<result name="unauthorized">/unauthorized.jsp</result>
<!-- 如果用户没有相应的角色或权限,要跳转的页面 -->
<result name="unAuthenticated">/login.jsp</result>
</global-results>
<global-exception-mappings>
<!-- 映射没有权限异常 -->
<exception-mapping result="unauthorized" exception="org.apache.shiro.authz.UnauthorizedException" />
<!-- 映射没有验证异常 -->
<exception-mapping result="unAuthenticated" exception="org.apache.shiro.authz.UnauthenticatedException" />
</global-exception-mappings>
</package>
注意这里的myPackage为abstract的,也就只中间不能配置action的,但是,我们可以新创建一个package,继承自myPackage,及 extends="myPackage"。
至此,问题基本解决,但是,对于hibernate的事务切面,使用动态代理感觉很不爽,于是,多折腾了会儿,找到了解决办法,下面给出解决方案:
在 org.apache.shiro.spring.security.interceptor 包下有一个 AopAllianceAnnotationsAuthorizingMethodInterceptor 类,因此,可以推测出,可以使用该类进行 aop 配置,配置如下:
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<aop:config proxy-target-class="true">
<aop:pointcut expression="execution(* action.*.*(..))" id="shiroPincut"/>
<aop:advisor advice-ref="shiroAdvisor" pointcut-ref="shiroPincut" />
</aop:config>
<bean name="shiroAdvisor" class="org.apache.shiro.spring.security.interceptor.AopAllianceAnnotationsAuthorizingMethodInterceptor" depends-on="lifecycleBeanPostProcessor" />
配置完shiro后,可以将hibernate的切面配置中的 proxy-target-class="true" 属性删除。
至此,shiro注解成功开启!