在 Spring 中启用 Apache Shiro 注释时找不到 Spring Data JPA 存储库
问题就在这里。
我有 spring 3.0.5,使用其新的 DATA JPA 存储库模块(扩展接口 CrudRepository
)。
我有 Apache Shiro 1.1.0 作为我的应用程序的安全解决方案。 Apache shiro 已配置 在 spring bean 定义 xml 文件中,如下所示:
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- Define the realm you want to use to connect to your back-end security datasource: -->
<bean id="securityDAORealm" class="com.bilto.archiweb.security.SecurityDAORealm" />
<bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property instead. -->
<property name="realm" ref="securityDAORealm"/>
</bean>
<!-- For simplest integration, so that all SecurityUtils.* methods work in all cases, -->
<!-- make the securityManager bean a static singleton. DO NOT do this in web -->
<!-- applications - see the 'Web Applications' section below instead. -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
<property name="arguments" ref="securityManager"/>
</bean>
请注意,我的应用程序是一个独立的应用程序,此 Apachoe Shiro 配置反映了它。
spring jpa 存储库的配置以及标准 spring 配置(注释扫描)是在其他文件中配置的,它们似乎与此问题无关,因此我将跳过打印它们。
我的 SecurityDAORealm 类自动装配 CredentialsRepository 作为其 jpa 存储库控制器接口(CredentialsRepository extends CrudRepository
),用于访问存储凭据的数据库。
@Component
public class SecurityDAORealm extends AuthorizingRealm {
@Autowired
CredentialRepository credentialRepository;
...
}
现在来说说问题。
配置 Apache Shiro 注释扫描时,找不到 CredentialsRepository 类型的自动装配 bean,因此未装配。当注释扫描关闭时,CredentialsRepository 变量会自动连接并且一切正常。
能够进行 Apache Shiro 注释处理的部分是这样,
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
通过注释掉其中心注释
<!-- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/> -->
,注释将被关闭,取消注释将再次打开它们。
作为测试,我尝试自动连接一个简单的 pojo 而不是我的 CredentialsRepository
,这在两种情况下都效果很好(注释打开/关闭)。
我对 Spring 的内部结构了解不多。这里可能发生的情况是,CredentialsRepository
变量没有自动连接,因为 Spring 没有机会在其后端创建其适当的实现 (SimpleJpaRepository
)。
这里的解决方法只是通过自动连接一些“全类”JPA 控制器而不是 spring 管理的接口实现。
然而我很好奇这是否是一个需要修复的错误,或者这里是否存在一些额外的 spring 魔法可以使其也可以与 spring 数据接口一起使用。
Here is the problem.
I have spring 3.0.5, using its new DATA JPA repository module (interfaces extendingCrudRepository<T, ID extends Serializable>
).
I have Apache Shiro 1.1.0 as a security solution for my app. Apache shiro is configured
in the spring bean defintion xml file as follows:
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
<!-- Define the realm you want to use to connect to your back-end security datasource: -->
<bean id="securityDAORealm" class="com.bilto.archiweb.security.SecurityDAORealm" />
<bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">
<!-- Single realm app. If you have multiple realms, use the 'realms' property instead. -->
<property name="realm" ref="securityDAORealm"/>
</bean>
<!-- For simplest integration, so that all SecurityUtils.* methods work in all cases, -->
<!-- make the securityManager bean a static singleton. DO NOT do this in web -->
<!-- applications - see the 'Web Applications' section below instead. -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
<property name="arguments" ref="securityManager"/>
</bean>
Please note that my app is a standalone application and this Apachoe Shiro configuration reflects it.
Configuration for spring jpa repositories as well as standard spring configurations (annotations scanning) is configured in others files, they do not seem to be relevant for this problem, so i will skip printing them.
My SecurityDAORealm
class is autowiring CredentialsRepository
as its jpa repository controller interface (CredentialsRepository extends CrudRepository<T, ID extends Serializable>
) that serves for accessing the database where credentials are stored.
@Component
public class SecurityDAORealm extends AuthorizingRealm {
@Autowired
CredentialRepository credentialRepository;
...
}
Now for the problem.
When Apache Shiro annotation scanning is configured, the autowired bean of type CredentialsRepository
is not found and thus not wired. When annotation scanning is turned off CredentialsRepository variable is autowired and all works properly.
The part that anables Apache Shiro annotation processing is this
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
By commenting out its central peace
<!-- <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/> -->
Annotations are turned off, uncommenting it will switch them on again.
As a test I tried to auto-wire a simple pojo instead of my CredentialsRepository
, this works well in both cases (annotations on/off).
I do not see much into spring internals. What might be happening here is that the CredentialsRepository
variable is not getting auto-wired as Spring does not get a chance to create its appropriate implementation (SimpleJpaRepository
) on its backend.
The workaround exist here simply by auto-wiring some "full class" JPA controller instead of a spring managed interface implementation.
However I am curious whether this is a bug that need to be fixed or whether some additional spring magic exist here that could make it work also with spring data interfaces.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我遇到了同样的问题。
我的解决方法是使 securityManager 依赖于需要注入的存储库。因此,在你的情况下:
I came accross the same issue.
My workaround is to make the securityManager depend on the Repository which needs to be injected. Thus, in your case:
我也遇到过类似的情况,我没有使用 shiro 来实现安全性,但我正在使用 spring security。
当我自动装配时,由于在组件扫描 spring-data @Repository 之前初始化了 spring security beans,因此无法正确注入。由于 Spring Security 需要在容器启动时进行初始化,以便设置 Servlet 过滤器等,因此我必须在 Spring Security 之前连接我的存储库,以便进行正确的注入。
知道这不完全是您的情况,但也许会有所帮助!
另外,最令人困惑的部分,也是导致我解决问题的原因,我设置了一个单元测试,@Autowired UserDetailsService,其中已将存储库注入其中,并且单元测试工作正常。让我相信这是豆子设置方式的排序问题。
I had a similar situation with this, I'm not using shiro to do security, but I'm using spring security.
When I autowired, it wasn't injecting correctly due to spring security beans being initialized before the component scan for the spring-data @Repository. Since spring security needs to be initialized with the startup of the container in order to set up servlet filters and such, I had to wire my repositories before spring security in order for proper injection to take place.
Know this isn't exactly your situtation, but maybe it will help!
Also, the most confusing part, and what led me to my solution to the problem, I set up a unit test that @Autowired the UserDetailsService which has the repository injected into it, and the unit test worked fine. Led me to believe it was an ordering problem with the way the beans were being setup.