【发布时间】:2016-11-01 10:08:38
【问题描述】:
我正在我的 Spring 项目中配置安全性,不幸的是我遇到了问题。为什么 CustomUserDetailsService.java 中自动装配的 userDAO 为空?
这里是有问题的代码:
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);
...
}
}
spring-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" />
编辑:
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的配置文件中的sn-p代码:
@Bean
public UserDAO getUserDAO() {
return new UserDAOImpl(getDataSource());
}
不过,有趣的是,这种配置似乎有点工作。当我将 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");
...
}
我已经阅读了一些问答,但到目前为止,它涉及自定义 UserDetailsService 的手动实例化。我的代码有什么问题?
【问题讨论】:
-
是否正在扫描?
-
java配置?是的。当我 testwise 将 DAO 自动连接到我的主控制器(与所有其他 DAO 相同)时,它不为空并且工作正常(按预期返回用户)。它在 CustomUserDetailsService.java 中仅为空。
-
方法
getUserDAO()在哪里存在? -
是java配置文件。是的,我的项目同时配置了xml和java。
-
在
CustomUserDetailsService处执行@ComponentScan可能会清除Spring Bean Pool 中先前扫描的项目。但是您仍然可以从控制器访问UserDAO,因为它在通过Configuration创建时已经被注入。无论如何,我不确定这一点。您不应该在常规组件上执行@ComponentScan。要么将其放入您的 Java 配置中,要么将其作为<context:component-scan>添加到 xml。
标签: spring spring-security autowired