Spring Security 3:问题自动装配UserDetailsManager / JdbcUserDetailsManager

时间:2010-08-24 00:43:02

标签: java security spring

我正在使用Peter Mularien的Spring Security 3,并且在设置UserDetailsManager时遇到了问题。

我按如下方式创建JdbcUserDetailsManager bean:

<bean id="jdbcUserService" class="org.springframework.security.provisioning.JdbcUserDetailsManager">
    <property name="dataSource" ref="mySqlDb" />
    <property name="authenticationManager" ref="authenticationManager" />
</bean>

并在我的控制器中自动装配其UserDetailsManager接口,如下所示:

@Autowired
public UserDetailsManager userDetailsManager;

当我启动应用程序进行测试时,我得到以下异常:

Error creating bean with name 'changePasswordController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.security.provisioning.UserDetailsManager com.ebisent.web.ChangePasswordController.userDetailsManager; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.security.provisioning.UserDetailsManager] is defined: expected single matching bean but found 2: [org.springframework.security.provisioning.JdbcUserDetailsManager#0, jdbcUserService]

我搜索了我的项目,看看我是否可能在其他地方设置了(Jdbc)UserDetailsManager,但我似乎没有这样做。如果我删除bean定义中的“id”属性,那么歧义就在JdbcUserDetailsManager#0和JdbcUserDetailsManager#1之间。

我的web.xml在两个地方引用了app-config.xml:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>WEB-INF/spring/app-config.xml</param-value>
</context-param>

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/spring/app-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

3 个答案:

答案 0 :(得分:3)

指定app-config.xml两次肯定存在问题,但这不是最初陈述的问题的答案。

看来Spring基于类型自动装配。 bean使用类JdbcUserDetailsManager定义,该类实现UserDetailsManager

在我的控制器中,我正在自动连接接口UserDetailsManager。 Spring发现界面两次,并抱怨它不知道要选哪个。

添加@Qualifier注释可以解决问题。以下是它现在的样子:

@Autowired
@Qualifier("jdbcUserService")  // <-- this references the bean id
public UserDetailsManager userDetailsManager;

答案 1 :(得分:2)

罗伯特, 是。您的web.xml所说的是创建指向app-config.xml父级的app-config.xml的Web应用程序上下文。这意味着你有两个每个bean的副本 - 正如你所注意到的那样是不正确的。

答案 2 :(得分:0)

这似乎可以解决问题:

  1. 评论“jdbcUserService”
  2. 插入:

    <authentication-manager alias="authenticationManager">
                <authentication-provider>
                <jdbc-user-service data-source-ref="dataSource"/>
                </authentication-provider> 
                </authentication-manager>
    
  3. 创建数据源:

        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost/secureApp"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
    </bean>
    
  4. 根据您使用的数据源创建nessecary配置(在本例中为MySQL)。如果您使用的是hibernate或jpa,请创建任何其他配置...

  5. 运行服务器。

  6. 我今天能够重现这一点。使用更改的密码更新数据库。似乎身份验证管理器已经实例化了一个JdbcUserDetailsManager ??