【发布时间】:2014-07-28 22:17:17
【问题描述】:
我正在尝试将 Spring-Security 4.0.0.M1 与 Spring-Boot 1.0.2.RELEASE 与 H2 和 Spring-data-jpa.1.5.2 一起使用。我可以在 SecurityConfig.configure 方法中创建一个用户,但是当我将它提取到它自己的类中时,我得到一个空指针异常。我进入 JdbcDaoSupport.java 并看到 getJdbcTemplate() 返回一个 null jdbcTemplate。
这是我的配置:
@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = false)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/resources/**" ).permitAll()
.antMatchers( "/css/**" ).permitAll();
http
.formLogin().failureUrl( "/login?error" )
.defaultSuccessUrl( "/" )
.loginPage( "/login" )
.permitAll()
.and()
.logout().logoutRequestMatcher( new AntPathRequestMatcher( "/logout" ) ).logoutSuccessUrl( "/login" )
.permitAll();
http
.authorizeRequests().anyRequest().authenticated();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource( dataSource );
}
@Bean
@Override
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManagerBean();
}
}
我的主要配置类定义了数据源,我知道它可以工作:
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType( EmbeddedDatabaseType.H2 ).setName( "ofac" )
.addScript( "classpath:h2.sql" ).build();
}
我有一个用于添加用户的用户服务:
@Component
public class UserService {
@Autowired
private AuthenticationManagerBuilder authenticationManagerBuilder;
@Autowired
private javax.sql.DataSource dataSource;
@PostConstruct()
public void initUsers() throws Exception {
addNewUser( "admin", "password", "ADMIN" );
}
public void addNewUser(String username, String plainPassword, String role) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add( new SimpleGrantedAuthority( role ) );
PasswordEncoder encoder = new BCryptPasswordEncoder();
UserDetails hashedUser = new User( username, encoder.encode( plainPassword ), authorities );
JdbcUserDetailsManager userDetailsService = (JdbcUserDetailsManager) authenticationManagerBuilder.getDefaultUserDetailsService();
try {
if ( userDetailsService.userExists( hashedUser.getUsername() ) ) {
userDetailsService.deleteUser( hashedUser.getUsername() );
}
// and finally, create the user
userDetailsService.createUser( hashedUser );
} catch ( Exception ex ) {
ex.printStackTrace();
}
}
}
我在 UserService.initUsers 上有一个断点,当行:
authenticationManagerBuilder.jdbcAuthentication().getUserDetailsService().userExists( hashedUser.getUsername() )
被调用,我可以看到authenticationManagerBuilder.jdbcAuthentication() 返回一个空的jdbcTemplate。所有在线文档似乎都表明这会起作用,但它似乎并没有像我期望的那样连接所有东西。
有谁知道可能出了什么问题?
更新: 我更改了项目,所以我不再拥有 SecurityConfig,而是拥有一个:
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@Configuration
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/resources/**" ).permitAll()
.antMatchers( "/css/**" ).permitAll();
http
.formLogin().failureUrl( "/login?error" )
.defaultSuccessUrl( "/" )
.loginPage( "/login" )
.permitAll()
.and()
.logout().logoutRequestMatcher( new AntPathRequestMatcher( "/logout" ) ).logoutSuccessUrl( "/login" )
.permitAll();
http
.authorizeRequests().anyRequest().authenticated();
}
}
还有一个:
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
public class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource( dataSource );
}
}
但是在我的 UserService 中,我在这里得到了一个 null userDetailsService:
JdbcUserDetailsManager userDetailsService = (JdbcUserDetailsManager) authenticationManagerBuilder.getDefaultUserDetailsService();
我还没有弄清楚如何在启动后实际创建用户。我认为它与 UserDetailsService 一起使用,但它不提供该功能。我想可能需要一个 JdbcUserDetailsManager,但到目前为止,我还无法连接一个有效的方法。
【问题讨论】:
-
我认为如果您想在两个地方共享用户详细信息服务,您应该将其定义为 bean。注入 auth mgr 构建器并不打算以这种方式工作。
标签: spring-security spring-boot