shiro配置 AOP式方法级权限检查时 事务失效
当对shiro配置 AOP式方法级权限检查时:
<!-- AOP式方法级权限检查 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
执行删除操作时(删除用户,同时删除用户下的任务)会报错:
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:154)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:55)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:95)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:85)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:313)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
具体错误语句,我测试过应该是:
taskDao.deleteByUserId(id);
@Modifying
@Query("delete from Task task where task.user.id = :id")
void deleteByUserId(@Param("id") Long id);
如果修改为:taskDao.delete(id); delete(id)是JPA DATA中的方法,不会报错。
不配置AOP式方法级权限检查,也不会报错。
在quickstart和showcase都会存在,配置方法和showcase一模一样,showcase虽然有这个例子,也不会报错,但可惜这种情况,属于我的上面举的不报错的情况,调用的是JPA自带的delete方法。希望作者能看一下,看看是什么问题,也希望大家能解决一下。经过我测试,是不是JPA DATA 和 shior AOP式方法级权限检查有冲突,导致事务失效!!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
引用来自“飘渺青衣”的评论
realm先不注入securityManager里,然后我写了一个事件,然后事物好用了
@Component
public class ShiroInitListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private Collection<Realm> realms;
@Resource
private RealmSecurityManager securityManager;
/* (non-Javadoc)
*
@see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
@Override
public void onApplicationEvent(ContextRefreshedEvent arg0) {
if(this.realms != null && this.securityManager != null) {
securityManager.setRealms(realms);
}
}
}
realm先不注入securityManager里,然后我写了一个事件,然后事物好用了
@Component
public class ShiroInitListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private Collection<Realm> realms;
@Resource
private RealmSecurityManager securityManager;
/* (non-Javadoc)
*
@see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
@Override
public void onApplicationEvent(ContextRefreshedEvent arg0) {
if(this.realms != null && this.securityManager != null) {
securityManager.setRealms(realms);
}
}
}
意思就是在spring-shiro.xml中不配置realm,而是在spring监听完成后把realm设置到securityManager。
求解啊 。。。。
The root cause of the issue is in fact due to the following:
All BeanPostProcessors and their directly referenced beans will be instantiated on startup... Since AOP auto-proxying is implemented as a BeanPostProcessor itself, no BeanPostProcessors or directly referenced beans are eligible for auto-proxying (and thus will not have aspects 'woven' into them.
Referenced SO question is here.
I have resolved this issue by decoupling the Realm bean creation from the SecurityManager bean creation.
The relevant change is from the following code:
to the following code:
Then I use a ServletContextListener which listens to when the Spring context initialization completes and I have the both the MainRealm and SecurityManager beans. Then I just plug one bean inside another.
没太看懂怎么解决
现在肯定的是与shiro有关
我也遇到了这个问题,不知道楼主有没有解决?
自己顶