2016-11-01 3 views
0

Я настраиваю безопасность в своем проекте Spring и, к сожалению, у меня возникла проблема. Почему autwired userDAO в CustomUserDetailsService.java null?Spring: autowired DAO имеет значение null в пользовательской реализации UserServiceDetails

Вот код в вопросе:

CustomUserDetailsService.java

@Service("customUserDetailsService") 
@ComponentScan(basePackages="...") 
public class CustomUserDetailsService implements UserDetailsService { 

    @Autowired 
    private UserDAO userDAO; 

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 

     // userDAO is null 
     UserModel user = userDAO.getUserByUsername(username); 
     ... 
    } 
} 

весна-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security-3.2.xsd"> 

<http pattern="/resources/**" security="none"/> 
<http pattern="/login" security="none"/> 

<http auto-config="true"> 
    <intercept-url pattern="/**" access="ROLE_USER" /> 
    <form-login 
     login-page="/login" 
     default-target-url="/home" 
     authentication-failure-url="/login?error" 
     username-parameter="username" 
     password-parameter="password" /> 
    <logout logout-success-url="/login?logout" /> 
</http> 

<authentication-manager> 
    <authentication-provider user-service-ref="customUserDetailsService"> 
     <password-encoder ref="encoder" /> 
    </authentication-provider> 
</authentication-manager> 

<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"> 
    <beans:constructor-arg name="strength" value="10" /> 
</beans:bean> 

<beans:bean id="customUserDetailsService" class="... .service.CustomUserDetailsService" /> 

Edit:

UserDAOImpl.java

public class UserDAOImpl implements UserDAO { 

private JdbcTemplate jdbcTemplate; 

public UserDAOImpl(DataSource dataSource) { 
    jdbcTemplate = new JdbcTemplate(dataSource); 
} 

    public UserModel getUserByUsername(String username) { 

     String sql = "SELECT * FROM users WHERE username = '" + username + "'"; 

     return jdbcTemplate.query(sql, new ResultSetExtractor<UserModel>() { 

      public UserModel extractData(ResultSet rs) throws SQLException, DataAccessException { 
       if (rs.next()) { 
        UserModel user = new UserModel(); 
        user.setUsername(rs.getString("username")); 
        user.setPassword(rs.getString("passwort")); 
        user.setEnabled(rs.getBoolean("enabled")); 

        return user; 
       } 
       return null; 
      } 
     }); 
    } 
} 

Вот фрагмент кода в файле конфигурации Java на основе:

@Bean 
public UserDAO getUserDAO() { 
    return new UserDAOImpl(getDataSource()); 
} 

Интересно, хотя, эта конфигурация, кажется, своего рода за работой. Когда я autowire в UserDAO в мой контроллер, он отлично работает:

MainController.java

@RequestMapping(value = {"", "/", "/home"}) 
public String homeHandler(Model model) { 

    // userDAO is not null, works perfectly fine and returns the UserModel-Object as expected 
    UserModel user = userDAO.getUserByUsername("dx"); 

    ... 
} 

Я уже прочитал некоторые Q & А, но до сих пор это касалось ручной instatiation пользовательского UserDetailsService. Что не так с моим кодом?

+0

Отсканировано ли это? –

+0

Конфигурация java? Да. Когда я тестирую autowire DAO на мой основной контроллер (так же, как и каждый другой DAO), он не является нулевым и работает нормально (возвратите пользователя, как ожидалось). Это только null в CustomUserDetailsService.java. –

+0

Где находится метод 'getUserDAO()'? – sura2k

ответ

1

Проблема заключается в том, что вы создаете объект customUserDetailsService в двух разных местах. У вас есть определение <bean> в файле spring-security.xml, а также у вас есть @Service аннотация по самому классу. В вашем определении бина вы не вводите UserDAO так, чтобы он был нулевым.

Вам необходимо оптимизировать проект, чтобы очистить определение компонента в конфигурациях java или XML-файлах (это не требуется, и вы можете иметь конфигурацию XML + java, но тогда это делает ее очень запутанной относительно того, что создает экземпляр этого компонента) , У вас мало вариантов;

  1. Удалите декларацию XML от CustomUserDetailsService. Добавьте <context:component-scan> в свой XML и добавьте имена пакетов, а также удалите @ComponentScan из CustomUserDetailsService. Это позволит весне сканировать пакеты и регистрировать компоненты, отмеченные @Service, @Bean и т. Д. Аннотации. Убедитесь, что ваш класс конфигурации java отмечен аннотацией @Configuration.

  2. Вы можете принять решение использовать XML-конфигурацию для всех бобов, в этом случае вам нужно удалить @Bean, @Service и т.д. аннотации и объявить их все в определении весной XML боба и убедитесь, что каждый из них имеет собственные зависимости впрыскивается.

Вам обязательно нужно очистить свои определения бобов, чтобы вставлять правильные зависимости.

0

Благодарим за ответы. Ответ Сету был самым полезным. Очевидно, проблема была действительно двойным экземпляром. Я добавил <context:component-scan base-package="... .service" /> и оставил обе аннотации @Service("customUserDetailsService") и @ComponentScan(basePackages="...") в CustomUserDetailsService (без @ComponentScan он не работал).